From b97e206f7a2cb094d4adaba0ca554d49a3040446 Mon Sep 17 00:00:00 2001 From: luke Date: Thu, 8 Jul 2021 09:44:28 +0100 Subject: [PATCH 1/3] Closures passed to the `skip` method are now bound to the test case to allow for more complex logic. --- src/PendingObjects/TestCall.php | 8 +++---- src/Plugins/Coverage.php | 1 - src/Support/HigherOrderMessage.php | 23 +++++++++++++++++++- src/Support/HigherOrderMessageCollection.php | 10 +++++++++ tests/Features/Skip.php | 8 +++++++ 5 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/PendingObjects/TestCall.php b/src/PendingObjects/TestCall.php index 394865653..76df5dacf 100644 --- a/src/PendingObjects/TestCall.php +++ b/src/PendingObjects/TestCall.php @@ -143,11 +143,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/Plugins/Coverage.php b/src/Plugins/Coverage.php index cc03bd171..6d9937171 100644 --- a/src/Plugins/Coverage.php +++ b/src/Plugins/Coverage.php @@ -81,7 +81,6 @@ public function handleArguments(array $originals): array } if ($input->getOption(self::MIN_OPTION) !== null) { - /* @phpstan-ignore-next-line */ $this->coverageMin = (float) $input->getOption(self::MIN_OPTION); } diff --git a/src/Support/HigherOrderMessage.php b/src/Support/HigherOrderMessage.php index 9f363b5aa..4479b21d1 100644 --- a/src/Support/HigherOrderMessage.php +++ b/src/Support/HigherOrderMessage.php @@ -4,6 +4,8 @@ namespace Pest\Support; +use Closure; +use const PHP_MAJOR_VERSION; use ReflectionClass; use Throwable; @@ -50,6 +52,13 @@ final class HigherOrderMessage */ public $arguments; + /** + * An optional condition that will determine if the message will be executed. + * + * @var callable|null + */ + public $condition = null; + /** * Creates a new higher order message. * @@ -70,6 +79,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; + } + try { return Reflection::call($target, $this->methodName, $this->arguments); } catch (Throwable $throwable) { @@ -88,9 +102,16 @@ public function call(object $target) } } + public function when(callable $condition): self + { + $this->condition = $condition; + + return $this; + } + private static function getUndefinedMethodMessage(object $target, string $methodName): string { - if (\PHP_MAJOR_VERSION >= 8) { + if (PHP_MAJOR_VERSION >= 8) { return sprintf(sprintf(self::UNDEFINED_METHOD, sprintf('%s::%s()', get_class($target), $methodName))); } 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..9102673b0 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,7 @@ 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); From fa3959db17c6b66b31116d902a6794b10d12bf0a Mon Sep 17 00:00:00 2001 From: luke Date: Thu, 8 Jul 2021 13:12:30 +0100 Subject: [PATCH 2/3] Type hints for callable --- src/Support/HigherOrderMessage.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Support/HigherOrderMessage.php b/src/Support/HigherOrderMessage.php index 4479b21d1..952acf542 100644 --- a/src/Support/HigherOrderMessage.php +++ b/src/Support/HigherOrderMessage.php @@ -55,7 +55,7 @@ final class HigherOrderMessage /** * An optional condition that will determine if the message will be executed. * - * @var callable|null + * @var callable(): bool|null */ public $condition = null; @@ -102,6 +102,11 @@ 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; From 6ce678d1c276b71c89fa91ab07a0368dd248ae8f Mon Sep 17 00:00:00 2001 From: luke Date: Thu, 8 Jul 2021 17:52:56 +0100 Subject: [PATCH 3/3] Adds an extra test to ensure that skipping takes place before higher order callables. --- tests/Features/Skip.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Features/Skip.php b/tests/Features/Skip.php index 9102673b0..f5d867ca9 100644 --- a/tests/Features/Skip.php +++ b/tests/Features/Skip.php @@ -39,3 +39,8 @@ 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();