From 60358461c4be748f7106ae4f318dfd33ce91f1f8 Mon Sep 17 00:00:00 2001 From: Owen Voke Date: Sun, 29 Jan 2023 12:33:25 +0000 Subject: [PATCH] feat: add support for `toHaveMethod` and `toHaveMethods` --- src/Mixins/Expectation.php | 30 +++++++++++++++++++++++++ tests/.snapshots/Failure.php.inc | 2 +- tests/.snapshots/success.txt | 14 +++++++++++- tests/Features/Expect/toHaveMethod.php | 28 +++++++++++++++++++++++ tests/Features/Expect/toHaveMethods.php | 30 +++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 tests/Features/Expect/toHaveMethod.php create mode 100644 tests/Features/Expect/toHaveMethods.php diff --git a/src/Mixins/Expectation.php b/src/Mixins/Expectation.php index 886ffab2..afec5ea0 100644 --- a/src/Mixins/Expectation.php +++ b/src/Mixins/Expectation.php @@ -302,6 +302,36 @@ final class Expectation return $this; } + /** + * Asserts that the value has the method $name. + * + * @return self + */ + public function toHaveMethod(string $name, string $message = ''): self + { + $this->toBeObject(); + + // @phpstan-ignore-next-line + Assert::assertTrue(method_exists($this->value, $name), $message); + + return $this; + } + + /** + * Asserts that the value has the provided methods $names. + * + * @param iterable $names + * @return self + */ + public function toHaveMethods(iterable $names, string $message = ''): self + { + foreach ($names as $name) { + $this->toHaveMethod($name, message: $message); + } + + return $this; + } + /** * Asserts that two variables have the same value. * diff --git a/tests/.snapshots/Failure.php.inc b/tests/.snapshots/Failure.php.inc index 01046cc7..51b54578 100644 --- a/tests/.snapshots/Failure.php.inc +++ b/tests/.snapshots/Failure.php.inc @@ -1,6 +1,6 @@ ##teamcity[testSuiteStarted name='Tests/tests/Failure' locationHint='file://tests/.tests/Failure.php' flowId='1234'] ##teamcity[testStarted name='it can fail with comparison' locationHint='pest_qn://tests/.tests/Failure.php::it can fail with comparison' flowId='1234'] -##teamcity[testFailed name='it can fail with comparison' message='Failed asserting that true matches expected false.' details='at src/Mixins/Expectation.php:312|nat src/Support/ExpectationPipeline.php:75|nat src/Support/ExpectationPipeline.php:79|nat src/Expectation.php:300|nat tests/.tests/Failure.php:6|nat src/Factories/TestCaseMethodFactory.php:106|nat src/Concerns/Testable.php:262|nat src/Support/ExceptionTrace.php:28|nat src/Concerns/Testable.php:262|nat src/Concerns/Testable.php:217|nat src/Kernel.php:79' type='comparisonFailure' actual='true' expected='false' flowId='1234'] +##teamcity[testFailed name='it can fail with comparison' message='Failed asserting that true matches expected false.' details='at src/Mixins/Expectation.php:342|nat src/Support/ExpectationPipeline.php:75|nat src/Support/ExpectationPipeline.php:79|nat src/Expectation.php:300|nat tests/.tests/Failure.php:6|nat src/Factories/TestCaseMethodFactory.php:106|nat src/Concerns/Testable.php:262|nat src/Support/ExceptionTrace.php:28|nat src/Concerns/Testable.php:262|nat src/Concerns/Testable.php:217|nat src/Kernel.php:79' type='comparisonFailure' actual='true' expected='false' flowId='1234'] ##teamcity[testFinished name='it can fail with comparison' duration='100000' flowId='1234'] ##teamcity[testStarted name='it can be ignored because of no assertions' locationHint='pest_qn://tests/.tests/Failure.php::it can be ignored because of no assertions' flowId='1234'] ##teamcity[testIgnored name='it can be ignored because of no assertions' message='This test did not perform any assertions' details='' flowId='1234'] diff --git a/tests/.snapshots/success.txt b/tests/.snapshots/success.txt index e80dff6b..986c03c4 100644 --- a/tests/.snapshots/success.txt +++ b/tests/.snapshots/success.txt @@ -556,6 +556,18 @@ ✓ it fails ✓ it fails with message + PASS Tests\Features\Expect\toHaveMethod + ✓ pass + ✓ failures + ✓ failures with message + ✓ not failures + + PASS Tests\Features\Expect\toHaveMethods + ✓ pass + ✓ failures + ✓ failures with custom message + ✓ not failures + PASS Tests\Features\Expect\toHaveProperties ✓ pass ✓ failures @@ -902,4 +914,4 @@ PASS Tests\Visual\Version ✓ visual snapshot of help command output - Tests: 4 incomplete, 4 todos, 18 skipped, 625 passed (1512 assertions) \ No newline at end of file + Tests: 4 incomplete, 4 todos, 18 skipped, 633 passed (1552 assertions) \ No newline at end of file diff --git a/tests/Features/Expect/toHaveMethod.php b/tests/Features/Expect/toHaveMethod.php new file mode 100644 index 00000000..421c1ddd --- /dev/null +++ b/tests/Features/Expect/toHaveMethod.php @@ -0,0 +1,28 @@ +toHaveMethod('foo') + ->and($object)->toHaveMethod('foo') + ->and($object)->not->toHaveMethod('fooNull'); +}); + +test('failures', function () use ($object) { + expect($object)->toHaveMethod('bar'); +})->throws(ExpectationFailedException::class); + +test('failures with message', function () use ($object) { + expect($object)->toHaveMethod(name: 'bar', message: 'oh no!'); +})->throws(ExpectationFailedException::class, 'oh no!'); + +test('not failures', function () use ($object) { + expect($object)->not->toHaveMethod('foo'); +})->throws(ExpectationFailedException::class); diff --git a/tests/Features/Expect/toHaveMethods.php b/tests/Features/Expect/toHaveMethods.php new file mode 100644 index 00000000..a02a3275 --- /dev/null +++ b/tests/Features/Expect/toHaveMethods.php @@ -0,0 +1,30 @@ +toHaveMethods(['foo', 'bar']); +}); + +test('failures', function () use ($object) { + expect($object)->toHaveMethods(['foo', 'bar', 'baz']); +})->throws(ExpectationFailedException::class); + +test('failures with custom message', function () use ($object) { + expect($object)->toHaveMethods(['foo', 'bar', 'baz'], 'oh no!'); +})->throws(ExpectationFailedException::class, 'oh no!'); + +test('not failures', function () use ($object) { + expect($object)->not->toHaveMethods(['foo', 'bar']); +})->throws(ExpectationFailedException::class);