From 03dc11c2f60bbc34a66c6376c1157beb9ba125c2 Mon Sep 17 00:00:00 2001 From: Nuno Maduro Date: Sun, 29 Nov 2020 16:30:57 +0100 Subject: [PATCH] Adds expect extend --- src/Concerns/Extendable.php | 55 ++++++++++++++++++++++++++++++++++++ src/Expectation.php | 3 ++ src/Support/Extendable.php | 33 ++++++++++++++++++++++ src/globals.php | 9 ++++-- tests/.snapshots/success.txt | 8 +++++- tests/Expect/extend.php | 29 +++++++++++++++++++ 6 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 src/Concerns/Extendable.php create mode 100644 src/Support/Extendable.php create mode 100644 tests/Expect/extend.php diff --git a/src/Concerns/Extendable.php b/src/Concerns/Extendable.php new file mode 100644 index 00000000..41757a9f --- /dev/null +++ b/src/Concerns/Extendable.php @@ -0,0 +1,55 @@ + + */ + private static $extends = []; + + /** + * Register a custom extend. + */ + public static function extend(string $name, Closure $extend): void + { + static::$extends[$name] = $extend; + } + + /** + * Checks if extend is registered. + */ + public static function hasExtend(string $name): bool + { + return array_key_exists($name, static::$extends); + } + + /** + * Dynamically handle calls to the class. + * + * @param array $parameters + * + * @return mixed + * + * @throws BadMethodCallException + */ + public function __call(string $method, array $parameters) + { + if (!static::hasExtend($method)) { + throw new BadMethodCallException(sprintf('Method %s::%s does not exist.', static::class, $method)); + } + + $extend = static::$extends[$method]->bindTo($this, static::class); + + return $extend(...$parameters); + } +} diff --git a/src/Expectation.php b/src/Expectation.php index 0946c00f..2815ef14 100644 --- a/src/Expectation.php +++ b/src/Expectation.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Pest; +use Pest\Concerns\Extendable; use PHPUnit\Framework\Assert; use PHPUnit\Framework\Constraint\Constraint; use SebastianBergmann\Exporter\Exporter; @@ -15,6 +16,8 @@ use SebastianBergmann\Exporter\Exporter; */ final class Expectation { + use Extendable; + /** * The expectation value. * diff --git a/src/Support/Extendable.php b/src/Support/Extendable.php new file mode 100644 index 00000000..dcbb7a5a --- /dev/null +++ b/src/Support/Extendable.php @@ -0,0 +1,33 @@ +extendableClass = $extendableClass; + } + + /** + * Register a custom extend. + */ + public function extend(string $name, Closure $extend): void + { + $this->extendableClass::extend($name, $extend); + } +} diff --git a/src/globals.php b/src/globals.php index 87bc6c4e..ed642a21 100644 --- a/src/globals.php +++ b/src/globals.php @@ -9,6 +9,7 @@ use Pest\PendingObjects\BeforeEachCall; use Pest\PendingObjects\TestCall; use Pest\PendingObjects\UsesCall; use Pest\Support\Backtrace; +use Pest\Support\Extendable; use Pest\Support\HigherOrderTapProxy; use Pest\TestSuite; use PHPUnit\Framework\TestCase; @@ -111,9 +112,13 @@ function afterAll(Closure $closure = null): void * * @param mixed $value the Value * - * @return Expectation + * @return Expectation|Extendable */ -function expect($value) +function expect($value = null) { + if (func_num_args() === 0) { + return new Extendable(Expectation::class); + } + return test()->expect($value); } diff --git a/tests/.snapshots/success.txt b/tests/.snapshots/success.txt index 300d25c6..b8319ef8 100644 --- a/tests/.snapshots/success.txt +++ b/tests/.snapshots/success.txt @@ -2,6 +2,12 @@ PASS Tests\CustomTestCase\ExecutedTest ✓ that gets executed + PASS Tests\Expect\extend + ✓ it macros true is true + ✓ it macros false is not true + ✓ it macros true is true with argument + ✓ it macros false is not true with argument + PASS Tests\Expect\not ✓ not property calls @@ -404,5 +410,5 @@ ✓ depends run test only once ✓ depends works with the correct test name - Tests: 7 skipped, 238 passed + Tests: 7 skipped, 242 passed \ No newline at end of file diff --git a/tests/Expect/extend.php b/tests/Expect/extend.php new file mode 100644 index 00000000..4be88241 --- /dev/null +++ b/tests/Expect/extend.php @@ -0,0 +1,29 @@ +extend('toBeAMacroExpectation', function () { + $this->toBeTrue(); + + return $this; +}); + +expect()->extend('toBeAMacroExpectationWithArguments', function (bool $value) { + $this->toBe($value); + + return $this; +}); + +it('macros true is true', function () { + expect(true)->toBeAMacroExpectation(); +}); + +it('macros false is not true', function () { + expect(false)->not->toBeAMacroExpectation(); +}); + +it('macros true is true with argument', function () { + expect(true)->toBeAMacroExpectationWithArguments(true); +}); + +it('macros false is not true with argument', function () { + expect(false)->not->toBeAMacroExpectationWithArguments(true); +});