chore: coding style changes

This commit is contained in:
nuno maduro
2026-08-07 14:52:56 +01:00
parent eb88513baf
commit 42d9b777bf
221 changed files with 139 additions and 3086 deletions
-5
View File
@@ -12,11 +12,6 @@ use Pest\Plugin\Loader;
*/
final class CallsAddsOutput
{
/**
* Executes the Plugin action.
*
* Provides an opportunity for any plugins that want to provide additional output after test execution.
*/
public static function execute(int $exitCode): int
{
$plugins = Loader::getPlugins(Plugins\AddsOutput::class);
-5
View File
@@ -12,11 +12,6 @@ use Pest\Plugin\Loader;
*/
final class CallsBoot
{
/**
* Executes the Plugin action.
*
* Provides an opportunity for any plugins to boot.
*/
public static function execute(): void
{
$plugins = Loader::getPlugins(Plugins\Bootable::class);
@@ -13,10 +13,6 @@ use Pest\Plugin\Loader;
final class CallsHandleArguments
{
/**
* Executes the Plugin action.
*
* Transform the input arguments by passing it to the relevant plugins.
*
* @param array<int, string> $argv
* @return array<int, string>
*/
@@ -13,10 +13,6 @@ use Pest\Plugin\Loader;
final class CallsHandleOriginalArguments
{
/**
* Executes the Plugin action.
*
* Transform the input arguments by passing it to the relevant plugins.
*
* @param array<int, string> $argv
*/
public static function execute(array $argv): void
-5
View File
@@ -12,11 +12,6 @@ use Pest\Plugin\Loader;
*/
final class CallsTerminable
{
/**
* Executes the Plugin action.
*
* Provides an opportunity for any plugins to terminate.
*/
public static function execute(): void
{
$plugins = Loader::getPlugins(Plugins\Terminable::class);
-3
View File
@@ -14,9 +14,6 @@ final class Bail implements HandlesArguments
{
use HandleArguments;
/**
* Handles the arguments, adding the `--stop-on-defect` when the `--bail` argument is present.
*/
public function handleArguments(array $arguments): array
{
if ($this->hasArgument('--bail', $arguments)) {
-6
View File
@@ -18,9 +18,6 @@ final class Cache implements HandlesArguments
{
use HandleArguments;
/**
* The temporary folder.
*/
private const string TEMPORARY_FOLDER = __DIR__
.DIRECTORY_SEPARATOR
.'..'
@@ -29,9 +26,6 @@ final class Cache implements HandlesArguments
.DIRECTORY_SEPARATOR
.'.temp';
/**
* Handles the arguments, adding the cache directory and the cache result arguments.
*/
public function handleArguments(array $arguments): array
{
if (! $this->hasArgument('--cache-directory', $arguments)) {
-8
View File
@@ -10,8 +10,6 @@ namespace Pest\Plugins\Concerns;
trait HandleArguments
{
/**
* Checks if the given argument exists on the arguments.
*
* @param array<int, string> $arguments
*/
public function hasArgument(string $argument, array $arguments): bool
@@ -30,8 +28,6 @@ trait HandleArguments
}
/**
* Adds the given argument and value to the list of arguments.
*
* @param array<int, string> $arguments
* @return array<int, string>
*/
@@ -43,8 +39,6 @@ trait HandleArguments
}
/**
* Pops the given argument from the arguments.
*
* @param array<int, string> $arguments
* @return array<int, string>
*/
@@ -61,8 +55,6 @@ trait HandleArguments
}
/**
* Pops the given argument and its value from the arguments, returning the value.
*
* @param array<int, string> $arguments
*/
public function popArgumentValue(string $argument, array &$arguments): ?string
-18
View File
@@ -18,9 +18,6 @@ final class Configuration implements HandlesArguments, Terminable
{
use HandleArguments;
/**
* The base PHPUnit file.
*/
public const string BASE_PHPUNIT_FILE = __DIR__
.DIRECTORY_SEPARATOR
.'..'
@@ -29,9 +26,6 @@ final class Configuration implements HandlesArguments, Terminable
.DIRECTORY_SEPARATOR
.'resources/base-phpunit.xml';
/**
* Handles the arguments, adding the cache directory and the cache result arguments.
*/
public function handleArguments(array $arguments): array
{
if ($this->hasArgument('--configuration', $arguments) || $this->hasArgument('-c', $arguments) || $this->hasCustomConfigurationFile()) {
@@ -43,9 +37,6 @@ final class Configuration implements HandlesArguments, Terminable
return $this->pushArgument((string) realpath($this->fromGeneratedConfigurationFile()), $arguments);
}
/**
* Get the configuration file from the generated configuration file.
*/
private function fromGeneratedConfigurationFile(): string
{
$path = $this->getTempPhpunitXmlPath();
@@ -63,9 +54,6 @@ final class Configuration implements HandlesArguments, Terminable
return $path;
}
/**
* Check if the configuration file is custom.
*/
private function hasCustomConfigurationFile(): bool
{
$cliConfiguration = (new CliConfigurationBuilder)->fromParameters([]);
@@ -74,17 +62,11 @@ final class Configuration implements HandlesArguments, Terminable
return is_string($configurationFile);
}
/**
* Get the temporary phpunit.xml path.
*/
private function getTempPhpunitXmlPath(): string
{
return getcwd().'/.pest.xml';
}
/**
* Terminates the plugin.
*/
public function terminate(): void
{
$path = $this->getTempPhpunitXmlPath();
+1 -22
View File
@@ -27,37 +27,19 @@ final class Coverage implements AddsOutput, HandlesArguments
private const string ONLY_COVERED_OPTION = 'only-covered';
/**
* Whether it should show the coverage or not.
*/
public bool $coverage = false;
/**
* Whether it should show the coverage or not.
*/
public bool $compact = false;
/**
* The minimum coverage.
*/
public float $coverageMin = 0.0;
/**
* The exactly coverage.
*/
public ?float $coverageExactly = null;
/**
* Whether it should show only covered files.
*/
public bool $showOnlyCovered = false;
/**
* Creates a new Plugin instance.
*/
public function __construct(private readonly OutputInterface $output)
{
// ..
//
}
/**
@@ -186,9 +168,6 @@ final class Coverage implements AddsOutput, HandlesArguments
return $exitCode;
}
/**
* Computes the comparable coverage to a percentage with one decimal.
*/
private function computeComparableCoverage(float $coverage): float
{
return floor($coverage * 10) / 10;
-12
View File
@@ -11,19 +11,10 @@ use Pest\Contracts\Plugins\HandlesArguments;
*/
final class Environment implements HandlesArguments
{
/**
* The continuous integration environment.
*/
public const string CI = 'ci';
/**
* The local environment.
*/
public const string LOCAL = 'local';
/**
* The current environment.
*/
private static ?string $name = null;
/**
@@ -42,9 +33,6 @@ final class Environment implements HandlesArguments
return array_values($arguments);
}
/**
* Gets the environment name.
*/
public static function name(?string $name = null): string
{
if (is_string($name)) {
+1 -7
View File
@@ -18,13 +18,10 @@ final readonly class Help implements HandlesArguments
{
use Concerns\HandleArguments;
/**
* Creates a new Plugin instance.
*/
public function __construct(
private OutputInterface $output
) {
// ..
//
}
/**
@@ -80,9 +77,6 @@ final readonly class Help implements HandlesArguments
return $arguments;
}
/**
* Colorizes the given string options.
*/
private function colorizeOptions(string $argument): string
{
return (string) preg_replace(
+1 -16
View File
@@ -17,14 +17,8 @@ use Symfony\Component\Console\Output\OutputInterface;
*/
final readonly class Init implements HandlesArguments
{
/**
* The option the triggers the init job.
*/
private const string INIT_OPTION = '--init';
/**
* The files that will be created.
*/
private const array STUBS = [
'phpunit.xml.stub' => 'phpunit.xml',
'Pest.php.stub' => 'tests/Pest.php',
@@ -33,15 +27,12 @@ final readonly class Init implements HandlesArguments
'Feature/ExampleTest.php.stub' => 'tests/Feature/ExampleTest.php',
];
/**
* Creates a new Plugin instance.
*/
public function __construct(
private TestSuite $testSuite,
private InputInterface $input,
private OutputInterface $output
) {
// ..
//
}
/**
@@ -63,9 +54,6 @@ final readonly class Init implements HandlesArguments
exit(0);
}
/**
* Initializes the tests directory.
*/
public function init(): void
{
$testsBaseDir = "{$this->testSuite->rootPath}/tests";
@@ -114,9 +102,6 @@ final readonly class Init implements HandlesArguments
(new Thanks($this->input, $this->output))();
}
/**
* Checks if laravel is installed through Composer
*/
private function isLaravelInstalled(): bool
{
return InstalledVersions::isInstalled('laravel/framework');
+1 -7
View File
@@ -15,18 +15,12 @@ final class Memory implements AddsOutput, HandlesArguments
{
use Concerns\HandleArguments;
/**
* If memory should be displayed.
*/
private bool $enabled = false;
/**
* Creates a new Plugin instance.
*/
public function __construct(
private readonly OutputInterface $output
) {
// ..
//
}
/**
-12
View File
@@ -15,9 +15,6 @@ use PHPUnit\Framework\Attributes\Group;
*/
final class Only implements Terminable
{
/**
* The temporary folder.
*/
private const string TEMPORARY_FOLDER = __DIR__
.DIRECTORY_SEPARATOR
.'..'
@@ -26,9 +23,6 @@ final class Only implements Terminable
.DIRECTORY_SEPARATOR
.'.temp';
/**
* Creates the lock file.
*/
public static function enable(TestCall|TestCaseMethodFactory $testCall, string $group = '__pest_only'): void
{
if ($testCall instanceof TestCall) {
@@ -59,9 +53,6 @@ final class Only implements Terminable
}
}
/**
* Checks if "only" mode is enabled.
*/
public static function isEnabled(): bool
{
$lockFile = self::TEMPORARY_FOLDER.DIRECTORY_SEPARATOR.'only.lock';
@@ -69,9 +60,6 @@ final class Only implements Terminable
return file_exists($lockFile);
}
/**
* Returns the group name.
*/
public static function group(): string
{
$lockFile = self::TEMPORARY_FOLDER.DIRECTORY_SEPARATOR.'only.lock';
-25
View File
@@ -36,9 +36,6 @@ final class Parallel implements HandlesArguments
*/
private const array UNSUPPORTED_ARGUMENTS = ['--todo', '--todos', '--retry', '--notes', '--issue', '--pr', '--pull-request', '--flaky'];
/**
* Whether the given command line arguments indicate that the test suite should be run in parallel.
*/
public static function isEnabled(): bool
{
$argv = new ArgvInput;
@@ -50,9 +47,6 @@ final class Parallel implements HandlesArguments
return $argv->hasParameterOption('-p');
}
/**
* If this code is running in a worker process rather than the main process.
*/
public static function isWorker(): bool
{
$argvValue = Arr::get($_SERVER, 'PARATEST');
@@ -62,9 +56,6 @@ final class Parallel implements HandlesArguments
return ((int) $argvValue) === 1;
}
/**
* Sets a global value that can be accessed by the parent process and all workers.
*/
public static function setGlobal(string $key, string|int|bool|Stringable $value): void
{
$data = ['value' => $value instanceof Stringable ? $value->__toString() : $value];
@@ -72,9 +63,6 @@ final class Parallel implements HandlesArguments
$_ENV[self::GLOBAL_PREFIX.$key] = json_encode($data, JSON_THROW_ON_ERROR);
}
/**
* Returns the given global value if one has been set.
*/
public static function getGlobal(string $key): string|int|bool|null
{
$placesToCheck = [$_SERVER, $_ENV];
@@ -110,8 +98,6 @@ final class Parallel implements HandlesArguments
}
/**
* Runs the test suite in parallel. This method will exit the process upon completion.
*
* @param array<int, string> $arguments
*/
private function runTestSuiteInParallel(array $arguments): int
@@ -135,8 +121,6 @@ final class Parallel implements HandlesArguments
}
/**
* Runs any handlers that have been registered to handle worker arguments, and returns the modified arguments.
*
* @param array<int, string> $arguments
* @return array<int, string>
*/
@@ -154,9 +138,6 @@ final class Parallel implements HandlesArguments
);
}
/**
* Builds an instance of the Paratest command.
*/
private function paratestCommand(): Application
{
/** @var non-empty-string $rootPath */
@@ -170,10 +151,6 @@ final class Parallel implements HandlesArguments
return $command;
}
/**
* Whether the command line arguments contain any arguments that are
* not supported or are suboptimal when running in parallel.
*/
private function hasArgumentsThatWouldBeFasterWithoutParallel(): bool
{
$arguments = new ArgvInput;
@@ -182,8 +159,6 @@ final class Parallel implements HandlesArguments
}
/**
* Removes any parallel arguments.
*
* @param array<int, string> $arguments
* @return array<int, string>
*/
@@ -37,8 +37,6 @@ final class Laravel implements HandlesArguments
}
/**
* Executes the given closure when running Laravel.
*
* @param array<int, string> $arguments
* @param Closure(array<int, string>): array<int, string> $closure
* @return array<int, string>
@@ -55,9 +53,6 @@ final class Laravel implements HandlesArguments
return $arguments;
}
/**
* Ensures the runner is resolvable.
*/
private function ensureRunnerIsResolvable(): void
{
ParallelRunner::resolveRunnerUsing( // @phpstan-ignore-line
@@ -66,8 +61,6 @@ final class Laravel implements HandlesArguments
}
/**
* Ensures the environment variables are set.
*
* @param array<int, string> $arguments
* @return array<int, string>
*/
@@ -89,8 +82,6 @@ final class Laravel implements HandlesArguments
}
/**
* Ensure the runner is set.
*
* @param array<int, string> $arguments
* @return array<int, string>
*/
@@ -15,9 +15,6 @@ final class Parallel implements HandlesArguments
{
use HandleArguments;
/**
* The list of arguments to remove.
*/
private const array ARGS_TO_REMOVE = [
'--parallel',
'-p',
@@ -25,9 +22,6 @@ final class Parallel implements HandlesArguments
'--cache-result',
];
/**
* Handles the arguments, removing the ones that are not needed, and adds the "runner" argument.
*/
public function handleArguments(array $arguments): array
{
$args = array_reduce(self::ARGS_TO_REMOVE, fn (array $args, string $arg): array => $this->popArgument($arg, $args), $arguments);
-3
View File
@@ -11,9 +11,6 @@ final class Pest implements HandlersWorkerArguments
{
use HandleArguments;
/**
* Handles the arguments, adding the "PEST_PARALLEL" environment variable to the global $_SERVER.
*/
public function handleWorkerArguments(array $arguments): array
{
$_SERVER['PEST_PARALLEL'] = '1';
@@ -21,9 +21,6 @@ final class CleanConsoleOutput extends ConsoleOutput
parent::doWrite($message, $newline);
}
/**
* Removes the opening headline, witch is not needed.
*/
private function isOpeningHeadline(string $message): bool
{
return str_contains($message, 'by Sebastian Bergmann and contributors.');
@@ -29,24 +29,12 @@ use function strlen;
*/
final class ResultPrinter
{
/**
* If the test should be marked as todo.
*/
public bool $lastWasTodo = false;
/**
* The "native" printer.
*/
public readonly Printer $printer;
/**
* The state.
*/
public int $passedTests = 0;
/**
* The "compact" printer.
*/
private readonly CompactPrinter $compactPrinter;
/** @var resource|null */
@@ -58,32 +58,17 @@ use function usleep;
*/
final class WrapperRunner implements RunnerInterface
{
/**
* The merged test result from the parallel run.
*/
public static ?TestResult $result = null;
/**
* The time to sleep between cycles.
*/
private const int 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> */
@@ -128,9 +113,6 @@ final class WrapperRunner implements RunnerInterface
/** @var non-empty-string[] */
private readonly array $parameters;
/**
* The code coverage filter registry.
*/
private CodeCoverageFilterRegistry $codeCoverageFilterRegistry;
public function __construct(
@@ -190,8 +172,6 @@ final class WrapperRunner implements RunnerInterface
}
/**
* Handles Laravel Herd's debug and coverage modes.
*
* @param array<string> $parameters
* @return array<string>
*/
@@ -352,7 +332,6 @@ final class WrapperRunner implements RunnerInterface
private function destroyWorker(int $token): void
{
$this->workers[$token]->stop();
// We need to wait for ApplicationForWrapperWorker::end to end
while ($this->workers[$token]->isRunning()) {
usleep(self::CYCLE_SLEEP);
}
@@ -612,8 +591,6 @@ final class WrapperRunner implements RunnerInterface
}
/**
* Returns the test files to be executed.
*
* @return array<int, non-empty-string>
*/
private function getTestFiles(SuiteLoader $suiteLoader): array
@@ -27,9 +27,6 @@ use function Termwind\terminal;
*/
final class CompactPrinter
{
/**
* The number of processed tests.
*/
private int $processed = 0;
/**
@@ -48,21 +45,15 @@ final class CompactPrinter
'F' => ['red', ''],
];
/**
* Creates a new instance of the Compact Printer.
*/
public function __construct(
private readonly Terminal $terminal,
private readonly OutputInterface $output,
private readonly Style $style,
private readonly int $compactSymbolsPerLine,
) {
// ..
//
}
/**
* Creates a new instance of the Compact Printer.
*/
public static function default(bool $decorated = true): self
{
return new self(
@@ -73,17 +64,11 @@ final class CompactPrinter
);
}
/**
* Output an empty line in the console. Useful for providing a little breathing room.
*/
public function newLine(): void
{
render('<div class="py-1"></div>');
}
/**
* Outputs the given description item from the ProgressPrinter as a gorgeous, colored symbol.
*/
public function descriptionItem(string $item): void
{
[$color, $icon] = self::LOOKUP_TABLE[$item] ?? self::LOOKUP_TABLE['.'];
@@ -104,9 +89,6 @@ final class CompactPrinter
$this->processed++;
}
/**
* Outputs all errors from the given state using Collision's beautiful error output.
*/
public function errors(State $state): void
{
$this->output->writeln('');
@@ -114,9 +96,6 @@ final class CompactPrinter
$this->style->writeErrorsSummary($state);
}
/**
* Outputs a clean recap of the test run, including the number of tests, assertions, and failures.
*/
public function recap(State $state, PHPUnitTestResult $testResult, Duration $duration, Options $options): void
{
assert($this->output instanceof ConsoleOutput);
-64
View File
@@ -27,16 +27,9 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
private const string SHARD_OPTION = 'shard';
/**
* The maximum length allowed for the filter argument.
* While ARG_MAX can be 2MB, individual arguments are often limited to 128KB (MAX_ARG_STRLEN).
* Practical limits in CI environments (like Docker or pipeline runners) can be even lower.
*/
private const int MAX_FILTER_LENGTH = 32768;
/**
* The shard index and total number of shards.
*
* @var array{
* index: int,
* total: int,
@@ -46,43 +39,24 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
*/
private static ?array $shard = null;
/**
* Whether to update the shards.json file.
*/
private static bool $updateShards = false;
/**
* Whether time-balanced sharding was used.
*/
private static bool $timeBalanced = false;
/**
* Whether the shards.json file is outdated.
*/
private static bool $shardsOutdated = false;
/**
* Whether the test suite passed.
*/
private static bool $passed = false;
/**
* Collected timings from workers or subscribers.
*
* @var array<string, float>|null
*/
private static ?array $collectedTimings = null;
/**
* The canonical list of test classes from --list-tests.
*
* @var list<string>|null
*/
private static ?array $knownTests = null;
/**
* Creates a new Plugin instance.
*/
public function __construct(
private readonly OutputInterface $output,
) {
@@ -162,8 +136,6 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
}
/**
* Handles the --update-shards argument.
*
* @param array<int, string> $arguments
* @return array<int, string>
*/
@@ -192,8 +164,6 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
}
/**
* Returns all tests that the test suite would run.
*
* @param list<string> $arguments
* @return list<string>
*/
@@ -223,8 +193,6 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
}
/**
* Builds the subprocess command used to enumerate tests via `--list-tests`.
*
* @param list<string> $arguments
* @return list<string>
*/
@@ -236,8 +204,6 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
}
/**
* Parses `--list-tests` output into a unique list of test class FQCNs.
*
* @return list<string>
*/
private function parseListTestsOutput(string $output): array
@@ -248,8 +214,6 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
}
/**
* Builds the filter argument for the given tests to run.
*
* @param array<int, string> $testsToRun
*/
private function buildFilterArgument(array $testsToRun): string
@@ -289,8 +253,6 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
}
/**
* Ensures that the filter length is safe for the current environment.
*
* @throws InvalidOption
*/
private function ensureFilterLengthIsSafe(string $filter): void
@@ -308,9 +270,6 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
}
}
/**
* Adds output after the Test Suite execution.
*/
public function addOutput(int $exitCode): int
{
self::$passed = $exitCode === 0;
@@ -357,9 +316,6 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
return $exitCode;
}
/**
* Terminates the plugin.
*/
public function terminate(): void
{
if (! self::$updateShards) {
@@ -386,8 +342,6 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
}
/**
* Collects timings from subscribers or worker temp files.
*
* @return array<string, float>
*/
private function collectTimings(): array
@@ -401,9 +355,6 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
return EnsureShardTimingsAreCollected::timings();
}
/**
* Writes the current worker's timing data to a temp file.
*/
private function writeWorkerTimings(): void
{
$timings = EnsureShardTimingsAreCollected::timings();
@@ -424,8 +375,6 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
}
/**
* Reads and merges timing data from all worker temp files.
*
* @return array<string, float>
*/
private function readWorkerTimings(string $runId): array
@@ -458,9 +407,6 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
return $merged;
}
/**
* Returns the path to shards.json.
*/
private function shardsPath(): string
{
$testSuite = TestSuite::getInstance();
@@ -469,8 +415,6 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
}
/**
* Loads the timings from shards.json.
*
* @return array<string, float>|null
*/
private function loadShardsFile(): ?array
@@ -497,8 +441,6 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
}
/**
* Partitions tests across shards using the LPT (Longest Processing Time) algorithm.
*
* @param list<string> $tests
* @param array<string, float> $timings
* @return list<list<string>>
@@ -536,8 +478,6 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
}
/**
* Calculates the median of an array of floats.
*
* @param list<float> $values
*/
private function median(array $values): float
@@ -555,8 +495,6 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
}
/**
* Writes the timings to shards.json.
*
* @param array<string, float> $timings
*/
private function writeTimings(array $timings): void
@@ -586,8 +524,6 @@ final class Shard implements AddsOutput, HandlesArguments, Terminable
}
/**
* Returns the shard information.
*
* @return array{index: int, total: int}
*/
public static function getShard(InputInterface $input): array
-7
View File
@@ -14,9 +14,6 @@ final class Snapshot implements HandlesArguments
{
use Concerns\HandleArguments;
/**
* Whether snapshots should be updated on this run.
*/
public static bool $updateSnapshots = false;
/**
@@ -48,8 +45,6 @@ final class Snapshot implements HandlesArguments
}
/**
* Options that take a value as the next argument (rather than via "=value").
*
* @var list<string>
*/
private const array FLAGS_WITH_VALUES = [
@@ -89,8 +84,6 @@ final class Snapshot implements HandlesArguments
];
/**
* Determines whether the command targets the entire suite (no filter, no path).
*
* @param array<int, string> $arguments
*/
private function isFullRun(array $arguments): bool
-14
View File
@@ -105,8 +105,6 @@ final class Tia implements AddsOutput, HandlesArguments, HandlesOriginalArgument
private const string DEFAULT_BRANCH = 'main';
/**
* PHPUnit/Pest CLI flags whose subsequent argument is a value, not a path.
*
* @var list<string>
*/
private const array VALUE_TAKING_FLAGS = [
@@ -354,7 +352,6 @@ final class Tia implements AddsOutput, HandlesArguments, HandlesOriginalArgument
/**
* Mirrors {@see HandleArguments::hasArgument()} for
* use from static contexts — matches both `--flag` and `--flag=value`.
*
* @param array<int, string> $arguments
*/
@@ -1626,10 +1623,6 @@ final class Tia implements AddsOutput, HandlesArguments, HandlesOriginalArgument
}
/**
* Union of two per-test edge maps — piggybacked line-coverage edges plus
* the recorder's link-tracked edges (rendered Blade views, ...), which
* never appear in line coverage.
*
* @param array<string, array<int, string>> $coverage
* @param array<string, array<int, string>> $linked
* @return array<string, array<int, string>>
@@ -2127,13 +2120,6 @@ final class Tia implements AddsOutput, HandlesArguments, HandlesOriginalArgument
return implode(', ', array_keys($seen));
}
/**
* The path from the git repository root down to $projectRoot (e.g.
* `laravel-app`) when the project is nested inside a larger repo, or `null`
* when the project root is itself the repo root (or git is unavailable).
* TIA requires the two to coincide: git reports and addresses paths
* relative to the repo root, while the dependency graph is project-relative.
*/
private function gitSubdirectoryPrefix(string $projectRoot): ?string
{
return new Git($projectRoot)->subdirectoryPrefix();
-5
View File
@@ -178,7 +178,6 @@ final readonly class ChangedFiles
implode("\x00", array_keys($candidates)),
);
// `check-ignore` exits 1 when nothing matched — that is not a failure.
if ($result['exitCode'] !== 0 && $result['exitCode'] !== 1) {
throw new MissingDependency('Tia mode', 'git');
}
@@ -291,10 +290,6 @@ final readonly class ChangedFiles
return $this->git->hasCommits();
}
/**
* Working-tree scans get a longer leash than metadata queries — on a large
* repository with a cold cache, `status` and `diff` are not instant.
*/
private function scan(): Git
{
return $this->git->withTimeout(60.0);
-4
View File
@@ -9,9 +9,5 @@ namespace Pest\Plugins\Tia\Contracts;
*/
interface Ci
{
/**
* The default branch advertised by this CI, or `null` when the run
* does not happen on it — or when it exposes no such information.
*/
public function defaultBranch(): ?string;
}
-5
View File
@@ -164,15 +164,10 @@ final class CoverageMerger
return null;
}
// Legacy `--coverage-php` format: a serialized `CodeCoverage` object.
if ($value instanceof CodeCoverage) {
return $value;
}
// Since phpunit/php-code-coverage 14, `--coverage-php` writes the report
// as a serialized array (`['codeCoverage' => ..., 'testResults' => ...,
// 'basePath' => ...]`) rather than a `CodeCoverage` object, so it has to
// be rebuilt into one before it can be merged.
return self::coverageFromSerializedData($reportPath);
}
-13
View File
@@ -35,19 +35,13 @@ final readonly class Fingerprint
'composer_lock' => self::composerLockHash($projectRoot),
'phpunit_xml' => self::trackedHash($projectRoot, 'phpunit.xml'),
'phpunit_xml_dist' => self::trackedHash($projectRoot, 'phpunit.xml.dist'),
// 'pest_factory' => self::contentHashOrNull(__DIR__.'/../../Factories/TestCaseFactory.php'),
// 'pest_method_factory' => self::contentHashOrNull(__DIR__.'/../../Factories/TestCaseMethodFactory.php'),
'vite_config' => self::viteConfigHash($projectRoot),
// 'package_json' => self::packageJsonHash($projectRoot),
'package_lock' => self::packageLockHash($projectRoot),
'js_config' => self::jsConfigHash($projectRoot),
// 'composer_json' => self::composerJsonHash($projectRoot),
],
'environmental' => [
'php_minor' => PHP_MAJOR_VERSION,
// 'extensions' => self::extensionsFingerprint($projectRoot),
// 'env_files' => self::envFilesHash($projectRoot),
],
];
}
@@ -267,13 +261,6 @@ final readonly class Fingerprint
return self::hashIfExists($projectRoot.'/'.$relativePath);
}
/**
* Returns true when the file exists and is not gitignored.
*
* Gitignored lockfiles (e.g. `package-lock.json` excluded from the repo)
* regenerate per-machine with OS-specific optional deps, which would
* otherwise force a fingerprint mismatch on every fetched baseline.
*/
private static function isTrackedByGit(string $projectRoot, string $relativePath): bool
{
if (! is_file($projectRoot.'/'.$relativePath)) {
-60
View File
@@ -19,10 +19,6 @@ use PHPUnit\TextUI\Configuration\Registry;
final class Graph
{
/**
* Livewire's generated-file directories, relative to its cache directory,
* mapped to the extension each one writes. Only these three land in the
* graph — scripts and styles are never rendered or executed by PHP.
*
* @var array<string, string>
*/
private const array LIVEWIRE_GENERATED_PATHS = [
@@ -184,9 +180,6 @@ final class Graph
*/
private function applyMigrationChanges(array $migrationPaths, array &$affectedSet): array
{
// With no recorded table usage at all, table intersection can never
// select anything — route every migration change through the
// watch-pattern fallback instead of silently skipping tests.
if ($this->testTables === []) {
return $migrationPaths;
}
@@ -231,7 +224,6 @@ final class Graph
* @param list<string> $nonMigrationPaths
* @param array<string, true> $affectedSet
* @return array{0: array<string, true>, 1: array<string, true>, 2: array<string, true>}
* globalFrontendRuntimeFiles, preciselyHandledPages, sharedFilesResolved
*/
private function applyInertiaChanges(array $nonMigrationPaths, array &$affectedSet): array
{
@@ -440,9 +432,6 @@ final class Graph
}
/**
* A changed file inside the configured test suites is itself the unit of
* work — always run it (new untracked tests, edited tests, renames).
*
* @param list<string> $nonMigrationPaths
* @param array<string, true> $affectedSet
*/
@@ -488,9 +477,6 @@ final class Graph
$bladeAffected = $this->affectedByStaticBladeUsage($rel);
// Only a walk that actually selected tests counts as handled — a
// component whose usage the static walk missed must still reach
// the watch-pattern fallback instead of being silently swallowed.
if ($bladeAffected !== []) {
foreach ($bladeAffected as $testFile) {
$affectedSet[$testFile] = true;
@@ -504,11 +490,6 @@ final class Graph
}
/**
* Livewire compiles single- and multi-file components into generated files
* under the (per-worker) compiled view directory, so the graph only ever
* holds those generated paths — never the component source the developer
* edited. Reproduce Livewire's hash to walk that mapping backwards.
*
* @param list<string> $nonMigrationPaths
* @param array<string, true> $affectedSet
* @return array<string, true>
@@ -553,11 +534,6 @@ final class Graph
}
/**
* The component sources whose Livewire hash a changed file could carry: the
* file itself when it is a single-file component, and its directory when it
* sits inside a multi-file component — a class or asset sibling of the view
* is compiled under the directory's hash, not its own.
*
* @return list<string>
*/
private function livewireSourcePaths(string $rel): array
@@ -577,12 +553,6 @@ final class Graph
return $sourcePaths;
}
/**
* Mirrors Livewire\Finder\Finder::hasValidMultiFileComponentSource(): a
* multi-file component is a directory holding both "<name>.php" and
* "<name>.blade.php", where "<name>" is the directory name with the ⚡
* marker stripped, collapsed to "index" for the index convention.
*/
private function isLivewireMultiFileDirectory(string $componentDirectory): bool
{
$directoryName = basename($componentDirectory);
@@ -602,22 +572,12 @@ final class Graph
return is_file($source.'.php') && is_file($source.'.blade.php');
}
/**
* Mirrors Livewire\Compiler\CacheManager::getHash(): the first eight hex
* digits of md5() over the source path relative to base_path(), leading
* separator included. Should Livewire ever change that scheme, nothing
* matches and the watch-pattern fallback takes over again.
*/
private function livewireHash(string $sourcePath): string
{
return substr(md5(DIRECTORY_SEPARATOR.str_replace('/', DIRECTORY_SEPARATOR, $sourcePath)), 0, 8);
}
/**
* Index every Livewire-generated file already in the graph by its hash. The
* same component yields one entry per parallel worker, so a hash maps to a
* list of ids rather than a single one.
*
* @return array<string, list<int>>
*/
private function livewireGeneratedFileIds(): array
@@ -915,11 +875,6 @@ final class Graph
return $this->shouldRerunStatus(TestStatus::from($status));
}
/**
* Whether a cached result with this status must be re-executed rather
* than replayed, honouring the configured failOn* / displayDetailsOn*
* policies.
*/
public function shouldRerunStatus(TestStatus $testStatus): bool
{
if ($testStatus->isFailure() || $testStatus->isError()) {
@@ -1098,20 +1053,9 @@ final class Graph
}
/**
* Mark test files that executed under a recorded coverage session as "known",
* seeding an empty edge set for any that produced zero project-source edges.
*
* Without this, a test that covers no application source (e.g. a pure unit
* test asserting on language primitives) never becomes an edge key, so
* {@see self::knowsTest()} reports it as unknown and it re-runs on every TIA
* run. Recording it with an empty edge set lets it be replayed/skipped while
* unchanged; it is still re-run whenever its own file changes, via
* {@see self::applyTestFileChanges()}.
*
* Must only be called from the recording path, where coverage was actually
* collected — otherwise a missing edge set could mean "coverage was off",
* not "genuinely covered nothing".
*
* @param array<int, string> $testFiles Absolute or project-relative test file paths.
*/
public function markKnownTestFiles(array $testFiles): void
@@ -1539,7 +1483,6 @@ final class Graph
$names = [$name, str_replace('_', '-', $name)];
// Anonymous index components: components/card/index.blade.php resolves as <x-card>.
if (str_ends_with($name, '.index') && $name !== '.index') {
$base = substr($name, 0, -strlen('.index'));
@@ -1696,9 +1639,6 @@ final class Graph
}
/**
* Prune baseline result entries whose test files were just executed but whose
* test IDs are no longer present (e.g. the test method was removed or renamed).
*
* @param array<int, string> $touchedFiles Absolute or project-relative paths.
* @param array<int, string> $keepTestIds Test IDs that produced a result this run.
*/
-3
View File
@@ -28,9 +28,6 @@ final class JsModuleGraph
];
/**
* Candidate page directories, in priority order. Must stay in sync with
* `PAGE_DIR_CANDIDATES` in bin/pest-tia-vite-deps.mjs.
*
* @var list<string>
*/
private const array PAGE_DIR_CANDIDATES = [
-5
View File
@@ -50,11 +50,6 @@ final class Recorder
$this->captureCoverage = true;
}
/**
* Enable per-test link tracking (tables, Inertia components, database
* usage, rendered views) without driving pcov/xdebug — for runs where
* coverage edges are piggybacked from an existing PHPUnit coverage session.
*/
public function activateLinkTracking(): void
{
$this->active = true;
+1 -1
View File
@@ -58,7 +58,7 @@ final class SourceScope
$phpunitExcludes[] = self::normalise($dir->path());
}
} catch (Throwable) {
// Registry not initialized — fall back to project-root scanning.
//
}
$rootIncludes = self::topLevelProjectDirs($projectRoot);
-8
View File
@@ -11,9 +11,6 @@ final class TableExtractor
{
private const array DML_PREFIXES = ['select', 'insert', 'update', 'delete', 'with', 'replace'];
/**
* A single (optionally quoted) identifier segment.
*/
private const string IDENTIFIER = '(?:"[^"]+"|`[^`]+`|\[[^\]]+\]|\w+)';
/**
@@ -118,11 +115,6 @@ final class TableExtractor
return $out;
}
/**
* The table segment of a possibly schema-qualified identifier chain,
* e.g. `"public"."users"` or `analytics.events` yield `users` / `events`.
* Empty when any segment is schema metadata (`information_schema.tables`, ...).
*/
private static function unqualified(string $qualified): string
{
$name = '';
+1 -5
View File
@@ -9,10 +9,6 @@ use PHPUnit\TextUI\Configuration\Registry;
use Throwable;
/**
* Resolves the set of project-relative paths that are considered test files,
* driven by phpunit.xml's <testsuites>. Falls back to the runtime TestSuite
* configuration when no config file is present.
*
* @internal
*/
final readonly class TestPaths
@@ -63,7 +59,7 @@ final readonly class TestPaths
}
}
} catch (Throwable) {
// Registry not initialized — fall through to defaults.
//
}
if ($suffixes === []) {
-3
View File
@@ -13,9 +13,6 @@ final class Verbose implements HandlesArguments
{
use Concerns\HandleArguments;
/**
* The list of verbosity levels.
*/
private const array VERBOSITY_LEVELS = ['v', 'vv', 'vvv', 'q'];
/**