refactor: pack hooks into an array instead of 1 argument per hook

This commit is contained in:
jordanbrauer
2021-04-06 19:27:50 -05:00
parent 53333b56ab
commit ff44589572
3 changed files with 111 additions and 26 deletions

View File

@ -5,7 +5,9 @@ declare(strict_types=1);
namespace Pest\Concerns; namespace Pest\Concerns;
use Closure; use Closure;
use Pest\Repositories\BeforeEachRepository;
use Pest\Support\ExceptionTrace; use Pest\Support\ExceptionTrace;
use Pest\Support\ChainableClosure;
use Pest\TestSuite; use Pest\TestSuite;
use PHPUnit\Framework\ExecutionOrderDependency; use PHPUnit\Framework\ExecutionOrderDependency;
use PHPUnit\Util\Test; use PHPUnit\Util\Test;
@ -34,6 +36,22 @@ trait TestCase
*/ */
private $__test; private $__test;
/**
* Holds a global/shared beforeEach ("set up") closure if one has been
* defined.
*
* @var Closure|null
*/
private $beforeEach = null;
/**
* Holds a global/shared afterEach ("tear down") closure if one has been
* defined.
*
* @var Closure|null
*/
private $afterEach = null;
/** /**
* Creates a new instance of the test case. * Creates a new instance of the test case.
*/ */
@ -55,15 +73,6 @@ trait TestCase
$this->setGroups($groups); $this->setGroups($groups);
} }
/**
* Add a shared/"global" before each test hook that will execute **before**
* the test defined `beforeEach` hook.
*/
public function addBeforeEach(?Closure $hook): void
{
$this->beforeEach = $hook;
}
/** /**
* Add dependencies to the test case and map them to instances of ExecutionOrderDependency. * Add dependencies to the test case and map them to instances of ExecutionOrderDependency.
*/ */
@ -82,6 +91,38 @@ trait TestCase
$this->setDependencies($tests); $this->setDependencies($tests);
} }
/**
* Add a shared/"global" before each test hook that will execute **before**
* the test defined `beforeEach` hook.
*/
public function addBeforeEach(?Closure $hook): void
{
$this->addHook('beforeEach', $hook);
}
/**
* Add a shared/"global" after each test hook that will execute **before**
* the test defined `afterEach` hook.
*/
public function addAfterEach(?Closure $hook): void
{
$this->addHook('afterEach', $hook);
}
/**
* Add a shared/global hook and compose them if more than one is passed.
*/
private function addHook(string $property, ?Closure $hook): void
{
if (!$hook) {
return;
}
$this->{$property} = ($this->{$property} instanceof Closure)
? ChainableClosure::from($this->{$property}, $hook)
: $hook;
}
/** /**
* Returns the test case name. Note that, in Pest * Returns the test case name. Note that, in Pest
* we ignore withDataset argument as the description * we ignore withDataset argument as the description
@ -130,12 +171,12 @@ trait TestCase
parent::setUp(); parent::setUp();
if ($this->beforeEach instanceof Closure) {
$this->__callClosure($this->beforeEach, func_get_args());
}
$beforeEach = TestSuite::getInstance()->beforeEach->get(self::$__filename); $beforeEach = TestSuite::getInstance()->beforeEach->get(self::$__filename);
if ($this->beforeEach instanceof Closure) {
$beforeEach = ChainableClosure::from($this->beforeEach, $beforeEach);
}
$this->__callClosure($beforeEach, func_get_args()); $this->__callClosure($beforeEach, func_get_args());
} }
@ -146,6 +187,10 @@ trait TestCase
{ {
$afterEach = TestSuite::getInstance()->afterEach->get(self::$__filename); $afterEach = TestSuite::getInstance()->afterEach->get(self::$__filename);
if ($this->afterEach instanceof Closure) {
$afterEach = ChainableClosure::from($this->afterEach, $afterEach);
}
$this->__callClosure($afterEach, func_get_args()); $this->__callClosure($afterEach, func_get_args());
parent::tearDown(); parent::tearDown();

View File

@ -16,9 +16,16 @@ final class UsesCall
/** /**
* Contains a global before each hook closure to be executed. * Contains a global before each hook closure to be executed.
* *
* @var Closure * Array indices here matter. They are mapped as follows:
*
* - `0` => `beforeAll`
* - `1` => `beforeEach`
* - `2` => `afterEach`
* - `3` => `afterAll`
*
* @var array<int, Closure>
*/ */
private $beforeEach; private $hooks = [];
/** /**
* Holds the class and traits. * Holds the class and traits.
@ -106,11 +113,41 @@ final class UsesCall
} }
/** /**
* Sets the global beforeEach test hook * Sets the global beforeAll test hook.
*/
public function beforeAll(Closure $hook): UsesCall
{
$this->hooks[0] = $hook;
return $this;
}
/**
* Sets the global beforeEach test hook.
*/ */
public function beforeEach(Closure $hook): UsesCall public function beforeEach(Closure $hook): UsesCall
{ {
$this->beforeEach = $hook; $this->hooks[1] = $hook;
return $this;
}
/**
* Sets the global afterEach test hook.
*/
public function afterEach(Closure $hook): UsesCall
{
$this->hooks[2] = $hook;
return $this;
}
/**
* Sets the global afterAll test hook.
*/
public function afterAll(Closure $hook): UsesCall
{
$this->hooks[3] = $hook;
return $this; return $this;
} }
@ -124,7 +161,7 @@ final class UsesCall
$this->classAndTraits, $this->classAndTraits,
$this->groups, $this->groups,
$this->targets, $this->targets,
$this->beforeEach, $this->hooks,
); );
} }
} }

View File

@ -47,9 +47,9 @@ final class TestRepository
}; };
foreach ($this->uses as $path => $uses) { foreach ($this->uses as $path => $uses) {
[$classOrTraits, $groups, $beforeEach] = $uses; [$classOrTraits, $groups, $hooks] = $uses;
$setClassName = function (TestCaseFactory $testCase, string $key) use ($path, $classOrTraits, $groups, $startsWith, $beforeEach): void { $setClassName = function (TestCaseFactory $testCase, string $key) use ($path, $classOrTraits, $groups, $startsWith, $hooks): void {
[$filename] = explode('@', $key); [$filename] = explode('@', $key);
if ((!is_dir($path) && $filename === $path) || (is_dir($path) && $startsWith($filename, $path))) { if ((!is_dir($path) && $filename === $path) || (is_dir($path) && $startsWith($filename, $path))) {
@ -65,8 +65,11 @@ final class TestRepository
} }
// IDEA: Consider set the real lines on these. // IDEA: Consider set the real lines on these.
$testCase->factoryProxies->add($filename, 0, 'addBeforeEach', [$beforeEach]);
$testCase->factoryProxies->add($filename, 0, 'addGroups', [$groups]); $testCase->factoryProxies->add($filename, 0, 'addGroups', [$groups]);
// $testCase->factoryProxies->add($filename, 0, 'addBeforeAll', [$hooks[0] ?? null]);
$testCase->factoryProxies->add($filename, 0, 'addBeforeEach', [$hooks[1] ?? null]);
$testCase->factoryProxies->add($filename, 0, 'addAfterEach', [$hooks[2] ?? null]);
// $testCase->factoryProxies->add($filename, 0, 'addAfterAll', [$hooks[3] ?? null]);
} }
}; };
@ -96,9 +99,9 @@ final class TestRepository
* @param array<int, string> $classOrTraits * @param array<int, string> $classOrTraits
* @param array<int, string> $groups * @param array<int, string> $groups
* @param array<int, string> $paths * @param array<int, string> $paths
* @param Closure|null $beforeEach * @param array<intm Closure> $hooks
*/ */
public function use(array $classOrTraits, array $groups, array $paths, ?Closure $beforeEach): void public function use(array $classOrTraits, array $groups, array $paths, array $hooks): void
{ {
foreach ($classOrTraits as $classOrTrait) { foreach ($classOrTraits as $classOrTrait) {
if (!class_exists($classOrTrait) && !trait_exists($classOrTrait)) { if (!class_exists($classOrTrait) && !trait_exists($classOrTrait)) {
@ -111,10 +114,10 @@ final class TestRepository
$this->uses[$path] = [ $this->uses[$path] = [
array_merge($this->uses[$path][0], $classOrTraits), array_merge($this->uses[$path][0], $classOrTraits),
array_merge($this->uses[$path][1], $groups), array_merge($this->uses[$path][1], $groups),
$this->uses[$path][2] ?? $beforeEach, $this->uses[$path][2] + $hooks,
]; ];
} else { } else {
$this->uses[$path] = [$classOrTraits, $groups, $beforeEach]; $this->uses[$path] = [$classOrTraits, $groups, $hooks];
} }
} }
} }