diff --git a/src/Expectations/HigherOrderExpectation.php b/src/Expectations/HigherOrderExpectation.php index 1879e167..f3aa62e7 100644 --- a/src/Expectations/HigherOrderExpectation.php +++ b/src/Expectations/HigherOrderExpectation.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Pest\Expectations; +use Closure; use Pest\Concerns\Retrievable; use Pest\Expectation; @@ -79,6 +80,21 @@ final class HigherOrderExpectation return $this->expect($value); } + /** + * Scope an expectation callback to the current value in + * the HigherOrderExpectation chain. + * + * @param Closure(Expectation): void $expectation + * + * @return HigherOrderExpectation + */ + public function scoped(Closure $expectation): self + { + $expectation->__invoke($this->expectation); + + return new self($this->original, $this->original->value); + } + /** * Creates a new expectation with the decoded JSON value. * diff --git a/tests/Features/Expect/HigherOrder/methods.php b/tests/Features/Expect/HigherOrder/methods.php index da610cf9..3c03ddb5 100644 --- a/tests/Features/Expect/HigherOrder/methods.php +++ b/tests/Features/Expect/HigherOrder/methods.php @@ -74,6 +74,23 @@ it('works with higher order tests') ->name()->toEqual('Has Methods') ->books()->each->toBeArray; +it('can use the scoped method to lock into the given level for expectations', function () { + expect(new HasMethods()) + ->attributes()->scoped(fn ($attributes) => $attributes + ->name->toBe('Has Methods') + ->quantity->toBe(20) + ) + ->name()->toBeString()->toBe('Has Methods') + ->newInstance()->newInstance()->scoped(fn ($instance) => $instance + ->name()->toBe('Has Methods') + ->quantity()->toBe(20) + ->attributes()->scoped(fn ($attributes) => $attributes + ->name->toBe('Has Methods') + ->quantity->toBe(20) + ) + ); +}); + it('works consistently with the json expectation method', function () { expect(new HasMethods()) ->jsonString()->json()->id->toBe(1)