mirror of
https://github.com/pestphp/pest.git
synced 2026-03-06 15:57:21 +01:00
implemements pipelines and adds tests for it
This commit is contained in:
@ -6,6 +6,8 @@ namespace Pest\Concerns;
|
|||||||
|
|
||||||
use BadMethodCallException;
|
use BadMethodCallException;
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use Pest\Expectation;
|
||||||
|
use PHPStan\Type\CallableType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
@ -19,6 +21,9 @@ trait Extendable
|
|||||||
*/
|
*/
|
||||||
private static array $extends = [];
|
private static array $extends = [];
|
||||||
|
|
||||||
|
/** @var array<string, array<Closure>> */
|
||||||
|
private static array $pipes = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a new extend.
|
* Register a new extend.
|
||||||
*/
|
*/
|
||||||
@ -35,6 +40,71 @@ trait Extendable
|
|||||||
return array_key_exists($name, static::$extends);
|
return array_key_exists($name, static::$extends);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a pipe to be applied before an expectation is checked.
|
||||||
|
*/
|
||||||
|
public static function pipe(string $name, Closure $handler): void
|
||||||
|
{
|
||||||
|
self::$pipes[$name][] = $handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register an interceptor that should replace an existing expectation.
|
||||||
|
*/
|
||||||
|
public static function intercept(string $name, string|Closure $filter, Closure $handler): void
|
||||||
|
{
|
||||||
|
if (is_string($filter)) {
|
||||||
|
$filter = fn ($value, ...$arguments): bool => $value instanceof $filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
self::pipe($name, function ($next, ...$arguments) use ($handler, $filter): void {
|
||||||
|
/** @phpstan-ignore-next-line */
|
||||||
|
if ($filter($this->value, ...$arguments)) {
|
||||||
|
/** @phpstan-ignore-next-line */
|
||||||
|
$handler = $handler->bindTo($this, get_class($this));
|
||||||
|
|
||||||
|
if($handler instanceof Closure){
|
||||||
|
$handler(...$arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$next();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if pipes are registered for a given expectation.
|
||||||
|
*/
|
||||||
|
public static function hasPipes(string $name): bool
|
||||||
|
{
|
||||||
|
return array_key_exists($name, static::$pipes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the pipes that have been registered for a given expectation and binds them to a context and a scope.
|
||||||
|
*
|
||||||
|
* @return array<int, Closure>
|
||||||
|
*/
|
||||||
|
private function pipes(string $name, object $context, string $scope): array
|
||||||
|
{
|
||||||
|
if (!self::hasPipes($name)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$pipes = [];
|
||||||
|
foreach (self::$pipes[$name] as $pipe) {
|
||||||
|
$pipe = $pipe->bindTo($context, $scope);
|
||||||
|
|
||||||
|
if($pipe instanceof Closure){
|
||||||
|
$pipes[] = $pipe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pipes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dynamically handle calls to the class.
|
* Dynamically handle calls to the class.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -170,7 +170,7 @@ final class CoreExpectation
|
|||||||
*/
|
*/
|
||||||
public function toStartWith(string $expected): CoreExpectation
|
public function toStartWith(string $expected): CoreExpectation
|
||||||
{
|
{
|
||||||
Assert::assertStringStartsWith($expected, $this->value);
|
Assert::assertStringStartsWith($expected, $this->value); //@phpstan-ignore-line
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -180,7 +180,7 @@ final class CoreExpectation
|
|||||||
*/
|
*/
|
||||||
public function toEndWith(string $expected): CoreExpectation
|
public function toEndWith(string $expected): CoreExpectation
|
||||||
{
|
{
|
||||||
Assert::assertStringEndsWith($expected, $this->value);
|
Assert::assertStringEndsWith($expected, $this->value); //@phpstan-ignore-line
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -322,7 +322,6 @@ final class CoreExpectation
|
|||||||
*/
|
*/
|
||||||
public function toBeInstanceOf(string $class): CoreExpectation
|
public function toBeInstanceOf(string $class): CoreExpectation
|
||||||
{
|
{
|
||||||
/* @phpstan-ignore-next-line */
|
|
||||||
Assert::assertInstanceOf($class, $this->value);
|
Assert::assertInstanceOf($class, $this->value);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Pest\Exceptions;
|
namespace Pest\Exceptions;
|
||||||
|
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
@ -11,7 +13,6 @@ final class ExpectationNotFoundException extends InvalidArgumentException
|
|||||||
{
|
{
|
||||||
public function __construct(string $expectationName)
|
public function __construct(string $expectationName)
|
||||||
{
|
{
|
||||||
parent::__construct(sprintf("Impossible to find [%s] expectation", $expectationName));
|
parent::__construct(sprintf('Impossible to find [%s] expectation', $expectationName));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,9 +9,9 @@ use Closure;
|
|||||||
use Pest\Concerns\Extendable;
|
use Pest\Concerns\Extendable;
|
||||||
use Pest\Concerns\RetrievesValues;
|
use Pest\Concerns\RetrievesValues;
|
||||||
use Pest\Exceptions\ExpectationNotFoundException;
|
use Pest\Exceptions\ExpectationNotFoundException;
|
||||||
|
use Pest\Support\ExpectationPipeline;
|
||||||
use PHPUnit\Framework\Assert;
|
use PHPUnit\Framework\Assert;
|
||||||
use PHPUnit\Framework\ExpectationFailedException;
|
use PHPUnit\Framework\ExpectationFailedException;
|
||||||
use SebastianBergmann\Exporter\Exporter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
@ -19,7 +19,7 @@ use SebastianBergmann\Exporter\Exporter;
|
|||||||
* @template TValue
|
* @template TValue
|
||||||
*
|
*
|
||||||
* @property Expectation $not Creates the opposite expectation.
|
* @property Expectation $not Creates the opposite expectation.
|
||||||
* @property Each $each Creates an expectation on each element on the traversable value.
|
* @property Each $each Creates an expectation on each element on the traversable value.
|
||||||
*
|
*
|
||||||
* @mixin CoreExpectation
|
* @mixin CoreExpectation
|
||||||
*/
|
*/
|
||||||
@ -81,8 +81,6 @@ final class Expectation
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Send the expectation value to Ray along with all given arguments.
|
* Send the expectation value to Ray along with all given arguments.
|
||||||
*
|
|
||||||
* @param ...mixed $arguments
|
|
||||||
*/
|
*/
|
||||||
public function ray(mixed ...$arguments): self
|
public function ray(mixed ...$arguments): self
|
||||||
{
|
{
|
||||||
@ -133,16 +131,16 @@ final class Expectation
|
|||||||
throw new BadMethodCallException('Expectation value is not iterable.');
|
throw new BadMethodCallException('Expectation value is not iterable.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = is_array($this->value) ? $this->value : iterator_to_array($this->value);
|
$value = is_array($this->value) ? $this->value : iterator_to_array($this->value);
|
||||||
$keys = array_keys($value);
|
$keys = array_keys($value);
|
||||||
$values = array_values($value);
|
$values = array_values($value);
|
||||||
$callbacksCount = count($callbacks);
|
$callbacksCount = count($callbacks);
|
||||||
|
|
||||||
$index = 0;
|
$index = 0;
|
||||||
|
|
||||||
while (count($callbacks) < count($values)) {
|
while (count($callbacks) < count($values)) {
|
||||||
$callbacks[] = $callbacks[$index];
|
$callbacks[] = $callbacks[$index];
|
||||||
$index = $index < count($values) - 1 ? $index + 1 : 0;
|
$index = $index < count($values) - 1 ? $index + 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($callbacksCount > count($values)) {
|
if ($callbacksCount > count($values)) {
|
||||||
@ -214,7 +212,7 @@ final class Expectation
|
|||||||
$condition = is_callable($condition)
|
$condition = is_callable($condition)
|
||||||
? $condition
|
? $condition
|
||||||
: static function () use ($condition): bool {
|
: static function () use ($condition): bool {
|
||||||
return $condition; // @phpstan-ignore-line
|
return $condition;
|
||||||
};
|
};
|
||||||
|
|
||||||
return $this->when(!$condition(), $callback);
|
return $this->when(!$condition(), $callback);
|
||||||
@ -231,7 +229,7 @@ final class Expectation
|
|||||||
$condition = is_callable($condition)
|
$condition = is_callable($condition)
|
||||||
? $condition
|
? $condition
|
||||||
: static function () use ($condition): bool {
|
: static function () use ($condition): bool {
|
||||||
return $condition; // @phpstan-ignore-line
|
return $condition;
|
||||||
};
|
};
|
||||||
|
|
||||||
if ($condition()) {
|
if ($condition()) {
|
||||||
@ -256,7 +254,10 @@ final class Expectation
|
|||||||
return new HigherOrderExpectation($this, $this->value->$method(...$parameters));
|
return new HigherOrderExpectation($this, $this->value->$method(...$parameters));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->getExpectationClosure($method)(...$parameters);
|
ExpectationPipeline::for($this->getExpectationClosure($method))
|
||||||
|
->send(...$parameters)
|
||||||
|
->through($this->pipes($method, $this, Expectation::class))
|
||||||
|
->run();
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -295,7 +296,7 @@ final class Expectation
|
|||||||
private function getExpectationClosure(string $name): Closure
|
private function getExpectationClosure(string $name): Closure
|
||||||
{
|
{
|
||||||
if (method_exists($this->coreExpectation, $name)) {
|
if (method_exists($this->coreExpectation, $name)) {
|
||||||
/** @phpstan-ignore-next-line */
|
/* @phpstan-ignore-next-line */
|
||||||
return Closure::fromCallable([$this->coreExpectation, $name]);
|
return Closure::fromCallable([$this->coreExpectation, $name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
65
src/Support/ExpectationPipeline.php
Normal file
65
src/Support/ExpectationPipeline.php
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Pest\Support;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class ExpectationPipeline
|
||||||
|
{
|
||||||
|
/** @var array<Closure> */
|
||||||
|
private array $pipes = [];
|
||||||
|
|
||||||
|
/** @var array<int|string, mixed> */
|
||||||
|
private array $passable;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private Closure $expectationClosure
|
||||||
|
) {
|
||||||
|
//..
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function for(Closure $expectationClosure): ExpectationPipeline
|
||||||
|
{
|
||||||
|
return new self($expectationClosure);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function send(...$passable): ExpectationPipeline
|
||||||
|
{
|
||||||
|
$this->passable = $passable;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<Closure> $pipes
|
||||||
|
*/
|
||||||
|
public function through(array $pipes): ExpectationPipeline
|
||||||
|
{
|
||||||
|
$this->pipes = $pipes;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$pipeline = array_reduce(
|
||||||
|
array_reverse($this->pipes),
|
||||||
|
$this->carry(),
|
||||||
|
function (): void {
|
||||||
|
($this->expectationClosure)(...$this->passable);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$pipeline();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function carry(): Closure
|
||||||
|
{
|
||||||
|
return fn ($stack, $pipe): Closure => fn () => $pipe($stack, ...$this->passable);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -24,4 +24,17 @@ final class Extendable
|
|||||||
{
|
{
|
||||||
$this->extendableClass::extend($name, $extend);
|
$this->extendableClass::extend($name, $extend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register pipe to be applied to the given expectation.
|
||||||
|
*/
|
||||||
|
public function pipe(string $name, Closure $handler): void
|
||||||
|
{
|
||||||
|
$this->extendableClass::pipe($name, $handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function intercept(string $name, string|Closure $filter, Closure $handler): void
|
||||||
|
{
|
||||||
|
$this->extendableClass::intercept($name, $filter, $handler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
255
tests/Features/Expect/pipes.php
Normal file
255
tests/Features/Expect/pipes.php
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use function PHPUnit\Framework\assertEquals;
|
||||||
|
use function PHPUnit\Framework\assertEqualsIgnoringCase;
|
||||||
|
use function PHPUnit\Framework\assertInstanceOf;
|
||||||
|
use function PHPUnit\Framework\assertSame;
|
||||||
|
|
||||||
|
class Number
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public int $value
|
||||||
|
) {
|
||||||
|
//..
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Char
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public string $value
|
||||||
|
) {
|
||||||
|
//..
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Symbol
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public string $value
|
||||||
|
) {
|
||||||
|
//..
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class State
|
||||||
|
{
|
||||||
|
public $runCount = [];
|
||||||
|
public $appliedCount = [];
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reset(): void
|
||||||
|
{
|
||||||
|
$this->appliedCount = $this->runCount = [
|
||||||
|
'char' => 0,
|
||||||
|
'number' => 0,
|
||||||
|
'wildcard' => 0,
|
||||||
|
'symbol' => 0,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$state = new State();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Overrides toBe to assert two Characters are the same
|
||||||
|
*/
|
||||||
|
expect()->pipe('toBe', function ($next, $expected) use ($state) {
|
||||||
|
$state->runCount['char']++;
|
||||||
|
|
||||||
|
if ($this->value instanceof Char) {
|
||||||
|
$state->appliedCount['char']++;
|
||||||
|
|
||||||
|
assertInstanceOf(Char::class, $expected);
|
||||||
|
assertEquals($this->value->value, $expected->value);
|
||||||
|
|
||||||
|
//returning nothing stops pipeline execution
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//calling $next(); let the pipeline to keep running
|
||||||
|
$next();
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Overrides toBe to assert two Number objects are the same
|
||||||
|
*/
|
||||||
|
expect()->intercept('toBe', Number::class, function ($expected) use ($state) {
|
||||||
|
$state->runCount['number']++;
|
||||||
|
$state->appliedCount['number']++;
|
||||||
|
|
||||||
|
assertInstanceOf(Number::class, $expected);
|
||||||
|
assertEquals($this->value->value, $expected->value);
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Overrides toBe to assert all integers are allowed if value is a wildcard (*)
|
||||||
|
*/
|
||||||
|
expect()->intercept('toBe', fn ($value, $expected) => $value === '*' && is_numeric($expected), function ($expected) use ($state) {
|
||||||
|
$state->runCount['wildcard']++;
|
||||||
|
$state->appliedCount['wildcard']++;
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Overrides toBe to assert to Symbols are the same
|
||||||
|
*/
|
||||||
|
expect()->pipe('toBe', function ($next, $expected) use ($state) {
|
||||||
|
$state->runCount['symbol']++;
|
||||||
|
|
||||||
|
if ($this->value instanceof Symbol) {
|
||||||
|
$state->appliedCount['symbol']++;
|
||||||
|
assertInstanceOf(Symbol::class, $expected);
|
||||||
|
assertEquals($this->value->value, $expected->value);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$next();
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Overrides toBe to allow ignoring case when checking strings
|
||||||
|
*/
|
||||||
|
expect()->intercept('toBe', fn ($value) => is_string($value), function ($expected, $ignoreCase = false) {
|
||||||
|
if ($ignoreCase) {
|
||||||
|
assertEqualsIgnoringCase($expected, $this->value);
|
||||||
|
} else {
|
||||||
|
assertSame($expected, $this->value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('pipe is applied and can stop pipeline', function () use ($state) {
|
||||||
|
$char = new Char('A');
|
||||||
|
|
||||||
|
$state->reset();
|
||||||
|
|
||||||
|
expect($char)->toBe(new Char('A'))
|
||||||
|
->and($state)
|
||||||
|
->runCount->toMatchArray([
|
||||||
|
'char' => 1,
|
||||||
|
'number' => 0,
|
||||||
|
'wildcard' => 0,
|
||||||
|
'symbol' => 0,
|
||||||
|
])
|
||||||
|
->appliedCount->toMatchArray([
|
||||||
|
'char' => 1,
|
||||||
|
'number' => 0,
|
||||||
|
'wildcard' => 0,
|
||||||
|
'symbol' => 0,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('pipe is run and lets the pipeline to keep going', function () use ($state) {
|
||||||
|
$state->reset();
|
||||||
|
|
||||||
|
expect(3)->toBe(3)
|
||||||
|
->and($state)
|
||||||
|
->runCount->toMatchArray([
|
||||||
|
'char' => 1,
|
||||||
|
'number' => 0,
|
||||||
|
'wildcard' => 0,
|
||||||
|
'symbol' => 1,
|
||||||
|
])
|
||||||
|
->appliedCount->toMatchArray([
|
||||||
|
'char' => 0,
|
||||||
|
'number' => 0,
|
||||||
|
'wildcard' => 0,
|
||||||
|
'symbol' => 0,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('pipe works with negated expectation', function () use ($state) {
|
||||||
|
$char = new Char('A');
|
||||||
|
|
||||||
|
$state->reset();
|
||||||
|
|
||||||
|
expect($char)->not->toBe(new Char('B'))
|
||||||
|
->and($state)
|
||||||
|
->runCount->toMatchArray([
|
||||||
|
'char' => 1,
|
||||||
|
'number' => 0,
|
||||||
|
'wildcard' => 0,
|
||||||
|
'symbol' => 0,
|
||||||
|
])
|
||||||
|
->appliedCount->toMatchArray([
|
||||||
|
'char' => 1,
|
||||||
|
'number' => 0,
|
||||||
|
'wildcard' => 0,
|
||||||
|
'symbol' => 0,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('interceptor is applied', function () use ($state) {
|
||||||
|
$number = new Number(1);
|
||||||
|
|
||||||
|
$state->reset();
|
||||||
|
|
||||||
|
expect($number)->toBe(new Number(1))
|
||||||
|
->and($state)
|
||||||
|
->runCount->toHaveKey('number', 1)
|
||||||
|
->appliedCount->toHaveKey('number', 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('interceptor stops the pipeline', function () use ($state) {
|
||||||
|
$number = new Number(1);
|
||||||
|
|
||||||
|
$state->reset();
|
||||||
|
|
||||||
|
expect($number)->toBe(new Number(1))
|
||||||
|
->and($state)
|
||||||
|
->runCount->toMatchArray([
|
||||||
|
'char' => 1,
|
||||||
|
'number' => 1,
|
||||||
|
'wildcard' => 0,
|
||||||
|
'symbol' => 0,
|
||||||
|
])
|
||||||
|
->appliedCount->toMatchArray([
|
||||||
|
'char' => 0,
|
||||||
|
'number' => 1,
|
||||||
|
'wildcard' => 0,
|
||||||
|
'symbol' => 0,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('interceptor is called only when filter is met', function () use ($state) {
|
||||||
|
$state->reset();
|
||||||
|
|
||||||
|
expect(1)->toBe(1)
|
||||||
|
->and($state)
|
||||||
|
->runCount->toHaveKey('number', 0)
|
||||||
|
->appliedCount->toHaveKey('number', 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('interceptor can be filtered with a closure', function () use ($state) {
|
||||||
|
$state->reset();
|
||||||
|
|
||||||
|
expect('*')->toBe(1)
|
||||||
|
->and($state)
|
||||||
|
->runCount->toHaveKey('wildcard', 1)
|
||||||
|
->appliedCount->toHaveKey('wildcard', 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('interceptor can be filter the expected parameter as well', function () use ($state) {
|
||||||
|
$state->reset();
|
||||||
|
|
||||||
|
expect('*')->toBe('*')
|
||||||
|
->and($state)
|
||||||
|
->runCount->toHaveKey('wildcard', 0)
|
||||||
|
->appliedCount->toHaveKey('wildcard', 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('interceptor works with negated expectation', function () {
|
||||||
|
$char = new Number(1);
|
||||||
|
|
||||||
|
expect($char)->not->toBe(new Char('B'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('intercept can add new parameters to the expectation', function () {
|
||||||
|
$ignoreCase = true;
|
||||||
|
|
||||||
|
expect('Foo')->toBe('foo', $ignoreCase);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user