From 97898a0a8e625821c3bf34222cfad0cfa57d81b6 Mon Sep 17 00:00:00 2001 From: Nuno Maduro Date: Mon, 1 May 2023 22:18:45 +0100 Subject: [PATCH] feat: allows to use test calls on before each calls --- composer.json | 2 +- src/Concerns/Testable.php | 2 +- src/Functions.php | 2 +- src/PendingCalls/BeforeEachCall.php | 33 ++++++++++++++----- src/PendingCalls/TestCall.php | 7 ++-- src/Repositories/BeforeEachRepository.php | 17 +++++++--- src/Support/Backtrace.php | 4 +-- tests/.snapshots/success.txt | 18 +++++++++- tests/.snapshots/todo.txt | 8 ++++- ...eEachProxiesToTestCallWithExpectations.php | 15 +++++++++ .../BeforeEachProxiesToTestCallWithSkip.php | 15 +++++++++ .../BeforeEachProxiesToTestCallWithTodo.php | 15 +++++++++ tests/Visual/Parallel.php | 2 +- tests/Visual/Todo.php | 4 ++- 14 files changed, 118 insertions(+), 26 deletions(-) create mode 100644 tests/Features/BeforeEachProxiesToTestCallWithExpectations.php create mode 100644 tests/Features/BeforeEachProxiesToTestCallWithSkip.php create mode 100644 tests/Features/BeforeEachProxiesToTestCallWithTodo.php diff --git a/composer.json b/composer.json index 33b08310..91ca38d9 100644 --- a/composer.json +++ b/composer.json @@ -50,7 +50,7 @@ }, "require-dev": { "pestphp/pest-dev-tools": "^2.7.0", - "symfony/process": "^6.2.8" + "symfony/process": "^6.2.10" }, "minimum-stability": "stable", "config": { diff --git a/src/Concerns/Testable.php b/src/Concerns/Testable.php index a973d132..ce020c3a 100644 --- a/src/Concerns/Testable.php +++ b/src/Concerns/Testable.php @@ -181,7 +181,7 @@ trait Testable parent::setUp(); - $beforeEach = TestSuite::getInstance()->beforeEach->get(self::$__filename); + $beforeEach = TestSuite::getInstance()->beforeEach->get(self::$__filename)[1]; if ($this->__beforeEach instanceof Closure) { $beforeEach = ChainableClosure::from($this->__beforeEach, $beforeEach); diff --git a/src/Functions.php b/src/Functions.php index ede5141c..0145219e 100644 --- a/src/Functions.php +++ b/src/Functions.php @@ -43,7 +43,7 @@ if (! function_exists('beforeEach')) { /** * Runs the given closure before each test in the current file. * - * @return HigherOrderTapProxy|TestCall|mixed + * @return HigherOrderTapProxy|TestCall|TestCase|mixed */ function beforeEach(Closure $closure = null): BeforeEachCall { diff --git a/src/PendingCalls/BeforeEachCall.php b/src/PendingCalls/BeforeEachCall.php index 450a0313..2a2fb5f8 100644 --- a/src/PendingCalls/BeforeEachCall.php +++ b/src/PendingCalls/BeforeEachCall.php @@ -19,12 +19,17 @@ final class BeforeEachCall /** * Holds the before each closure. */ - private readonly \Closure $closure; + private readonly Closure $closure; /** - * The calls that should be proxied. + * The test call proxies. */ - private readonly HigherOrderMessageCollection $proxies; + private readonly HigherOrderMessageCollection $testCallProxies; + + /** + * The test case proxies. + */ + private readonly HigherOrderMessageCollection $testCaseProxies; /** * Creates a new Pending Call. @@ -36,7 +41,8 @@ final class BeforeEachCall ) { $this->closure = $closure instanceof Closure ? $closure : NullClosure::create(); - $this->proxies = new HigherOrderMessageCollection(); + $this->testCallProxies = new HigherOrderMessageCollection(); + $this->testCaseProxies = new HigherOrderMessageCollection(); } /** @@ -44,13 +50,16 @@ final class BeforeEachCall */ public function __destruct() { - $proxies = $this->proxies; + $testCaseProxies = $this->testCaseProxies; $this->testSuite->beforeEach->set( $this->filename, - ChainableClosure::from(function () use ($proxies): void { - $proxies->chain($this); - }, $this->closure) + function (TestCall $testCall): void { + $this->testCallProxies->chain($testCall); + }, + ChainableClosure::from(function () use ($testCaseProxies): void { + $testCaseProxies->chain($this); + }, $this->closure), ); } @@ -61,7 +70,13 @@ final class BeforeEachCall */ public function __call(string $name, array $arguments): self { - $this->proxies + if (method_exists(TestCall::class, $name)) { + $this->testCallProxies->add(Backtrace::file(), Backtrace::line(), $name, $arguments); + + return $this; + } + + $this->testCaseProxies ->add(Backtrace::file(), Backtrace::line(), $name, $arguments); return $this; diff --git a/src/PendingCalls/TestCall.php b/src/PendingCalls/TestCall.php index 347f3daf..79885fbf 100644 --- a/src/PendingCalls/TestCall.php +++ b/src/PendingCalls/TestCall.php @@ -40,12 +40,15 @@ final class TestCall */ public function __construct( private readonly TestSuite $testSuite, - string $filename, + private readonly string $filename, string $description = null, Closure $closure = null ) { $this->testCaseMethod = new TestCaseMethodFactory($filename, $description, $closure); + $this->descriptionLess = $description === null; + + $this->testSuite->beforeEach->get($filename)[0]($this); } /** @@ -167,7 +170,7 @@ final class TestCall $this->testCaseMethod ->chains - ->addWhen($condition, Backtrace::file(), Backtrace::line(), 'markTestSkipped', [$message]); + ->addWhen($condition, $this->filename, Backtrace::line(), 'markTestSkipped', [$message]); return $this; } diff --git a/src/Repositories/BeforeEachRepository.php b/src/Repositories/BeforeEachRepository.php index 0e800a79..e74f78ed 100644 --- a/src/Repositories/BeforeEachRepository.php +++ b/src/Repositories/BeforeEachRepository.php @@ -14,27 +14,34 @@ use Pest\Support\NullClosure; final class BeforeEachRepository { /** - * @var array + * @var array */ private array $state = []; /** * Sets a before each closure. */ - public function set(string $filename, Closure $closure): void + public function set(string $filename, Closure $beforeEachTestCall, Closure $beforeEachTestCase): void { if (array_key_exists($filename, $this->state)) { throw new BeforeEachAlreadyExist($filename); } - $this->state[$filename] = $closure; + $this->state[$filename] = [$beforeEachTestCall, $beforeEachTestCase]; } /** * Gets a before each closure by the given filename. + * + * @return array{0: Closure, 1: Closure} */ - public function get(string $filename): Closure + public function get(string $filename): array { - return $this->state[$filename] ?? NullClosure::create(); + $closures = $this->state[$filename] ?? []; + + return [ + $closures[0] ?? NullClosure::create(), + $closures[1] ?? NullClosure::create(), + ]; } } diff --git a/src/Support/Backtrace.php b/src/Support/Backtrace.php index 24d856a6..8f683ff7 100644 --- a/src/Support/Backtrace.php +++ b/src/Support/Backtrace.php @@ -104,8 +104,6 @@ final class Backtrace { $trace = debug_backtrace(self::BACKTRACE_OPTIONS)[1]; - assert(array_key_exists('line', $trace)); - - return $trace['line']; + return $trace['line'] ?? 0; } } diff --git a/tests/.snapshots/success.txt b/tests/.snapshots/success.txt index 12c9fba9..f6505826 100644 --- a/tests/.snapshots/success.txt +++ b/tests/.snapshots/success.txt @@ -22,6 +22,22 @@ ✓ it gets executed before each test ✓ it gets executed before each test once again + PASS Tests\Features\BeforeEachProxiesToTestCallWithExpectations + ✓ runs 1 + ✓ runs 2 + ✓ runs 3 + + WARN Tests\Features\BeforeEachProxiesToTestCallWithSkip + - does not run 1 + - does not run 2 + - does not run 3 + + TODO Tests\Features\BeforeEachProxiesToTestCallWithTodo - 4 todos + ↓ is marked as todo 1 + ↓ is marked as todo 2 + ↓ is marked as todo 3 + ↓ shouldBeMarkedAsTodo + WARN Tests\Features\Coverage ✓ it has plugin - it adds coverage if --coverage exist → Coverage is not available @@ -1017,4 +1033,4 @@ PASS Tests\Visual\Version ✓ visual snapshot of help command output - Tests: 1 deprecated, 3 warnings, 4 incomplete, 1 notice, 4 todos, 14 skipped, 711 passed (1719 assertions) \ No newline at end of file + Tests: 1 deprecated, 3 warnings, 4 incomplete, 1 notice, 8 todos, 17 skipped, 714 passed (1722 assertions) \ No newline at end of file diff --git a/tests/.snapshots/todo.txt b/tests/.snapshots/todo.txt index a3abcfe3..1d506b46 100644 --- a/tests/.snapshots/todo.txt +++ b/tests/.snapshots/todo.txt @@ -1,3 +1,9 @@ + TODO Tests\Features\BeforeEachProxiesToTestCallWithTodo - 4 todos + ↓ is marked as todo 1 + ↓ is marked as todo 2 + ↓ is marked as todo 3 + ↓ shouldBeMarkedAsTodo + TODO Tests\Features\DatasetsTests - 1 todo ↓ forbids to define tests in Datasets dirs and Datasets.php files @@ -9,4 +15,4 @@ PASS Tests\CustomTestCase\ExecutedTest ✓ that gets executed - Tests: 4 todos, 1 passed (1 assertions) + Tests: 8 todos, 1 passed (1 assertions) diff --git a/tests/Features/BeforeEachProxiesToTestCallWithExpectations.php b/tests/Features/BeforeEachProxiesToTestCallWithExpectations.php new file mode 100644 index 00000000..cc15d3ec --- /dev/null +++ b/tests/Features/BeforeEachProxiesToTestCallWithExpectations.php @@ -0,0 +1,15 @@ +expect(true)->toBeTrue(); + +test('runs 1', function () { + // This test did performs assertions... +}); + +test('runs 2', function () { + // This test did performs assertions... +}); + +test('runs 3', function () { + // This test did performs assertions... +}); diff --git a/tests/Features/BeforeEachProxiesToTestCallWithSkip.php b/tests/Features/BeforeEachProxiesToTestCallWithSkip.php new file mode 100644 index 00000000..b315c9d8 --- /dev/null +++ b/tests/Features/BeforeEachProxiesToTestCallWithSkip.php @@ -0,0 +1,15 @@ +skip(); + +test('does not run 1', function () { + $this->fail('This test should not run'); +}); + +test('does not run 2', function () { + $this->fail('This test should not run'); +}); + +test('does not run 3', function () { + $this->fail('This test should not run'); +}); diff --git a/tests/Features/BeforeEachProxiesToTestCallWithTodo.php b/tests/Features/BeforeEachProxiesToTestCallWithTodo.php new file mode 100644 index 00000000..8f113976 --- /dev/null +++ b/tests/Features/BeforeEachProxiesToTestCallWithTodo.php @@ -0,0 +1,15 @@ +todo(); + +test('is marked as todo 1', function () { + $this->fail('This test should not run'); +}); + +test('is marked as todo 2', function () { + $this->fail('This test should not run'); +}); + +test('is marked as todo 3'); + +test()->shouldBeMarkedAsTodo(); diff --git a/tests/Visual/Parallel.php b/tests/Visual/Parallel.php index 70242017..8e220884 100644 --- a/tests/Visual/Parallel.php +++ b/tests/Visual/Parallel.php @@ -18,7 +18,7 @@ $run = function () { test('parallel', function () use ($run) { expect($run('--exclude-group=integration')) - ->toContain('Tests: 1 deprecated, 3 warnings, 4 incomplete, 1 notice, 4 todos, 11 skipped, 699 passed (1704 assertions)') + ->toContain('Tests: 1 deprecated, 3 warnings, 4 incomplete, 1 notice, 8 todos, 14 skipped, 702 passed (1707 assertions)') ->toContain('Parallel: 3 processes'); })->skipOnWindows(); diff --git a/tests/Visual/Todo.php b/tests/Visual/Todo.php index 43b9b9e3..a6307435 100644 --- a/tests/Visual/Todo.php +++ b/tests/Visual/Todo.php @@ -11,7 +11,9 @@ $run = function (string $target, bool $parallel) { expect($process->getExitCode())->toBe(0); - return preg_replace('#\\x1b[[][^A-Za-z]*[A-Za-z]#', '', $process->getOutput()); + $outputContent = preg_replace('#\\x1b[[][^A-Za-z]*[A-Za-z]#', '', $process->getOutput()); + + return $outputContent; }; $snapshot = function ($name) {