This commit is contained in:
Nuno Maduro
2024-07-20 14:15:28 +01:00
parent a7553b7593
commit b3c8c24aea
8 changed files with 87 additions and 50 deletions

View File

@ -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'))
);
}

View File

@ -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'))
);
}
/**

View File

@ -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)
Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 13 todos, 24 skipped, 1074 passed (2626 assertions)

View File

@ -1,13 +0,0 @@
<?php
use Pest\Arch\Exceptions\ArchExpectationFailedException;
use Pest\Expectation;
use Tests\Fixtures\Inheritance\ExampleTest;
it('passes', function () {
expect(Expectation::class)->toHaveAllMethodsDocumented();
});
it('fails', function () {
expect(ExampleTest::class)->toHaveAllMethodsDocumented();
})->throws(ArchExpectationFailedException::class);

View File

@ -1,13 +0,0 @@
<?php
use Pest\Arch\Exceptions\ArchExpectationFailedException;
use Pest\Expectation;
use Tests\Fixtures\Inheritance\ExampleTest;
it('passes', function () {
expect(Expectation::class)->toHaveAllPropertiesDocumented();
});
it('fails', function () {
expect(ExampleTest::class)->toHaveAllPropertiesDocumented();
})->throws(ArchExpectationFailedException::class);

View File

@ -0,0 +1,19 @@
<?php
use Pest\Arch\Exceptions\ArchExpectationFailedException;
use Pest\Configuration;
use Pest\Expectation;
use Tests\Fixtures\Inheritance\ExampleTest;
it('passes', function () {
expect(Expectation::class)->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);

View File

@ -0,0 +1,19 @@
<?php
use Pest\Arch\Exceptions\ArchExpectationFailedException;
use Pest\Expectation;
use Pest\Factories\TestCaseFactory;
use Tests\Fixtures\Inheritance\ExampleTest;
it('passes', function () {
expect(Expectation::class)->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);

View File

@ -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();