Issues (7)

src/Job.php (2 issues)

Severity
1
<?php
2
declare(strict_types=1);
3
4
namespace MyTester;
5
6
use Ayesh\PHP_Timer\Timer;
7
use Psr\EventDispatcher\EventDispatcherInterface;
8
use Throwable;
9
use TypeError;
10
11
/**
12
 * One job of a test suite
13
 *
14
 * @author Jakub Konečný
15
 * @property-read callable $callback
16
 * @property-read bool|string $skip
17
 * @property-read JobResult $result
18
 * @property-read string $output @internal
19
 * @property-read int $totalTime Total elapsed time in milliseconds
20
 * @property-read Throwable|null $exception
21
 * @property-read string $nameWithDataSet Job's name + data set (or its custom name)
22
 */
23
final class Job
24
{
25
    use \Nette\SmartObject;
26
27
    /** @var callable Task */
28
    private $callback;
29
    private JobResult $result = JobResult::PASSED;
30
    private string $output = "";
31
    /** @var int Total elapsed time in milliseconds */
32
    private int $totalTime = 0;
33
    /**
34
     * @internal
35
     */
36
    public int $totalAssertions = 0;
37
    private Throwable|null $exception = null;
38
    private EventDispatcherInterface $eventDispatcher;
39
40
    /**
41
     * @param mixed[] $params
42
     * @param callable[] $onAfterExecute
43
     */
44 1
    public function __construct(
45
        public readonly string $name,
46
        callable $callback,
47
        public readonly array $params = [],
48
        private bool|string $skip = false,
49
        public array $onAfterExecute = [],
50
        public readonly string $dataSetName = "",
51
        public readonly bool $reportDeprecations = true
52
    ) {
53 1
        if (count($this->onAfterExecute) > 0) {
54
            trigger_error("Using " . self::class . "::]\$onAfterExecute is deprecated, add a listener for event " . Events\TestJobFinished::class . " instead", E_USER_DEPRECATED);
0 ignored issues
show
Line exceeds 120 characters; contains 179 characters
Loading history...
55
        }
56 1
        $this->callback = $callback;
57 1
    }
58
59
    protected function getCallback(): callable
60
    {
61 1
        return $this->callback;
62
    }
63
64
    protected function getSkip(): bool|string
65
    {
66 1
        return $this->skip;
67
    }
68
69
    protected function getResult(): JobResult
70
    {
71 1
        return $this->result;
72
    }
73
74
    protected function getOutput(): string
75
    {
76 1
        return $this->output;
77
    }
78
79
    protected function getTotalTime(): int
80
    {
81 1
        return $this->totalTime;
82
    }
83
84
    protected function getException(): ?\Throwable
85
    {
86 1
        return $this->exception;
87
    }
88
89
    protected function getNameWithDataSet(): string
90
    {
91 1
        $jobName = $this->name;
92 1
        if (count($this->params) > 0) {
93 1
            $jobName .= " with data set ";
94 1
            if ($this->dataSetName !== "") {
95 1
                $jobName .= $this->dataSetName;
96
            } else {
97 1
                $jobName .= "(" . implode(", ", $this->params) . ")";
98
            }
99
        }
100 1
        return $jobName;
101
    }
102
103
    /**
104
     * @internal
105
     */
106
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void
107
    {
108 1
        $this->eventDispatcher = $eventDispatcher;
109 1
    }
110
111
    /**
112
     * @deprecated
113
     */
114
    private function onAfterExecute(): void
115
    {
116 1
        foreach ($this->onAfterExecute as $callback) {
117
            $callback($this);
118
        }
119 1
    }
120
121
    /**
122
     * Executes the task
123
     */
124
    public function execute(): void
0 ignored issues
show
Function's cyclomatic complexity (13) exceeds 10; consider refactoring the function
Loading history...
125
    {
126 1
        if ($this->skip === false) {
127 1
            $timerName = $this->name . time();
128 1
            Timer::start($timerName);
129 1
            ob_start();
130 1
            set_error_handler(
131 1
                function (int $errno, string $errstr, string $errfile, int $errline): bool {
132 1
                    if ($this->reportDeprecations) {
133 1
                        $this->eventDispatcher->dispatch(new Events\DeprecationTriggered($errstr, $errfile, $errline));
134
                    }
135 1
                    return true;
136 1
                },
137 1
                E_USER_DEPRECATED
138
            );
139
            try {
140
                try {
141 1
                    call_user_func_array($this->callback, $this->params);
142 1
                } catch (TypeError $e) {
143
                    if (
144
                        isset($e->getTrace()[0]) &&
145
                        isset($e->getTrace()[0]["class"]) && $e->getTrace()[0]["class"] === TestCase::class &&
146
                        isset($e->getTrace()[0]["function"]) && str_starts_with($e->getTrace()[0]["function"], "assert")
147
                    ) {
148
                        /** @var array{0: TestCase, 1: string}&callable $callback */
149
                        $callback = $this->callback;
150
                        throw new AssertionFailedException(
151
                            "Invalid value passed to an assertion.",
152
                            $callback[0]->getCounter() + 1,
153
                            $e
154
                        );
155
                    }
156 1
                    throw $e;
157
                }
158 1
            } catch (SkippedTestException $e) {
159 1
                $this->skip = ($e->getMessage() !== "") ? $e->getMessage() : true;
160 1
            } catch (IncompleteTestException $e) {
161 1
                $message = $e->getMessage() !== "" ? $e->getMessage() : "incomplete";
162 1
                echo "Warning: $message\n";
163 1
            } catch (AssertionFailedException $e) {
164 1
                echo $e->getMessage();
165 1
                $this->exception = $e;
166 1
            } catch (Throwable $e) {
167 1
                echo "Error: " . ($e->getMessage() !== "" ? $e->getMessage() : $e::class) . "\n";
168 1
                echo "Trace:\n" . $e->getTraceAsString() . "\n";
169 1
                $this->exception = $e;
170
            }
171 1
            if (is_array($this->callback) && isset($this->callback[0]) && $this->callback[0] instanceof TestCase) {
172 1
                $this->totalAssertions = $this->callback[0]->getCounter();
173
            }
174 1
            $this->eventDispatcher->dispatch(new Events\TestJobFinished($this));
175 1
            $this->onAfterExecute(); // @phpstan-ignore method.deprecated
176 1
            restore_error_handler();
177 1
            $this->output = (string) ob_get_clean();
178 1
            Timer::stop($timerName);
179
            // @phpstan-ignore argument.type, cast.int
180 1
            $this->totalTime = (int) Timer::read($timerName, Timer::FORMAT_PRECISE);
181
        }
182 1
        $this->result = JobResult::fromJob($this);
183 1
    }
184
}
185