diff --git a/src/Repositories/TestRepository.php b/src/Repositories/TestRepository.php index f8b789c2..fa208110 100644 --- a/src/Repositories/TestRepository.php +++ b/src/Repositories/TestRepository.php @@ -25,7 +25,7 @@ final class TestRepository private array $testCases = []; /** - * @var array, 1: array, 2: array}> + * @var array, 1: array, 2: array>}> */ private array $uses = []; @@ -77,12 +77,17 @@ final class TestRepository throw new TestCaseClassOrTraitNotFound($classOrTrait); } + $hooks = array_map(fn (Closure $hook): array => [$hook], $hooks); + foreach ($paths as $path) { if (array_key_exists($path, $this->uses)) { $this->uses[$path] = [ [...$this->uses[$path][0], ...$classOrTraits], [...$this->uses[$path][1], ...$groups], - $this->uses[$path][2] + $hooks, + array_map( + fn (int $index): array => [...$this->uses[$path][2][$index] ?? [], ...($hooks[$index] ?? [])], + range(0, 3), + ), ]; } else { $this->uses[$path] = [$classOrTraits, $groups, $hooks]; @@ -189,10 +194,11 @@ final class TestRepository $method->groups = [...$groups, ...$method->groups]; } - $testCase->factoryProxies->add($testCase->filename, 0, '__addBeforeAll', [$hooks[0] ?? null]); - $testCase->factoryProxies->add($testCase->filename, 0, '__addBeforeEach', [$hooks[1] ?? null]); - $testCase->factoryProxies->add($testCase->filename, 0, '__addAfterEach', [$hooks[2] ?? null]); - $testCase->factoryProxies->add($testCase->filename, 0, '__addAfterAll', [$hooks[3] ?? null]); + foreach (['__addBeforeAll', '__addBeforeEach', '__addAfterEach', '__addAfterAll'] as $index => $name) { + foreach ($hooks[$index] ?? [null] as $hook) { + $testCase->factoryProxies->add($testCase->filename, 0, $name, [$hook]); + } + } } } diff --git a/tests/Hooks/AfterAllTest.php b/tests/Hooks/AfterAllTest.php new file mode 100644 index 00000000..28335361 --- /dev/null +++ b/tests/Hooks/AfterAllTest.php @@ -0,0 +1,45 @@ +afterAll(function () { + expect($_SERVER['globalHook']) + ->toHaveProperty('afterAll') + ->and($_SERVER['globalHook']->afterAll) + ->toBe(1) + ->and($_SERVER['globalHook']->calls) + ->afterAll + ->toBe(1); + + $_SERVER['globalHook']->afterAll = 2; + $_SERVER['globalHook']->calls->afterAll++; +}); + +afterAll(function () { + expect($_SERVER['globalHook']) + ->toHaveProperty('afterAll') + ->and($_SERVER['globalHook']->afterAll) + ->toBe(1) + ->and($_SERVER['globalHook']->calls) + ->afterAll + ->toBe(2); + + $_SERVER['globalHook']->afterAll = 2; + $_SERVER['globalHook']->calls->afterAll++; +}); + +test('global afterAll execution order', function () { + expect($_SERVER['globalHook']) + ->not() + ->toHaveProperty('afterAll') + ->and($_SERVER['globalHook']->calls) + ->afterAll + ->toBe(0); +}); + +it('only gets called once per file', function () { + expect($_SERVER['globalHook']) + ->not() + ->toHaveProperty('afterAll') + ->and($_SERVER['globalHook']->calls) + ->afterAll + ->toBe(0); +}); diff --git a/tests/Hooks/AfterEachTest.php b/tests/Hooks/AfterEachTest.php index 41dc6692..dc7176a9 100644 --- a/tests/Hooks/AfterEachTest.php +++ b/tests/Hooks/AfterEachTest.php @@ -4,16 +4,16 @@ uses()->afterEach(function () { expect($this) ->toHaveProperty('ith') ->and($this->ith) - ->toBe(0); + ->toBe(1); - $this->ith = 1; + $this->ith = 2; }); afterEach(function () { expect($this) ->toHaveProperty('ith') ->and($this->ith) - ->toBe(1); + ->toBe(2); }); test('global afterEach execution order', function () { diff --git a/tests/Hooks/BeforeAllTest.php b/tests/Hooks/BeforeAllTest.php new file mode 100644 index 00000000..ae5a8446 --- /dev/null +++ b/tests/Hooks/BeforeAllTest.php @@ -0,0 +1,55 @@ +calls baseline. This is because +// two other tests are executed before this one due to filename ordering. +$args = $_SERVER['argv'] ?? []; +$single = (isset($args[1]) && Str::endsWith(__FILE__, $args[1])) || Parallel::isWorker(); +$offset = $single ? 0 : 2; + +uses()->beforeAll(function () use ($offset) { + expect($_SERVER['globalHook']) + ->toHaveProperty('beforeAll') + ->and($_SERVER['globalHook']->beforeAll) + ->toBe(1) + ->and($_SERVER['globalHook']->calls) + ->beforeAll + ->toBe(1 + $offset); + + $_SERVER['globalHook']->beforeAll = 2; + $_SERVER['globalHook']->calls->beforeAll++; +}); + +beforeAll(function () use ($offset) { + expect($_SERVER['globalHook']) + ->toHaveProperty('beforeAll') + ->and($_SERVER['globalHook']->beforeAll) + ->toBe(2) + ->and($_SERVER['globalHook']->calls) + ->beforeAll + ->toBe(2 + $offset); + + $_SERVER['globalHook']->beforeAll = 3; + $_SERVER['globalHook']->calls->beforeAll++; +}); + +test('global beforeAll execution order', function () use ($offset) { + expect($_SERVER['globalHook']) + ->toHaveProperty('beforeAll') + ->and($_SERVER['globalHook']->beforeAll) + ->toBe(3) + ->and($_SERVER['globalHook']->calls) + ->beforeAll + ->toBe(3 + $offset); +}); + +it('only gets called once per file', function () use ($offset) { + expect($_SERVER['globalHook']) + ->beforeAll + ->toBe(3) + ->and($_SERVER['globalHook']->calls) + ->beforeAll + ->toBe(3 + $offset); +}); diff --git a/tests/Hooks/BeforeEachTest.php b/tests/Hooks/BeforeEachTest.php index a9317cef..9b74ee10 100644 --- a/tests/Hooks/BeforeEachTest.php +++ b/tests/Hooks/BeforeEachTest.php @@ -1,15 +1,6 @@ beforeEach(function () { - expect($this) - ->toHaveProperty('baz') - ->and($this->baz) - ->toBe(0); - - $this->baz = 1; -}); - -beforeEach(function () { expect($this) ->toHaveProperty('baz') ->and($this->baz) @@ -18,9 +9,18 @@ beforeEach(function () { $this->baz = 2; }); -test('global beforeEach execution order', function () { +beforeEach(function () { expect($this) ->toHaveProperty('baz') ->and($this->baz) ->toBe(2); + + $this->baz = 3; +}); + +test('global beforeEach execution order', function () { + expect($this) + ->toHaveProperty('baz') + ->and($this->baz) + ->toBe(3); }); diff --git a/tests/Pest.php b/tests/Pest.php index 27c64913..4499f0a5 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -33,6 +33,41 @@ uses() }) ->in('Hooks'); +uses() + ->beforeEach(function () { + expect($this) + ->toHaveProperty('baz') + ->and($this->baz) + ->toBe(0); + + $this->baz = 1; + }) + ->beforeAll(function () { + expect($_SERVER['globalHook']) + ->toHaveProperty('beforeAll') + ->and($_SERVER['globalHook']->beforeAll) + ->toBe(0); + + $_SERVER['globalHook']->beforeAll = 1; + }) + ->afterEach(function () { + expect($this) + ->toHaveProperty('ith') + ->and($this->ith) + ->toBe(0); + + $this->ith = 1; + }) + ->afterAll(function () { + expect($_SERVER['globalHook']) + ->toHaveProperty('afterAll') + ->and($_SERVER['globalHook']->afterAll) + ->toBe(0); + + $_SERVER['globalHook']->afterAll = 1; + }) + ->in('Hooks'); + function helper_returns_string() { return 'string';