diff --git a/src/PendingObjects/TestCall.php b/src/PendingObjects/TestCall.php index 40574ed13..41d85826e 100644 --- a/src/PendingObjects/TestCall.php +++ b/src/PendingObjects/TestCall.php @@ -144,11 +144,9 @@ public function skip($conditionOrMessage = true, string $message = ''): TestCall ? $conditionOrMessage : $message; - if ($condition() !== false) { - $this->testCaseFactory - ->chains - ->add(Backtrace::file(), Backtrace::line(), 'markTestSkipped', [$message]); - } + $this->testCaseFactory + ->chains + ->addWhen($condition, Backtrace::file(), Backtrace::line(), 'markTestSkipped', [$message]); return $this; } diff --git a/src/Support/HigherOrderMessage.php b/src/Support/HigherOrderMessage.php index 2a51b7ba0..78820dc38 100644 --- a/src/Support/HigherOrderMessage.php +++ b/src/Support/HigherOrderMessage.php @@ -4,6 +4,7 @@ namespace Pest\Support; +use Closure; use ReflectionClass; use Throwable; @@ -50,6 +51,13 @@ final class HigherOrderMessage */ public $arguments; + /** + * An optional condition that will determine if the message will be executed. + * + * @var callable(): bool|null + */ + public $condition = null; + /** * Creates a new higher order message. * @@ -70,6 +78,11 @@ public function __construct(string $filename, int $line, string $methodName, arr */ public function call(object $target) { + /* @phpstan-ignore-next-line */ + if (is_callable($this->condition) && call_user_func(Closure::bind($this->condition, $target)) === false) { + return $target; + } + if ($this->hasHigherOrderCallable()) { /* @phpstan-ignore-next-line */ return (new HigherOrderCallables($target))->{$this->methodName}(...$this->arguments); @@ -93,6 +106,18 @@ public function call(object $target) } } + /** + * Indicates that this message should only be called when the given condition is true. + * + * @param callable(): bool $condition + */ + public function when(callable $condition): self + { + $this->condition = $condition; + + return $this; + } + /** * Determines whether or not there exists a higher order callable with the message name. * diff --git a/src/Support/HigherOrderMessageCollection.php b/src/Support/HigherOrderMessageCollection.php index f16765e1c..4c6e9cd26 100644 --- a/src/Support/HigherOrderMessageCollection.php +++ b/src/Support/HigherOrderMessageCollection.php @@ -24,6 +24,16 @@ public function add(string $filename, int $line, string $methodName, array $argu $this->messages[] = new HigherOrderMessage($filename, $line, $methodName, $arguments); } + /** + * Adds a new higher order message to the collection if the callable condition is does not return false. + * + * @param array $arguments + */ + public function addWhen(callable $condition, string $filename, int $line, string $methodName, array $arguments): void + { + $this->messages[] = (new HigherOrderMessage($filename, $line, $methodName, $arguments))->when($condition); + } + /** * Proxy all the messages starting from the target. */ diff --git a/tests/Features/Skip.php b/tests/Features/Skip.php index 66d6fe627..f5d867ca9 100644 --- a/tests/Features/Skip.php +++ b/tests/Features/Skip.php @@ -1,5 +1,9 @@ shouldSkip = true; +}); + it('do not skips') ->skip(false) ->assertTrue(true); @@ -31,3 +35,12 @@ it('skips when skip after assertion') ->assertTrue(true) ->skip(); + +it('can use something in the test case as a condition') + ->skip(function () { return $this->shouldSkip; }, 'This test was skipped') + ->assertTrue(false); + +it('can user higher order callables and skip') + ->skip(function () { return $this->shouldSkip; }) + ->expect(function () { return $this->shouldSkip; }) + ->toBeFalse();