mirror of
https://github.com/pestphp/pest.git
synced 2026-09-05 22:33:35 +02:00
chore: refactors exceptions
This commit is contained in:
@@ -16,6 +16,6 @@ final class AfterAllAlreadyExist extends InvalidArgumentException implements Exc
|
||||
{
|
||||
public function __construct(string $filename)
|
||||
{
|
||||
parent::__construct(sprintf('The afterAll already exists in the filename [%s].', $filename));
|
||||
parent::__construct(sprintf('The [afterAll] hook is already defined in [%s]. Each test file may only define it once.', $filename));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,6 @@ final class AfterAllWithinDescribe extends InvalidArgumentException implements E
|
||||
{
|
||||
public function __construct(string $filename)
|
||||
{
|
||||
parent::__construct(sprintf('The afterAll method can not be used within describe functions. Filename [%s].', $filename));
|
||||
parent::__construct(sprintf('The [afterAll] hook may not be used inside a [describe] block. Please move it to the top level of [%s].', $filename));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,6 @@ final class AfterBeforeTestFunction extends InvalidArgumentException implements
|
||||
{
|
||||
public function __construct(string $filename)
|
||||
{
|
||||
parent::__construct('After method cannot be used with before the [test|it] functions in the filename ['.$filename.'].');
|
||||
parent::__construct(sprintf('The [after] hook may only be chained onto [beforeEach] inside a [describe] block. Please move it inside one in [%s].', $filename));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,6 @@ final class BeforeAllAlreadyExist extends InvalidArgumentException implements Ex
|
||||
{
|
||||
public function __construct(string $filename)
|
||||
{
|
||||
parent::__construct(sprintf('The beforeAll already exists in the filename [%s].', $filename));
|
||||
parent::__construct(sprintf('The [beforeAll] hook is already defined in [%s]. Each test file may only define it once.', $filename));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,6 @@ final class BeforeAllWithinDescribe extends InvalidArgumentException implements
|
||||
{
|
||||
public function __construct(string $filename)
|
||||
{
|
||||
parent::__construct(sprintf('The beforeAll method can not be used within describe functions. Filename [%s].', $filename));
|
||||
parent::__construct(sprintf('The [beforeAll] hook may not be used inside a [describe] block. Please move it to the top level of [%s].', $filename));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,6 @@ final class DatasetAlreadyExists extends InvalidArgumentException implements Exc
|
||||
{
|
||||
public function __construct(string $name, string $scope)
|
||||
{
|
||||
parent::__construct(sprintf('A dataset with the name [%s] already exists in scope [%s].', $name, $scope));
|
||||
parent::__construct(sprintf('A dataset named [%s] is already registered in [%s]. Please choose a different name.', $name, $scope));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,9 @@ final class DatasetArgumentsMismatch extends Exception
|
||||
public function __construct(int $requiredCount, int $suppliedCount)
|
||||
{
|
||||
if ($requiredCount <= $suppliedCount) {
|
||||
parent::__construct('Test argument names and dataset keys do not match');
|
||||
parent::__construct('The test arguments do not match the dataset keys. Please make sure each argument is named after a key in the dataset.');
|
||||
} else {
|
||||
parent::__construct(sprintf('Test expects %d arguments but dataset only provides %d', $requiredCount, $suppliedCount));
|
||||
parent::__construct(sprintf('The test expects [%d] argument(s), but the dataset only provides [%d].', $requiredCount, $suppliedCount));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,6 @@ final class DatasetDoesNotExist extends InvalidArgumentException implements Exce
|
||||
{
|
||||
public function __construct(string $name)
|
||||
{
|
||||
parent::__construct(sprintf("A dataset with the name [%s] does not exist. You can create it using `dataset('%s', ['a', 'b']);`.", $name, $name));
|
||||
parent::__construct(sprintf("A dataset named [%s] does not exist. You may create one using `dataset('%s', ['a', 'b']);`.", $name, $name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,11 @@ final class DatasetMissing extends BadFunctionCallException implements Exception
|
||||
public function __construct(string $file, string $name, array $arguments)
|
||||
{
|
||||
parent::__construct(sprintf(
|
||||
'A test with the description [%s] has [%d] argument(s) ([%s]) and no dataset(s) provided in [%s]',
|
||||
'The test [%s] in [%s] expects [%d] argument(s) ([%s]), but no dataset was provided. Please chain [with()] onto the test to supply one.',
|
||||
$name,
|
||||
$file,
|
||||
count($arguments),
|
||||
implode(', ', array_map(static fn (string $arg, string $type): string => sprintf('%s $%s', $type, $arg), array_keys($arguments), $arguments)),
|
||||
$file,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,6 @@ final class ExpectationNotFound extends Exception
|
||||
{
|
||||
public static function fromName(string $name): ExpectationNotFound
|
||||
{
|
||||
return new self("Expectation [$name] does not exist.");
|
||||
return new self("The expectation [$name] does not exist. You may register it using [expect()->extend()].");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,6 @@ final class FileOrFolderNotFound extends InvalidArgumentException implements Exc
|
||||
{
|
||||
public function __construct(string $filename)
|
||||
{
|
||||
parent::__construct(sprintf('The file or folder with the name [%s] could not be found.', $filename));
|
||||
parent::__construct(sprintf('The file or folder [%s] could not be found. Please check the path and try again.', $filename));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,6 @@ final class InvalidExpectation extends LogicException implements ExceptionInterf
|
||||
*/
|
||||
public static function fromMethods(array $methods): never
|
||||
{
|
||||
throw new self(sprintf('Expectation [%s] is not valid.', implode('->', $methods)));
|
||||
throw new self(sprintf('The expectation [%s] does not exist. Please check the spelling, or register it using [expect()->extend()].', implode('->', $methods)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,6 @@ final class InvalidExpectationValue extends InvalidArgumentException
|
||||
*/
|
||||
public static function expected(string $type): never
|
||||
{
|
||||
throw new self(sprintf('Invalid expectation value type. Expected [%s].', $type));
|
||||
throw new self(sprintf('This expectation may only be used on a value of type [%s].', $type));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,6 @@ final class InvalidPestCommand extends InvalidArgumentException implements Excep
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('Please run [./vendor/bin/pest] instead.');
|
||||
parent::__construct('Pest must be run through its own binary. Please run [./vendor/bin/pest] instead.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ final class InvalidTestClassName extends InvalidArgumentException implements Exc
|
||||
public static function fromClassName(string $filename, string $className): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'The test file [%s] would create the class [%s], which is not a valid PHP class name. Please rename the test file.',
|
||||
'The test file [%s] would create the class [%s], which is not a valid PHP class name. Please rename the file.',
|
||||
$filename,
|
||||
$className,
|
||||
));
|
||||
@@ -26,7 +26,7 @@ final class InvalidTestClassName extends InvalidArgumentException implements Exc
|
||||
public static function fromNamespace(string $filename, string $namespace, string $part): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'The test file [%s] would create the namespace [%s], which is not a valid PHP namespace, as [%s] may not be used as a namespace name. Please rename the folder in question.',
|
||||
'The test file [%s] would create the namespace [%s], which is not a valid PHP namespace, because [%s] may not be used as a namespace name. Please rename that folder.',
|
||||
$filename,
|
||||
$namespace,
|
||||
$part,
|
||||
|
||||
@@ -16,6 +16,6 @@ final class MissingDependency extends InvalidArgumentException implements Except
|
||||
{
|
||||
public function __construct(string $feature, string $dependency)
|
||||
{
|
||||
parent::__construct(sprintf('The feature [%s] requires [%s].', $feature, $dependency));
|
||||
parent::__construct(sprintf('The [%s] feature requires [%s]. Please install it and try again.', $feature, $dependency));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ final class ShouldNotHappen extends RuntimeException
|
||||
$message = $exception->getMessage();
|
||||
|
||||
parent::__construct(sprintf(<<<'EOF'
|
||||
This should not happen - please create an new issue here: https://github.com/pestphp/pest/issues
|
||||
This should not have happened. Please report it here: https://github.com/pestphp/pest/issues
|
||||
|
||||
Issue: %s
|
||||
PHP version: %s
|
||||
|
||||
@@ -16,6 +16,6 @@ final class TestAlreadyExist extends InvalidArgumentException implements Excepti
|
||||
{
|
||||
public function __construct(string $fileName, string $description)
|
||||
{
|
||||
parent::__construct(sprintf('A test with the description [%s] already exists in the filename [%s].', $description, $fileName));
|
||||
parent::__construct(sprintf('A test named [%s] already exists in [%s]. Please give this test a different description.', $description, $fileName));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ final class TestCaseAlreadyInUse extends InvalidArgumentException implements Exc
|
||||
public function __construct(string $inUse, string $newOne, string $folder)
|
||||
{
|
||||
parent::__construct(sprintf(
|
||||
'Test case [%s] can not be used. The folder [%s] already uses the test case [%s].',
|
||||
'The test case [%s] may not be used here. The folder [%s] is already bound to the test case [%s].',
|
||||
$newOne,
|
||||
$folder,
|
||||
$inUse,
|
||||
|
||||
@@ -16,6 +16,6 @@ final class TestCaseClassOrTraitNotFound extends InvalidArgumentException implem
|
||||
{
|
||||
public function __construct(string $testCaseClass)
|
||||
{
|
||||
parent::__construct(sprintf('The class [%s] was not found.', $testCaseClass));
|
||||
parent::__construct(sprintf('The class or trait [%s] could not be found. Please check the name, and make sure it is autoloadable.', $testCaseClass));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ final class TestClosureMustNotBeStatic extends InvalidArgumentException implemen
|
||||
{
|
||||
parent::__construct(
|
||||
sprintf(
|
||||
'Test closure must not be static. Please remove the [static] keyword from the [%s] method in [%s].',
|
||||
'Test closures may not be static. Please remove the [static] keyword from the test [%s] in [%s].',
|
||||
$method->description,
|
||||
$method->filename
|
||||
)
|
||||
|
||||
@@ -16,6 +16,6 @@ final class TestDescriptionMissing extends InvalidArgumentException implements E
|
||||
{
|
||||
public function __construct(string $fileName)
|
||||
{
|
||||
parent::__construct(sprintf('Test description is missing in the filename [%s].', $fileName));
|
||||
parent::__construct(sprintf('A test in [%s] is missing its description. Please give every test a description.', $fileName));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ final class TiaRequiresPestTests extends RuntimeException implements ExceptionIn
|
||||
public function __construct(private readonly string $className, string $filename)
|
||||
{
|
||||
parent::__construct(sprintf(
|
||||
'Tia mode requires only functional based Pest tests, but encountered PHPUnit class [%s] in [%s].',
|
||||
'Tia mode supports functional Pest tests only, but found the PHPUnit class [%s] in [%s]. Please convert it to a Pest test, or run without Tia.',
|
||||
$className,
|
||||
$filename,
|
||||
));
|
||||
|
||||
@@ -19,7 +19,7 @@ final class TiaRequiresRepositoryRoot extends RuntimeException implements Except
|
||||
public function __construct(private readonly string $subdirectoryPrefix)
|
||||
{
|
||||
parent::__construct(sprintf(
|
||||
'Tia mode requires the project root to be the git repository root, but it sits in the subdirectory [%s] of a larger repo.',
|
||||
'Tia mode requires the project root to be the git repository root, but this project sits in the subdirectory [%s] of a larger repository. Please give it its own repository to use Tia.',
|
||||
$this->subdirectoryPrefix,
|
||||
));
|
||||
}
|
||||
|
||||
+6
-6
@@ -318,7 +318,7 @@ final class Expectation
|
||||
|
||||
if (! is_object($this->value)) {
|
||||
throw new BadMethodCallException(sprintf(
|
||||
'Method "%s" does not exist in %s.',
|
||||
'Method [%s] does not exist in [%s].',
|
||||
$method,
|
||||
gettype($this->value)
|
||||
));
|
||||
@@ -534,7 +534,7 @@ final class Expectation
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => count(array_filter($methods, fn (string $method): bool => isset($object->reflectionClass) && $object->reflectionClass->hasMethod($method))) === count($methods),
|
||||
sprintf("to have method '%s'", implode("', '", $methods)),
|
||||
sprintf('to have method [%s]', implode('], [', $methods)),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
}
|
||||
@@ -659,7 +659,7 @@ final class Expectation
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && ($class === $object->reflectionClass->getName() || $object->reflectionClass->isSubclassOf($class)),
|
||||
sprintf("to extend '%s'", $class),
|
||||
sprintf('to extend [%s]', $class),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
}
|
||||
@@ -753,7 +753,7 @@ final class Expectation
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && str_starts_with($object->reflectionClass->getShortName(), $prefix),
|
||||
"to have prefix '{$prefix}'",
|
||||
"to have prefix [{$prefix}]",
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
}
|
||||
@@ -763,7 +763,7 @@ final class Expectation
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && str_ends_with($object->reflectionClass->getName(), $suffix),
|
||||
"to have suffix '{$suffix}'",
|
||||
"to have suffix [{$suffix}]",
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
}
|
||||
@@ -930,7 +930,7 @@ final class Expectation
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->getAttributes($attribute) !== [],
|
||||
"to have attribute '{$attribute}'",
|
||||
"to have attribute [{$attribute}]",
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ final readonly class OppositeExpectation
|
||||
},
|
||||
$methods === []
|
||||
? 'not to have public methods'
|
||||
: sprintf("not to have public methods besides '%s'", implode("', '", $methods)),
|
||||
: sprintf('not to have public methods besides [%s]', implode('], [', $methods)),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, (string) $state->contains)),
|
||||
);
|
||||
}
|
||||
@@ -337,7 +337,7 @@ final readonly class OppositeExpectation
|
||||
},
|
||||
$methods === []
|
||||
? 'not to have protected methods'
|
||||
: sprintf("not to have protected methods besides '%s'", implode("', '", $methods)),
|
||||
: sprintf('not to have protected methods besides [%s]', implode('], [', $methods)),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, (string) $state->contains)),
|
||||
);
|
||||
}
|
||||
@@ -378,7 +378,7 @@ final readonly class OppositeExpectation
|
||||
},
|
||||
$methods === []
|
||||
? 'not to have private methods'
|
||||
: sprintf("not to have private methods besides '%s'", implode("', '", $methods)),
|
||||
: sprintf('not to have private methods besides [%s]', implode('], [', $methods)),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, (string) $state->contains)),
|
||||
);
|
||||
}
|
||||
@@ -450,7 +450,7 @@ final readonly class OppositeExpectation
|
||||
return Targeted::make(
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isSubclassOf($class),
|
||||
sprintf("not to extend '%s'", $class),
|
||||
sprintf('not to extend [%s]', $class),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
}
|
||||
@@ -535,7 +535,7 @@ final readonly class OppositeExpectation
|
||||
return Targeted::make(
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! str_starts_with($object->reflectionClass->getShortName(), $prefix),
|
||||
"not to have prefix '{$prefix}'",
|
||||
"not to have prefix [{$prefix}]",
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
}
|
||||
@@ -548,7 +548,7 @@ final readonly class OppositeExpectation
|
||||
return Targeted::make(
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! str_ends_with($object->reflectionClass->getName(), $suffix),
|
||||
"not to have suffix '{$suffix}'",
|
||||
"not to have suffix [{$suffix}]",
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
}
|
||||
@@ -615,7 +615,7 @@ final readonly class OppositeExpectation
|
||||
return Targeted::make(
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || $object->reflectionClass->getAttributes($attribute) === [],
|
||||
"to not have attribute '{$attribute}'",
|
||||
"to not have attribute [{$attribute}]",
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ final class TestCaseFactory
|
||||
eval($classCode);
|
||||
} catch (ParseError $caught) {
|
||||
throw new RuntimeException(sprintf(
|
||||
"Unable to create test case for test file at %s. \n %s",
|
||||
"Unable to create test case for test file at [%s]. \n %s",
|
||||
$filename,
|
||||
$classCode
|
||||
), 1, $caught);
|
||||
@@ -237,6 +237,6 @@ final class TestCaseFactory
|
||||
}
|
||||
}
|
||||
|
||||
throw ShouldNotHappen::fromMessage(sprintf('Method %s not found.', $methodName));
|
||||
throw ShouldNotHappen::fromMessage(sprintf('Method [%s] not found.', $methodName));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -541,7 +541,7 @@ final class Expectation
|
||||
/* @phpstan-ignore-next-line */
|
||||
} catch (ExpectationFailedException $exception) {
|
||||
if ($message === '') {
|
||||
$message = "Failed asserting that an array has the key '$key'";
|
||||
$message = "Failed asserting that an array has the key [$key]";
|
||||
}
|
||||
|
||||
throw new ExpectationFailedException($message, $exception->getComparisonFailure());
|
||||
@@ -863,10 +863,10 @@ final class Expectation
|
||||
Assert::assertTrue(true);
|
||||
|
||||
if (! $exception instanceof Throwable && ! class_exists($exception)) {
|
||||
throw new ExpectationFailedException("Exception with message \"$exception\" not thrown.");
|
||||
throw new ExpectationFailedException("Exception with message [$exception] not thrown.");
|
||||
}
|
||||
|
||||
throw new ExpectationFailedException("Exception \"$exception\" not thrown.");
|
||||
throw new ExpectationFailedException("Exception [$exception] not thrown.");
|
||||
}
|
||||
|
||||
private function export(mixed $value): string
|
||||
|
||||
@@ -504,7 +504,7 @@ final class TestCall // @phpstan-ignore-line
|
||||
$isFunction = function_exists($classOrFunction);
|
||||
|
||||
if (! $isClass && ! $isTrait && ! $isFunction) {
|
||||
throw new InvalidArgumentException(sprintf('No class, trait or method named "%s" has been found.', $classOrFunction));
|
||||
throw new InvalidArgumentException(sprintf('No class, trait or method named [%s] has been found.', $classOrFunction));
|
||||
}
|
||||
|
||||
if ($isClass) {
|
||||
|
||||
@@ -17,7 +17,7 @@ use Symfony\Component\Process\Process;
|
||||
*/
|
||||
final readonly class BaselineSync
|
||||
{
|
||||
private const string WORKFLOW_FILE = 'tia-baseline.yml';
|
||||
private const string DEFAULT_WORKFLOW_FILE = 'tia-baseline.yml';
|
||||
|
||||
private const string ARTIFACT_NAME = 'pest-tia-baseline';
|
||||
|
||||
@@ -57,8 +57,14 @@ final readonly class BaselineSync
|
||||
public function __construct(
|
||||
private State $state,
|
||||
private OutputInterface $output,
|
||||
private WatchPatterns $watchPatterns,
|
||||
) {}
|
||||
|
||||
private function workflowFile(): string
|
||||
{
|
||||
return $this->watchPatterns->baselineWorkflow() ?? self::DEFAULT_WORKFLOW_FILE;
|
||||
}
|
||||
|
||||
private function renderBadge(string $type, string $content): void
|
||||
{
|
||||
View::render('components.badge', ['type' => $type, 'content' => $content]);
|
||||
@@ -276,7 +282,7 @@ final readonly class BaselineSync
|
||||
|
||||
Panic::with(new BaselineFetchFailed(
|
||||
sprintf('%s — %s', $contextPrefix, $diagnosis['message']),
|
||||
'Verify workflow tia-baseline.yml, artifact pest-tia-baseline, and gh token scope.',
|
||||
sprintf('Verify workflow [%s], artifact [%s], and gh token scope.', $this->workflowFile(), self::ARTIFACT_NAME),
|
||||
$hasAnchor,
|
||||
));
|
||||
}
|
||||
@@ -528,7 +534,7 @@ final readonly class BaselineSync
|
||||
$process = new Process([
|
||||
'gh', 'run', 'list',
|
||||
'-R', $repo,
|
||||
'--workflow', self::WORKFLOW_FILE,
|
||||
'--workflow', $this->workflowFile(),
|
||||
'--status', 'success',
|
||||
'--limit', '1',
|
||||
'--json', 'databaseId',
|
||||
|
||||
@@ -51,12 +51,16 @@ final class Configuration
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function baselined(): self
|
||||
public function baselined(?string $workflow = null): self
|
||||
{
|
||||
/** @var WatchPatterns $watchPatterns */
|
||||
$watchPatterns = Container::getInstance()->get(WatchPatterns::class);
|
||||
$watchPatterns->markBaselined();
|
||||
|
||||
if ($workflow !== null) {
|
||||
$watchPatterns->setBaselineWorkflow($workflow);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,10 +27,12 @@ final class CoverageCollector
|
||||
}
|
||||
|
||||
try {
|
||||
$lineCoverage = PhpUnitCodeCoverage::instance()
|
||||
$data = PhpUnitCodeCoverage::instance()
|
||||
->codeCoverage()
|
||||
->getData()
|
||||
->lineCoverage();
|
||||
->getData();
|
||||
|
||||
$lineCoverage = $data->lineCoverage();
|
||||
$idByIndex = $data->testIds();
|
||||
} catch (Throwable) {
|
||||
return [];
|
||||
}
|
||||
@@ -46,12 +48,16 @@ final class CoverageCollector
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($hits as $id) {
|
||||
$testIds[$id] = true;
|
||||
foreach (array_keys($hits) as $index) {
|
||||
if (! isset($idByIndex[$index])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$testIds[$index] = $idByIndex[$index];
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array_keys($testIds) as $testId) {
|
||||
foreach ($testIds as $testId) {
|
||||
$testFile = $this->testIdToFile($testId);
|
||||
|
||||
if ($testFile === null) {
|
||||
|
||||
@@ -100,19 +100,32 @@ final class CoverageMerger
|
||||
}
|
||||
|
||||
$cachedData = $cached->getData();
|
||||
|
||||
$staleIndexes = [];
|
||||
|
||||
foreach ($cachedData->testIds() as $index => $id) {
|
||||
if (in_array($id, $currentIds, true)) {
|
||||
$staleIndexes[$index] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($staleIndexes === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
$lineCoverage = $cachedData->lineCoverage();
|
||||
|
||||
foreach ($lineCoverage as $file => $lines) {
|
||||
foreach ($lines as $line => $ids) {
|
||||
if ($ids === null) {
|
||||
foreach ($lines as $line => $hits) {
|
||||
if ($hits === null) {
|
||||
continue;
|
||||
}
|
||||
if ($ids === []) {
|
||||
if ($hits === []) {
|
||||
continue;
|
||||
}
|
||||
$filtered = array_values(array_diff($ids, $currentIds));
|
||||
$filtered = array_diff_key($hits, $staleIndexes);
|
||||
|
||||
if ($filtered !== $ids) {
|
||||
if ($filtered !== $hits) {
|
||||
$lineCoverage[$file][$line] = $filtered;
|
||||
}
|
||||
}
|
||||
@@ -126,21 +139,28 @@ final class CoverageMerger
|
||||
*/
|
||||
private static function collectTestIds(CodeCoverage $coverage): array
|
||||
{
|
||||
$data = $coverage->getData();
|
||||
$idByIndex = $data->testIds();
|
||||
|
||||
$ids = [];
|
||||
|
||||
foreach ($coverage->getData()->lineCoverage() as $lines) {
|
||||
foreach ($data->lineCoverage() as $lines) {
|
||||
foreach ($lines as $hits) {
|
||||
if ($hits === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($hits as $id) {
|
||||
$ids[$id] = true;
|
||||
foreach (array_keys($hits) as $index) {
|
||||
if (! isset($idByIndex[$index])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ids[$index] = $idByIndex[$index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array_keys($ids);
|
||||
return array_values($ids);
|
||||
}
|
||||
|
||||
private static function state(): State
|
||||
|
||||
@@ -46,6 +46,8 @@ final class WatchPatterns
|
||||
|
||||
private ?string $defaultBranch = null;
|
||||
|
||||
private ?string $baselineWorkflow = null;
|
||||
|
||||
public function useDefaults(string $projectRoot): void
|
||||
{
|
||||
$testPath = TestSuite::getInstance()->testPath;
|
||||
@@ -189,6 +191,18 @@ final class WatchPatterns
|
||||
return $this->defaultBranch;
|
||||
}
|
||||
|
||||
public function setBaselineWorkflow(string $workflow): void
|
||||
{
|
||||
$workflow = trim($workflow);
|
||||
|
||||
$this->baselineWorkflow = $workflow === '' ? null : $workflow;
|
||||
}
|
||||
|
||||
public function baselineWorkflow(): ?string
|
||||
{
|
||||
return $this->baselineWorkflow;
|
||||
}
|
||||
|
||||
public function reset(): void
|
||||
{
|
||||
$this->patterns = [];
|
||||
@@ -198,6 +212,7 @@ final class WatchPatterns
|
||||
$this->filtered = false;
|
||||
$this->baselined = false;
|
||||
$this->defaultBranch = null;
|
||||
$this->baselineWorkflow = null;
|
||||
}
|
||||
|
||||
private function keyMatches(string $key, string $file): bool
|
||||
|
||||
@@ -73,7 +73,7 @@ final class Container
|
||||
if ($type instanceof \ReflectionType && $type->isBuiltin()) {
|
||||
$candidate = $param->getName();
|
||||
} else {
|
||||
throw ShouldNotHappen::fromMessage(sprintf('The type of `$%s` in `%s` cannot be determined.', $id, $param->getName()));
|
||||
throw ShouldNotHappen::fromMessage(sprintf('The type of [$%s] in [%s] cannot be determined.', $id, $param->getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,6 @@ final class Container
|
||||
return $reflectionClass->newInstance();
|
||||
}
|
||||
|
||||
throw ShouldNotHappen::fromMessage(sprintf('A dependency with the name `%s` cannot be resolved.', $id));
|
||||
throw ShouldNotHappen::fromMessage(sprintf('A dependency with the name [%s] cannot be resolved.', $id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ final class Coverage
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
throw ShouldNotHappen::fromMessage(sprintf('Coverage not found in path: %s.', $reportPath));
|
||||
throw ShouldNotHappen::fromMessage(sprintf('Coverage not found in path: [%s].', $reportPath));
|
||||
}
|
||||
|
||||
CoverageMerger::applyIfMarked($reportPath);
|
||||
|
||||
Reference in New Issue
Block a user