feat: toHaveAllMethodsDocumented and toHaveAllPropertiesDocumented

This commit is contained in:
Nuno Maduro
2024-07-19 14:03:59 +01:00
parent 99107544ff
commit f2691623cf
18 changed files with 154 additions and 4 deletions

View File

@ -11,6 +11,9 @@ use Pest\PendingCalls\UsesCall;
*/
final class Configuration
{
/**
* The filename of the configuration.
*/
private readonly string $filename;
/**

View File

@ -33,6 +33,8 @@ use Pest\Support\ExpectationPipeline;
use PHPUnit\Architecture\Elements\ObjectDescription;
use PHPUnit\Framework\ExpectationFailedException;
use ReflectionEnum;
use ReflectionMethod;
use ReflectionProperty;
/**
* @template TValue
@ -460,6 +462,43 @@ final class Expectation
);
}
/**
* Asserts that the given expectation target have all methods documented.
*/
public function toHaveAllMethodsDocumented(): ArchExpectation
{
return Targeted::make(
$this,
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false
|| array_filter(
$object->reflectionClass->getMethods(),
fn (ReflectionMethod $method): bool => $method->class === $object->name
&& $method->getDocComment() === false,
) === [],
'to have all methods documented',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))
);
}
/**
* Asserts that the given expectation target have all properties documented.
*/
public function toHaveAllPropertiesDocumented(): ArchExpectation
{
return Targeted::make(
$this,
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false
|| array_filter(
$object->reflectionClass->getProperties(),
fn (ReflectionProperty $property): bool => $property->class === $object->name
&& $property->isPromoted() === false
&& $property->getDocComment() === false,
) === [],
'to have all properties documented',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))
);
}
/**
* Asserts that the given expectation target use the "declare(strict_types=1)" declaration.
*/
@ -768,6 +807,9 @@ final class Expectation
return ToUseNothing::make($this);
}
/**
* Not supported.
*/
public function toBeUsed(): never
{
throw InvalidExpectation::fromMethods(['toBeUsed']);

View File

@ -17,6 +17,9 @@ use function expect;
*/
final class EachExpectation
{
/**
* Indicates if the expectation is the opposite.
*/
private bool $opposite = false;
/**

View File

@ -25,8 +25,14 @@ final class HigherOrderExpectation
*/
private Expectation|EachExpectation $expectation;
/**
* Indicates if the expectation is the opposite.
*/
private bool $opposite = false;
/**
* Indicates if the expectation should reset the value.
*/
private bool $shouldReset = false;
/**

View File

@ -96,6 +96,22 @@ final class OppositeExpectation
throw InvalidExpectation::fromMethods(['not', 'toHaveLineCountLessThan']);
}
/**
* Not supported.
*/
public function toHaveAllMethodsDocumented(): ArchExpectation
{
throw InvalidExpectation::fromMethods(['not', 'toHaveAllMethodsDocumented']);
}
/**
* Not supported.
*/
public function toHaveAllPropertiesDocumented(): ArchExpectation
{
throw InvalidExpectation::fromMethods(['not', 'toHaveAllPropertiesDocumented']);
}
/**
* Asserts that the given expectation target does not use the "declare(strict_types=1)" declaration.
*/

View File

@ -26,8 +26,14 @@ use PHPUnit\TestRunner\TestResult\TestResult as PhpUnitTestResult;
*/
final class Converter
{
/**
* The prefix for the test suite name.
*/
private const PREFIX = 'P\\';
/**
* The state generator.
*/
private readonly StateGenerator $stateGenerator;
/**

View File

@ -9,6 +9,9 @@ namespace Pest\Logging\TeamCity;
*/
final class ServiceMessage
{
/**
* The flow ID.
*/
private static ?int $flowId = null;
/**

View File

@ -43,8 +43,14 @@ use Symfony\Component\Console\Output\OutputInterface;
*/
final class TeamCityLogger
{
/**
* The current time.
*/
private ?HRTime $time = null;
/**
* Indicates if the summary test count has been printed.
*/
private bool $isSummaryTestCountPrinted = false;
/**

View File

@ -46,15 +46,27 @@ use function usleep;
*/
final class WrapperRunner implements RunnerInterface
{
/**
* The time to sleep between cycles.
*/
private const CYCLE_SLEEP = 10000;
/**
* The result printer.
*/
private readonly ResultPrinter $printer;
/**
* The timer.
*/
private readonly Timer $timer;
/** @var list<non-empty-string> */
private array $pending = [];
/**
* The exit code.
*/
private int $exitcode = -1;
/** @var array<positive-int,WrapperWorker> */
@ -84,6 +96,9 @@ final class WrapperRunner implements RunnerInterface
/** @var non-empty-string[] */
private readonly array $parameters;
/**
* The code coverage filter registry.
*/
private CodeCoverageFilterRegistry $codeCoverageFilterRegistry;
public function __construct(

View File

@ -13,6 +13,9 @@ use ReflectionParameter;
*/
final class Container
{
/**
* The instance of the container.
*/
private static ?Container $instance = null;
/**

View File

@ -14,15 +14,21 @@ use Symfony\Component\Process\Process;
final class GitDirtyTestCaseFilter implements TestCaseFilter
{
/**
* @var string[]|null
* @var array<int, string>|null
*/
private ?array $changedFiles = null;
/**
* Creates a new instance of the filter.
*/
public function __construct(private readonly string $projectRoot)
{
// ...
}
/**
* {@inheritdoc}
*/
public function accept(string $testCaseFilename): bool
{
if ($this->changedFiles === null) {
@ -41,6 +47,9 @@ final class GitDirtyTestCaseFilter implements TestCaseFilter
return in_array($relativePath, $this->changedFiles, true);
}
/**
* Loads the changed files.
*/
private function loadChangedFiles(): void
{
$process = new Process(['git', 'status', '--short', '--', '*.php']);