mirror of
https://github.com/pestphp/pest.git
synced 2026-03-06 15:57:21 +01:00
213 lines
5.4 KiB
PHP
213 lines
5.4 KiB
PHP
<?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);
|
|
}
|
|
}
|