diff --git a/src/Expectation.php b/src/Expectation.php index 751dcbe5..1455f81e 100644 --- a/src/Expectation.php +++ b/src/Expectation.php @@ -465,19 +465,18 @@ final class Expectation /** * Asserts that the given expectation target have all methods documented. */ - public function toHaveAllMethodsDocumented(): ArchExpectation + public function toHaveMethodsDocumented(): ArchExpectation { return Targeted::make( $this, fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || array_filter( $object->reflectionClass->getMethods(), - fn (ReflectionMethod $method): bool => - (enum_exists($object->name) === false || in_array($method->name, ['from', 'tryFrom', 'cases'], true) === false) - && realpath($method->getFileName() ?: '/') === realpath($object->path) + fn (ReflectionMethod $method): bool => (enum_exists($object->name) === false || in_array($method->name, ['from', 'tryFrom', 'cases'], true) === false) + && realpath($method->getFileName() ?: '/') === realpath($object->path) // @phpstan-ignore-line && $method->getDocComment() === false, ) === [], - 'to have all methods documented', + 'to have methods with documentation / annotations', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')) ); } @@ -485,20 +484,19 @@ final class Expectation /** * Asserts that the given expectation target have all properties documented. */ - public function toHaveAllPropertiesDocumented(): ArchExpectation + public function toHavePropertiesDocumented(): ArchExpectation { return Targeted::make( $this, fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || array_filter( $object->reflectionClass->getProperties(), - fn (ReflectionProperty $property): bool => - (enum_exists($object->name) === false || in_array($property->name, ['value', 'name'], true) === false) - && realpath($property->getDeclaringClass()->getFileName() ?: '/') === realpath($object->path) + fn (ReflectionProperty $property): bool => (enum_exists($object->name) === false || in_array($property->name, ['value', 'name'], true) === false) + && realpath($property->getDeclaringClass()->getFileName() ?: '/') === realpath($object->path) // @phpstan-ignore-line && $property->isPromoted() === false && $property->getDocComment() === false, ) === [], - 'to have all properties documented', + 'to have properties with documentation / annotations', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')) ); } diff --git a/src/Expectations/OppositeExpectation.php b/src/Expectations/OppositeExpectation.php index 061e9f68..1f07f8fe 100644 --- a/src/Expectations/OppositeExpectation.php +++ b/src/Expectations/OppositeExpectation.php @@ -21,6 +21,8 @@ use Pest\Support\Exporter; use PHPUnit\Architecture\Elements\ObjectDescription; use PHPUnit\Framework\AssertionFailedError; use PHPUnit\Framework\ExpectationFailedException; +use ReflectionMethod; +use ReflectionProperty; /** * @internal @@ -99,17 +101,40 @@ final class OppositeExpectation /** * Not supported. */ - public function toHaveAllMethodsDocumented(): ArchExpectation + public function toHaveMethodsDocumented(): ArchExpectation { - throw InvalidExpectation::fromMethods(['not', 'toHaveAllMethodsDocumented']); + return Targeted::make( + $this->original, + fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false + || array_filter( + $object->reflectionClass->getMethods(), + fn (ReflectionMethod $method): bool => (enum_exists($object->name) === false || in_array($method->name, ['from', 'tryFrom', 'cases'], true) === false) + && realpath($method->getFileName() ?: '/') === realpath($object->path) // @phpstan-ignore-line + && $method->getDocComment() !== false, + ) === [], + 'to have methods without documentation / annotations', + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')) + ); } /** * Not supported. */ - public function toHaveAllPropertiesDocumented(): ArchExpectation + public function toHavePropertiesDocumented(): ArchExpectation { - throw InvalidExpectation::fromMethods(['not', 'toHaveAllPropertiesDocumented']); + return Targeted::make( + $this->original, + fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false + || array_filter( + $object->reflectionClass->getProperties(), + fn (ReflectionProperty $property): bool => (enum_exists($object->name) === false || in_array($property->name, ['value', 'name'], true) === false) + && realpath($property->getDeclaringClass()->getFileName() ?: '/') === realpath($object->path) // @phpstan-ignore-line + && $property->isPromoted() === false + && $property->getDocComment() !== false, + ) === [], + 'to have properties without documentation / annotations', + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')) + ); } /** diff --git a/tests/.snapshots/success.txt b/tests/.snapshots/success.txt index 575a192b..0b9ef423 100644 --- a/tests/.snapshots/success.txt +++ b/tests/.snapshots/success.txt @@ -715,14 +715,6 @@ ✓ failures with custom message ✓ not failures - PASS Tests\Features\Expect\toHaveAllMethodsDocumented - ✓ it passes - ✓ it fails - - PASS Tests\Features\Expect\toHaveAllPropertiesDocumented - ✓ it passes - ✓ it fails - PASS Tests\Features\Expect\toHaveAttribute ✓ class has attribute ✓ opposite class has attribute @@ -823,6 +815,11 @@ ✓ failures with custom message ✓ not failures + PASS Tests\Features\Expect\toHaveMethodsDocumented + ✓ it passes + ✓ it fails 1 + ✓ it fails 2 + PASS Tests\Features\Expect\toHavePrefix ✓ missing prefix ✓ has prefix @@ -835,6 +832,11 @@ ✓ failures with custom message ✓ not failures + PASS Tests\Features\Expect\toHavePropertiesDocumented + ✓ it passes + ✓ it fails 1 + ✓ it fails 2 + PASS Tests\Features\Expect\toHaveProperty ✓ pass ✓ failures @@ -1533,4 +1535,4 @@ WARN Tests\Visual\Version - visual snapshot of help command output - Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 13 todos, 24 skipped, 1072 passed (2620 assertions) \ No newline at end of file + Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 13 todos, 24 skipped, 1074 passed (2626 assertions) \ No newline at end of file diff --git a/tests/Features/Expect/toHaveAllMethodsDocumented.php b/tests/Features/Expect/toHaveAllMethodsDocumented.php deleted file mode 100644 index c212c74a..00000000 --- a/tests/Features/Expect/toHaveAllMethodsDocumented.php +++ /dev/null @@ -1,13 +0,0 @@ -toHaveAllMethodsDocumented(); -}); - -it('fails', function () { - expect(ExampleTest::class)->toHaveAllMethodsDocumented(); -})->throws(ArchExpectationFailedException::class); diff --git a/tests/Features/Expect/toHaveAllPropertiesDocumented.php b/tests/Features/Expect/toHaveAllPropertiesDocumented.php deleted file mode 100644 index f8ad5b89..00000000 --- a/tests/Features/Expect/toHaveAllPropertiesDocumented.php +++ /dev/null @@ -1,13 +0,0 @@ -toHaveAllPropertiesDocumented(); -}); - -it('fails', function () { - expect(ExampleTest::class)->toHaveAllPropertiesDocumented(); -})->throws(ArchExpectationFailedException::class); diff --git a/tests/Features/Expect/toHaveMethodsDocumented.php b/tests/Features/Expect/toHaveMethodsDocumented.php new file mode 100644 index 00000000..abe9f259 --- /dev/null +++ b/tests/Features/Expect/toHaveMethodsDocumented.php @@ -0,0 +1,19 @@ +toHaveMethodsDocumented() + ->and(ExampleTest::class)->not->toHaveMethodsDocumented(); +}); + +it('fails 1', function () { + expect(ExampleTest::class)->toHaveMethodsDocumented(); +})->throws(ArchExpectationFailedException::class); + +it('fails 2', function () { + expect(Configuration::class)->not->toHaveMethodsDocumented(); +})->throws(ArchExpectationFailedException::class); diff --git a/tests/Features/Expect/toHavePropertiesDocumented.php b/tests/Features/Expect/toHavePropertiesDocumented.php new file mode 100644 index 00000000..8ea3cb96 --- /dev/null +++ b/tests/Features/Expect/toHavePropertiesDocumented.php @@ -0,0 +1,19 @@ +toHavePropertiesDocumented() + ->and(ExampleTest::class)->not->toHavePropertiesDocumented(); +}); + +it('fails 1', function () { + expect(ExampleTest::class)->toHavePropertiesDocumented(); +})->throws(ArchExpectationFailedException::class); + +it('fails 2', function () { + expect(TestCaseFactory::class)->not->toHavePropertiesDocumented(); +})->throws(ArchExpectationFailedException::class); diff --git a/tests/Visual/Parallel.php b/tests/Visual/Parallel.php index 66b5c629..f29c72f1 100644 --- a/tests/Visual/Parallel.php +++ b/tests/Visual/Parallel.php @@ -16,7 +16,7 @@ $run = function () { test('parallel', function () use ($run) { expect($run('--exclude-group=integration')) - ->toContain('Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 13 todos, 19 skipped, 1058 passed (2588 assertions)') + ->toContain('Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 13 todos, 19 skipped, 1060 passed (2594 assertions)') ->toContain('Parallel: 3 processes'); })->skipOnWindows();