mirror of
https://github.com/pestphp/pest.git
synced 2026-03-06 15:57:21 +01:00
refactor: comments
This commit is contained in:
69
src/PendingCalls/AfterEachCall.php
Normal file
69
src/PendingCalls/AfterEachCall.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest\PendingCalls;
|
||||
|
||||
use Closure;
|
||||
use Pest\Support\Backtrace;
|
||||
use Pest\Support\ChainableClosure;
|
||||
use Pest\Support\HigherOrderMessageCollection;
|
||||
use Pest\Support\NullClosure;
|
||||
use Pest\TestSuite;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class AfterEachCall
|
||||
{
|
||||
/**
|
||||
* The "afterEach" closure.
|
||||
*/
|
||||
private Closure $closure;
|
||||
|
||||
/**
|
||||
* The calls that should be proxied.
|
||||
*/
|
||||
private HigherOrderMessageCollection $proxies;
|
||||
|
||||
/**
|
||||
* Creates a new Pending Call.
|
||||
*/
|
||||
public function __construct(
|
||||
private TestSuite $testSuite,
|
||||
private string $filename,
|
||||
Closure $closure = null
|
||||
) {
|
||||
$this->closure = $closure instanceof Closure ? $closure : NullClosure::create();
|
||||
|
||||
$this->proxies = new HigherOrderMessageCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the Call.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$proxies = $this->proxies;
|
||||
|
||||
$this->testSuite->afterEach->set(
|
||||
$this->filename,
|
||||
ChainableClosure::from(function () use ($proxies): void {
|
||||
$proxies->chain($this);
|
||||
}, $this->closure)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the calls to be used on the target.
|
||||
*
|
||||
* @param array<int, mixed> $arguments
|
||||
*/
|
||||
public function __call(string $name, array $arguments): self
|
||||
{
|
||||
$this->proxies
|
||||
->add(Backtrace::file(), Backtrace::line(), $name, $arguments);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
69
src/PendingCalls/BeforeEachCall.php
Normal file
69
src/PendingCalls/BeforeEachCall.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest\PendingCalls;
|
||||
|
||||
use Closure;
|
||||
use Pest\Support\Backtrace;
|
||||
use Pest\Support\ChainableClosure;
|
||||
use Pest\Support\HigherOrderMessageCollection;
|
||||
use Pest\Support\NullClosure;
|
||||
use Pest\TestSuite;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BeforeEachCall
|
||||
{
|
||||
/**
|
||||
* Holds the before each closure.
|
||||
*/
|
||||
private \Closure $closure;
|
||||
|
||||
/**
|
||||
* The calls that should be proxied.
|
||||
*/
|
||||
private HigherOrderMessageCollection $proxies;
|
||||
|
||||
/**
|
||||
* Creates a new Pending Call.
|
||||
*/
|
||||
public function __construct(
|
||||
private TestSuite $testSuite,
|
||||
private string $filename,
|
||||
Closure $closure = null
|
||||
) {
|
||||
$this->closure = $closure instanceof Closure ? $closure : NullClosure::create();
|
||||
|
||||
$this->proxies = new HigherOrderMessageCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the Call.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$proxies = $this->proxies;
|
||||
|
||||
$this->testSuite->beforeEach->set(
|
||||
$this->filename,
|
||||
ChainableClosure::from(function () use ($proxies): void {
|
||||
$proxies->chain($this);
|
||||
}, $this->closure)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the calls to be used on the target.
|
||||
*
|
||||
* @param array<int, mixed> $arguments
|
||||
*/
|
||||
public function __call(string $name, array $arguments): self
|
||||
{
|
||||
$this->proxies
|
||||
->add(Backtrace::file(), Backtrace::line(), $name, $arguments);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
212
src/PendingCalls/TestCall.php
Normal file
212
src/PendingCalls/TestCall.php
Normal file
@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest\PendingCalls;
|
||||
|
||||
use Closure;
|
||||
use Pest\Factories\TestCaseFactory;
|
||||
use Pest\Support\Backtrace;
|
||||
use Pest\Support\HigherOrderCallables;
|
||||
use Pest\Support\NullClosure;
|
||||
use Pest\TestSuite;
|
||||
use SebastianBergmann\Exporter\Exporter;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @mixin HigherOrderCallables
|
||||
*/
|
||||
final class TestCall
|
||||
{
|
||||
/**
|
||||
* The Test Case Factory.
|
||||
*/
|
||||
private TestCaseFactory $testCaseFactory;
|
||||
|
||||
/**
|
||||
* If test call is descriptionLess.
|
||||
*/
|
||||
private bool $descriptionLess;
|
||||
|
||||
/**
|
||||
* Creates a new Pending Call.
|
||||
*/
|
||||
public function __construct(
|
||||
private TestSuite $testSuite,
|
||||
string $filename,
|
||||
string $description = null,
|
||||
Closure $closure = null
|
||||
) {
|
||||
$this->testCaseFactory = new TestCaseFactory($filename, $description, $closure);
|
||||
$this->descriptionLess = $description === null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the test throws the given `$exceptionClass` when called.
|
||||
*/
|
||||
public function throws(string $exception, string $exceptionMessage = null): TestCall
|
||||
{
|
||||
if (class_exists($exception)) {
|
||||
$this->testCaseFactory
|
||||
->proxies
|
||||
->add(Backtrace::file(), Backtrace::line(), 'expectException', [$exception]);
|
||||
} else {
|
||||
$exceptionMessage = $exception;
|
||||
}
|
||||
|
||||
if (is_string($exceptionMessage)) {
|
||||
$this->testCaseFactory
|
||||
->proxies
|
||||
->add(Backtrace::file(), Backtrace::line(), 'expectExceptionMessage', [$exceptionMessage]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the test throws the given `$exceptionClass` when called if the given condition is true.
|
||||
*
|
||||
* @param (callable(): bool)|bool $condition
|
||||
*/
|
||||
public function throwsIf(callable|bool $condition, string $exception, string $exceptionMessage = null): TestCall
|
||||
{
|
||||
$condition = is_callable($condition)
|
||||
? $condition
|
||||
: static function () use ($condition): bool {
|
||||
return $condition; // @phpstan-ignore-line
|
||||
};
|
||||
|
||||
if ($condition()) {
|
||||
return $this->throws($exception, $exceptionMessage);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the current test multiple times with
|
||||
* each item of the given `iterable`.
|
||||
*
|
||||
* @param array<\Closure|iterable<int|string, mixed>|string> $data
|
||||
*/
|
||||
public function with(...$data): TestCall
|
||||
{
|
||||
foreach ($data as $dataset) {
|
||||
$this->testCaseFactory->datasets[] = $dataset;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the test depends.
|
||||
*/
|
||||
public function depends(string ...$tests): TestCall
|
||||
{
|
||||
$this->testCaseFactory
|
||||
->factoryProxies
|
||||
->add(Backtrace::file(), Backtrace::line(), 'addDependencies', [$tests]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the test suite only this test case.
|
||||
*/
|
||||
public function only(): TestCall
|
||||
{
|
||||
$this->testCaseFactory->only = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the test group(s).
|
||||
*/
|
||||
public function group(string ...$groups): TestCall
|
||||
{
|
||||
$this->testCaseFactory
|
||||
->factoryProxies
|
||||
->add(Backtrace::file(), Backtrace::line(), 'addGroups', [$groups]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips the current test.
|
||||
*/
|
||||
public function skip(Closure|bool|string $conditionOrMessage = true, string $message = ''): TestCall
|
||||
{
|
||||
$condition = is_string($conditionOrMessage)
|
||||
? NullClosure::create()
|
||||
: $conditionOrMessage;
|
||||
|
||||
$condition = is_callable($condition)
|
||||
? $condition
|
||||
: fn () => $condition;
|
||||
|
||||
$message = is_string($conditionOrMessage)
|
||||
? $conditionOrMessage
|
||||
: $message;
|
||||
|
||||
/** @var callable(): bool $condition */
|
||||
$condition = $condition->bindTo(null);
|
||||
|
||||
$this->testCaseFactory
|
||||
->chains
|
||||
->addWhen($condition, Backtrace::file(), Backtrace::line(), 'markTestSkipped', [$message]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the property accessors to be used on the target.
|
||||
*/
|
||||
public function __get(string $name): self
|
||||
{
|
||||
return $this->addChain($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the calls to be used on the target.
|
||||
*
|
||||
* @param array<int, mixed> $arguments
|
||||
*/
|
||||
public function __call(string $name, array $arguments): self
|
||||
{
|
||||
return $this->addChain($name, $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a chain to the test case factory. Omitting the arguments will treat it as a property accessor.
|
||||
*
|
||||
* @param array<int, mixed>|null $arguments
|
||||
*/
|
||||
private function addChain(string $name, array $arguments = null): self
|
||||
{
|
||||
$this->testCaseFactory
|
||||
->chains
|
||||
->add(Backtrace::file(), Backtrace::line(), $name, $arguments);
|
||||
|
||||
if ($this->descriptionLess) {
|
||||
$exporter = new Exporter();
|
||||
if ($this->testCaseFactory->description !== null) {
|
||||
$this->testCaseFactory->description .= ' → ';
|
||||
}
|
||||
$this->testCaseFactory->description .= $arguments === null
|
||||
? $name
|
||||
: sprintf('%s %s', $name, $exporter->shortenedRecursiveExport($arguments));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the Call.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->testSuite->tests->set($this->testCaseFactory);
|
||||
}
|
||||
}
|
||||
149
src/PendingCalls/UsesCall.php
Normal file
149
src/PendingCalls/UsesCall.php
Normal file
@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest\PendingCalls;
|
||||
|
||||
use Closure;
|
||||
use Pest\TestSuite;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class UsesCall
|
||||
{
|
||||
/**
|
||||
* Contains a global before each hook closure to be executed.
|
||||
*
|
||||
* Array indices here matter. They are mapped as follows:
|
||||
*
|
||||
* - `0` => `beforeAll`
|
||||
* - `1` => `beforeEach`
|
||||
* - `2` => `afterEach`
|
||||
* - `3` => `afterAll`
|
||||
*
|
||||
* @var array<int, Closure>
|
||||
*/
|
||||
private array $hooks = [];
|
||||
|
||||
/**
|
||||
* Holds the targets of the uses.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
private array $targets;
|
||||
|
||||
/**
|
||||
* Holds the groups of the uses.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
private array $groups = [];
|
||||
|
||||
/**
|
||||
* Creates a new Pending Call.
|
||||
*
|
||||
* @param array<int, string> $classAndTraits
|
||||
*/
|
||||
public function __construct(
|
||||
private string $filename,
|
||||
private array $classAndTraits
|
||||
) {
|
||||
$this->targets = [$filename];
|
||||
}
|
||||
|
||||
/**
|
||||
* The directories or file where the
|
||||
* class or traits should be used.
|
||||
*/
|
||||
public function in(string ...$targets): void
|
||||
{
|
||||
$targets = array_map(function ($path): string {
|
||||
$startChar = DIRECTORY_SEPARATOR;
|
||||
|
||||
if ('\\' === DIRECTORY_SEPARATOR || preg_match('~\A[A-Z]:(?![^/\\\\])~i', $path) > 0) {
|
||||
$path = (string) preg_replace_callback('~^(?P<drive>[a-z]+:\\\)~i', fn ($match): string => strtolower($match['drive']), $path);
|
||||
|
||||
$startChar = strtolower((string) preg_replace('~^([a-z]+:\\\).*$~i', '$1', __DIR__));
|
||||
}
|
||||
|
||||
return str_starts_with($path, $startChar)
|
||||
? $path
|
||||
: implode(DIRECTORY_SEPARATOR, [
|
||||
dirname($this->filename),
|
||||
$path,
|
||||
]);
|
||||
}, $targets);
|
||||
|
||||
$this->targets = array_reduce($targets, function (array $accumulator, string $target): array {
|
||||
if (is_dir($target) || file_exists($target)) {
|
||||
$accumulator[] = (string) realpath($target);
|
||||
}
|
||||
|
||||
return $accumulator;
|
||||
}, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the test group(s).
|
||||
*/
|
||||
public function group(string ...$groups): UsesCall
|
||||
{
|
||||
$this->groups = $groups;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the Call.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
TestSuite::getInstance()->tests->use(
|
||||
$this->classAndTraits,
|
||||
$this->groups,
|
||||
$this->targets,
|
||||
$this->hooks,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user