mirror of
https://github.com/pestphp/pest.git
synced 2026-03-06 07:47:22 +01:00
refacto: 100% type coverage
This commit is contained in:
@ -50,9 +50,11 @@
|
|||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"pestphp/pest-dev-tools": "^2.12.0",
|
"pestphp/pest-dev-tools": "^2.12.0",
|
||||||
|
"pestphp/pest-plugin-type-coverage": "^2.0.0",
|
||||||
"symfony/process": "^6.3.0"
|
"symfony/process": "^6.3.0"
|
||||||
},
|
},
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "dev",
|
||||||
|
"prefer-stable": true,
|
||||||
"config": {
|
"config": {
|
||||||
"sort-packages": true,
|
"sort-packages": true,
|
||||||
"preferred-install": "dist",
|
"preferred-install": "dist",
|
||||||
|
|||||||
@ -381,9 +381,7 @@ final class Expectation
|
|||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => str_contains((string) file_get_contents($object->path), 'declare(strict_types=1);'),
|
fn (ObjectDescription $object): bool => str_contains((string) file_get_contents($object->path), 'declare(strict_types=1);'),
|
||||||
'to use strict types',
|
'to use strict types',
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, '<?php')),
|
||||||
return str_contains($line, '<?php');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,9 +394,7 @@ final class Expectation
|
|||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->isFinal(),
|
fn (ObjectDescription $object): bool => $object->reflectionClass->isFinal(),
|
||||||
'to be final',
|
'to be final',
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,9 +407,7 @@ final class Expectation
|
|||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->isReadOnly(),
|
fn (ObjectDescription $object): bool => $object->reflectionClass->isReadOnly(),
|
||||||
'to be readonly',
|
'to be readonly',
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -426,9 +420,7 @@ final class Expectation
|
|||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->isTrait(),
|
fn (ObjectDescription $object): bool => $object->reflectionClass->isTrait(),
|
||||||
'to be trait',
|
'to be trait',
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,9 +441,7 @@ final class Expectation
|
|||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->isAbstract(),
|
fn (ObjectDescription $object): bool => $object->reflectionClass->isAbstract(),
|
||||||
'to be abstract',
|
'to be abstract',
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,9 +454,7 @@ final class Expectation
|
|||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->isEnum(),
|
fn (ObjectDescription $object): bool => $object->reflectionClass->isEnum(),
|
||||||
'to be enum',
|
'to be enum',
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -487,9 +475,7 @@ final class Expectation
|
|||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->isInterface(),
|
fn (ObjectDescription $object): bool => $object->reflectionClass->isInterface(),
|
||||||
'to be interface',
|
'to be interface',
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,9 +498,7 @@ final class Expectation
|
|||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->isSubclassOf($class),
|
fn (ObjectDescription $object): bool => $object->reflectionClass->isSubclassOf($class),
|
||||||
sprintf("to extend '%s'", $class),
|
sprintf("to extend '%s'", $class),
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,9 +511,7 @@ final class Expectation
|
|||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->getParentClass() === false,
|
fn (ObjectDescription $object): bool => $object->reflectionClass->getParentClass() === false,
|
||||||
'to extend nothing',
|
'to extend nothing',
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -542,9 +524,7 @@ final class Expectation
|
|||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->getInterfaceNames() === [],
|
fn (ObjectDescription $object): bool => $object->reflectionClass->getInterfaceNames() === [],
|
||||||
'to implement nothing',
|
'to implement nothing',
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -562,9 +542,7 @@ final class Expectation
|
|||||||
fn (ObjectDescription $object): bool => count($interfaces) === count($object->reflectionClass->getInterfaceNames())
|
fn (ObjectDescription $object): bool => count($interfaces) === count($object->reflectionClass->getInterfaceNames())
|
||||||
&& array_diff($interfaces, $object->reflectionClass->getInterfaceNames()) === [],
|
&& array_diff($interfaces, $object->reflectionClass->getInterfaceNames()) === [],
|
||||||
"to only implement '".implode("', '", $interfaces)."'",
|
"to only implement '".implode("', '", $interfaces)."'",
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -577,9 +555,7 @@ final class Expectation
|
|||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => str_ends_with($object->reflectionClass->getName(), $suffix),
|
fn (ObjectDescription $object): bool => str_ends_with($object->reflectionClass->getName(), $suffix),
|
||||||
"to have suffix '{$suffix}'",
|
"to have suffix '{$suffix}'",
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -592,9 +568,7 @@ final class Expectation
|
|||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => str_starts_with($object->reflectionClass->getName(), $suffix),
|
fn (ObjectDescription $object): bool => str_starts_with($object->reflectionClass->getName(), $suffix),
|
||||||
"to have prefix '{$suffix}'",
|
"to have prefix '{$suffix}'",
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -619,9 +593,7 @@ final class Expectation
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
"to implement '".implode("', '", $interfaces)."'",
|
"to implement '".implode("', '", $interfaces)."'",
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -84,9 +84,7 @@ final class OppositeExpectation
|
|||||||
$this->original,
|
$this->original,
|
||||||
fn (ObjectDescription $object): bool => ! str_contains((string) file_get_contents($object->path), 'declare(strict_types=1);'),
|
fn (ObjectDescription $object): bool => ! str_contains((string) file_get_contents($object->path), 'declare(strict_types=1);'),
|
||||||
'not to use strict types',
|
'not to use strict types',
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, '<?php')),
|
||||||
return str_contains($line, '<?php');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,9 +97,7 @@ final class OppositeExpectation
|
|||||||
$this->original,
|
$this->original,
|
||||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isFinal(),
|
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isFinal(),
|
||||||
'not to be final',
|
'not to be final',
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,9 +110,7 @@ final class OppositeExpectation
|
|||||||
$this->original,
|
$this->original,
|
||||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isReadOnly(),
|
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isReadOnly(),
|
||||||
'not to be readonly',
|
'not to be readonly',
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,9 +123,7 @@ final class OppositeExpectation
|
|||||||
$this->original,
|
$this->original,
|
||||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isTrait(),
|
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isTrait(),
|
||||||
'not to be trait',
|
'not to be trait',
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,9 +136,7 @@ final class OppositeExpectation
|
|||||||
$this->original,
|
$this->original,
|
||||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isAbstract(),
|
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isAbstract(),
|
||||||
'not to be abstract',
|
'not to be abstract',
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,9 +149,7 @@ final class OppositeExpectation
|
|||||||
$this->original,
|
$this->original,
|
||||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isEnum(),
|
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isEnum(),
|
||||||
'not to be enum',
|
'not to be enum',
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,9 +162,7 @@ final class OppositeExpectation
|
|||||||
$this->original,
|
$this->original,
|
||||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isInterface(),
|
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isInterface(),
|
||||||
'not to be interface',
|
'not to be interface',
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,9 +177,7 @@ final class OppositeExpectation
|
|||||||
$this->original,
|
$this->original,
|
||||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isSubclassOf($class),
|
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isSubclassOf($class),
|
||||||
sprintf("not to extend '%s'", $class),
|
sprintf("not to extend '%s'", $class),
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,14 +190,14 @@ final class OppositeExpectation
|
|||||||
$this->original,
|
$this->original,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->getParentClass() !== false,
|
fn (ObjectDescription $object): bool => $object->reflectionClass->getParentClass() !== false,
|
||||||
'to extend a class',
|
'to extend a class',
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asserts that the given expectation target not to implement the given interfaces.
|
* Asserts that the given expectation target not to implement the given interfaces.
|
||||||
|
*
|
||||||
|
* @param array<int, class-string>|string $interfaces
|
||||||
*/
|
*/
|
||||||
public function toImplement(array|string $interfaces): ArchExpectation
|
public function toImplement(array|string $interfaces): ArchExpectation
|
||||||
{
|
{
|
||||||
@ -230,10 +214,8 @@ final class OppositeExpectation
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
"not to implement '".implode("', '", (array) $interfaces)."'",
|
"not to implement '".implode("', '", $interfaces)."'",
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,31 +225,42 @@ final class OppositeExpectation
|
|||||||
public function toImplementNothing(): ArchExpectation
|
public function toImplementNothing(): ArchExpectation
|
||||||
{
|
{
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this,
|
$this->original,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->getInterfaceNames() !== [],
|
fn (ObjectDescription $object): bool => $object->reflectionClass->getInterfaceNames() !== [],
|
||||||
'to implement an interface',
|
'to implement an interface',
|
||||||
FileLineFinder::where(function (string $line): bool {
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
return str_contains($line, 'class');
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function toOnlyImplement(array|string $interfaces): ArchExpectation
|
/**
|
||||||
|
* Not supported.
|
||||||
|
*
|
||||||
|
* @param array<int, class-string>|string $interfaces
|
||||||
|
*/
|
||||||
|
public function toOnlyImplement(array|string $interfaces): never
|
||||||
{
|
{
|
||||||
throw InvalidExpectation::fromMethods(['not', 'toOnlyImplement']);
|
throw InvalidExpectation::fromMethods(['not', 'toOnlyImplement']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not supported.
|
||||||
|
*/
|
||||||
public function toHavePrefix(string $suffix): never
|
public function toHavePrefix(string $suffix): never
|
||||||
{
|
{
|
||||||
throw InvalidExpectation::fromMethods(['not', 'toHavePrefix']);
|
throw InvalidExpectation::fromMethods(['not', 'toHavePrefix']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not supported.
|
||||||
|
*/
|
||||||
public function toHaveSuffix(string $suffix): never
|
public function toHaveSuffix(string $suffix): never
|
||||||
{
|
{
|
||||||
throw InvalidExpectation::fromMethods(['not', 'toHaveSuffix']);
|
throw InvalidExpectation::fromMethods(['not', 'toHaveSuffix']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Not supported.
|
||||||
|
*
|
||||||
* @param array<int, string>|string $targets
|
* @param array<int, string>|string $targets
|
||||||
*/
|
*/
|
||||||
public function toOnlyUse(array|string $targets): never
|
public function toOnlyUse(array|string $targets): never
|
||||||
@ -275,6 +268,9 @@ final class OppositeExpectation
|
|||||||
throw InvalidExpectation::fromMethods(['not', 'toOnlyUse']);
|
throw InvalidExpectation::fromMethods(['not', 'toOnlyUse']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not supported.
|
||||||
|
*/
|
||||||
public function toUseNothing(): never
|
public function toUseNothing(): never
|
||||||
{
|
{
|
||||||
throw InvalidExpectation::fromMethods(['not', 'toUseNothing']);
|
throw InvalidExpectation::fromMethods(['not', 'toUseNothing']);
|
||||||
@ -358,8 +354,13 @@ final class OppositeExpectation
|
|||||||
|
|
||||||
$exporter = Exporter::default();
|
$exporter = Exporter::default();
|
||||||
|
|
||||||
$toString = fn ($argument): string => $exporter->shortenedExport($argument);
|
$toString = fn (mixed $argument): string => $exporter->shortenedExport($argument);
|
||||||
|
|
||||||
throw new ExpectationFailedException(sprintf('Expecting %s not %s %s.', $toString($this->original->value), strtolower((string) preg_replace('/(?<!\ )[A-Z]/', ' $0', $name)), implode(' ', array_map(fn ($argument): string => $toString($argument), $arguments))));
|
throw new ExpectationFailedException(sprintf(
|
||||||
|
'Expecting %s not %s %s.',
|
||||||
|
$toString($this->original->value),
|
||||||
|
strtolower((string) preg_replace('/(?<!\ )[A-Z]/', ' $0', $name)),
|
||||||
|
implode(' ', array_map(fn (mixed $argument): string => $toString($argument), $arguments)),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -98,7 +98,7 @@ final class TestCaseFactory
|
|||||||
{
|
{
|
||||||
if ('\\' === DIRECTORY_SEPARATOR) {
|
if ('\\' === DIRECTORY_SEPARATOR) {
|
||||||
// In case Windows, strtolower drive name, like in UsesCall.
|
// In case Windows, strtolower drive name, like in UsesCall.
|
||||||
$filename = (string) preg_replace_callback('~^(?P<drive>[a-z]+:\\\)~i', static fn ($match): string => strtolower($match['drive']), $filename);
|
$filename = (string) preg_replace_callback('~^(?P<drive>[a-z]+:\\\)~i', static fn (array $match): string => strtolower($match['drive']), $filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
$filename = str_replace('\\\\', '\\', addslashes((string) realpath($filename)));
|
$filename = str_replace('\\\\', '\\', addslashes((string) realpath($filename)));
|
||||||
@ -134,7 +134,7 @@ final class TestCaseFactory
|
|||||||
|
|
||||||
$hasPrintableTestCaseClassFQN = sprintf('\%s', HasPrintableTestCaseName::class);
|
$hasPrintableTestCaseClassFQN = sprintf('\%s', HasPrintableTestCaseName::class);
|
||||||
$traitsCode = sprintf('use %s;', implode(', ', array_map(
|
$traitsCode = sprintf('use %s;', implode(', ', array_map(
|
||||||
static fn ($trait): string => sprintf('\%s', $trait), $this->traits))
|
static fn (string $trait): string => sprintf('\%s', $trait), $this->traits))
|
||||||
);
|
);
|
||||||
|
|
||||||
$partsFQN = explode('\\', $classFQN);
|
$partsFQN = explode('\\', $classFQN);
|
||||||
|
|||||||
@ -147,11 +147,11 @@ final class TestCaseMethodFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
$annotations = implode('', array_map(
|
$annotations = implode('', array_map(
|
||||||
static fn ($annotation): string => sprintf("\n * %s", $annotation), $annotations,
|
static fn (string $annotation): string => sprintf("\n * %s", $annotation), $annotations,
|
||||||
));
|
));
|
||||||
|
|
||||||
$attributes = implode('', array_map(
|
$attributes = implode('', array_map(
|
||||||
static fn ($attribute): string => sprintf("\n %s", $attribute), $attributes,
|
static fn (string $attribute): string => sprintf("\n %s", $attribute), $attributes,
|
||||||
));
|
));
|
||||||
|
|
||||||
return <<<PHP
|
return <<<PHP
|
||||||
|
|||||||
@ -66,11 +66,11 @@ final class UsesCall
|
|||||||
*/
|
*/
|
||||||
public function in(string ...$targets): void
|
public function in(string ...$targets): void
|
||||||
{
|
{
|
||||||
$targets = array_map(function ($path): string {
|
$targets = array_map(function (string $path): string {
|
||||||
$startChar = DIRECTORY_SEPARATOR;
|
$startChar = DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
if ('\\' === DIRECTORY_SEPARATOR || preg_match('~\A[A-Z]:(?![^/\\\\])~i', $path) > 0) {
|
if ('\\' === DIRECTORY_SEPARATOR || preg_match('~\A[A-Z]:(?![^/\\\\])~i', $path) > 0) {
|
||||||
$path = (string) preg_replace_callback('~^(?P<drive>[a-z]+:\\\)~i', fn ($match): string => strtolower($match['drive']), $path);
|
$path = (string) preg_replace_callback('~^(?P<drive>[a-z]+:\\\)~i', fn (array $match): string => strtolower($match['drive']), $path);
|
||||||
|
|
||||||
$startChar = strtolower((string) preg_replace('~^([a-z]+:\\\).*$~i', '$1', __DIR__));
|
$startChar = strtolower((string) preg_replace('~^([a-z]+:\\\).*$~i', '$1', __DIR__));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,7 +50,7 @@ final class Coverage implements AddsOutput, HandlesArguments
|
|||||||
*/
|
*/
|
||||||
public function handleArguments(array $originals): array
|
public function handleArguments(array $originals): array
|
||||||
{
|
{
|
||||||
$arguments = [...[''], ...array_values(array_filter($originals, function ($original): bool {
|
$arguments = [...[''], ...array_values(array_filter($originals, function (string $original): bool {
|
||||||
foreach ([self::COVERAGE_OPTION, self::MIN_OPTION] as $option) {
|
foreach ([self::COVERAGE_OPTION, self::MIN_OPTION] as $option) {
|
||||||
if ($original === sprintf('--%s', $option)) {
|
if ($original === sprintf('--%s', $option)) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -115,13 +115,13 @@ final class Parallel implements HandlesArguments
|
|||||||
private function runTestSuiteInParallel(array $arguments): int
|
private function runTestSuiteInParallel(array $arguments): int
|
||||||
{
|
{
|
||||||
$handlers = array_filter(
|
$handlers = array_filter(
|
||||||
array_map(fn ($handler): object|string => Container::getInstance()->get($handler), self::HANDLERS),
|
array_map(fn (string $handler): object|string => Container::getInstance()->get($handler), self::HANDLERS),
|
||||||
fn ($handler): bool => $handler instanceof HandlesArguments,
|
fn (object|string $handler): bool => $handler instanceof HandlesArguments,
|
||||||
);
|
);
|
||||||
|
|
||||||
$filteredArguments = array_reduce(
|
$filteredArguments = array_reduce(
|
||||||
$handlers,
|
$handlers,
|
||||||
fn ($arguments, HandlesArguments $handler): array => $handler->handleArguments($arguments),
|
fn (array $arguments, HandlesArguments $handler): array => $handler->handleArguments($arguments),
|
||||||
$arguments
|
$arguments
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -139,13 +139,13 @@ final class Parallel implements HandlesArguments
|
|||||||
private function runWorkerHandlers(array $arguments): array
|
private function runWorkerHandlers(array $arguments): array
|
||||||
{
|
{
|
||||||
$handlers = array_filter(
|
$handlers = array_filter(
|
||||||
array_map(fn ($handler): object|string => Container::getInstance()->get($handler), self::HANDLERS),
|
array_map(fn (string $handler): object|string => Container::getInstance()->get($handler), self::HANDLERS),
|
||||||
fn ($handler): bool => $handler instanceof HandlersWorkerArguments,
|
fn (object|string $handler): bool => $handler instanceof HandlersWorkerArguments,
|
||||||
);
|
);
|
||||||
|
|
||||||
return array_reduce(
|
return array_reduce(
|
||||||
$handlers,
|
$handlers,
|
||||||
fn ($arguments, HandlersWorkerArguments $handler): array => $handler->handleWorkerArguments($arguments),
|
fn (array $arguments, HandlersWorkerArguments $handler): array => $handler->handleWorkerArguments($arguments),
|
||||||
$arguments
|
$arguments
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,7 +30,7 @@ final class Parallel implements HandlesArguments
|
|||||||
*/
|
*/
|
||||||
public function handleArguments(array $arguments): array
|
public function handleArguments(array $arguments): array
|
||||||
{
|
{
|
||||||
$args = array_reduce(self::ARGS_TO_REMOVE, fn ($args, $arg): array => $this->popArgument($arg, $args), $arguments);
|
$args = array_reduce(self::ARGS_TO_REMOVE, fn (array $args, string $arg): array => $this->popArgument($arg, $args), $arguments);
|
||||||
|
|
||||||
return $this->pushArgument('--runner='.WrapperRunner::class, $args);
|
return $this->pushArgument('--runner='.WrapperRunner::class, $args);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,7 @@ use ParaTest\WrapperRunner\WrapperWorker;
|
|||||||
use Pest\Result;
|
use Pest\Result;
|
||||||
use Pest\TestSuite;
|
use Pest\TestSuite;
|
||||||
use PHPUnit\Event\Facade as EventFacade;
|
use PHPUnit\Event\Facade as EventFacade;
|
||||||
|
use PHPUnit\Event\TestRunner\WarningTriggered;
|
||||||
use PHPUnit\Runner\CodeCoverage;
|
use PHPUnit\Runner\CodeCoverage;
|
||||||
use PHPUnit\TestRunner\TestResult\Facade as TestResultFacade;
|
use PHPUnit\TestRunner\TestResult\Facade as TestResultFacade;
|
||||||
use PHPUnit\TestRunner\TestResult\TestResult;
|
use PHPUnit\TestRunner\TestResult\TestResult;
|
||||||
@ -317,7 +318,10 @@ final class WrapperRunner implements RunnerInterface
|
|||||||
$testResultSum->testTriggeredPhpunitErrorEvents(),
|
$testResultSum->testTriggeredPhpunitErrorEvents(),
|
||||||
$testResultSum->testTriggeredPhpunitWarningEvents(),
|
$testResultSum->testTriggeredPhpunitWarningEvents(),
|
||||||
$testResultSum->testRunnerTriggeredDeprecationEvents(),
|
$testResultSum->testRunnerTriggeredDeprecationEvents(),
|
||||||
array_values(array_filter($testResultSum->testRunnerTriggeredWarningEvents(), fn ($event): bool => ! str_contains($event->message(), 'No tests found'))),
|
array_values(array_filter(
|
||||||
|
$testResultSum->testRunnerTriggeredWarningEvents(),
|
||||||
|
fn (WarningTriggered $event): bool => ! str_contains($event->message(), 'No tests found')
|
||||||
|
)),
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->printer->printResults(
|
$this->printer->printResults(
|
||||||
|
|||||||
@ -66,11 +66,11 @@ final class DatasetsRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Closure|array<int|string, mixed>|never
|
* @return Closure|array<int|string, mixed>
|
||||||
*
|
*
|
||||||
* @throws ShouldNotHappen
|
* @throws ShouldNotHappen
|
||||||
*/
|
*/
|
||||||
public static function get(string $filename, string $description)
|
public static function get(string $filename, string $description): Closure|array
|
||||||
{
|
{
|
||||||
$dataset = self::$withs[$filename.self::SEPARATOR.$description];
|
$dataset = self::$withs[$filename.self::SEPARATOR.$description];
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ final class DatasetsRepository
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<Closure|iterable<int|string, mixed>|string> $datasets
|
* @param array<Closure|iterable<int|string, mixed>|string> $datasets
|
||||||
* @return array<array<mixed>>
|
* @return array<int, array<int, mixed>>
|
||||||
*/
|
*/
|
||||||
private static function processDatasets(array $datasets, string $currentTestFile): array
|
private static function processDatasets(array $datasets, string $currentTestFile): array
|
||||||
{
|
{
|
||||||
@ -193,7 +193,7 @@ final class DatasetsRepository
|
|||||||
|
|
||||||
$closestScopeDatasetKey = array_reduce(
|
$closestScopeDatasetKey = array_reduce(
|
||||||
array_keys($matchingDatasets),
|
array_keys($matchingDatasets),
|
||||||
fn ($keyA, $keyB) => $keyA !== null && strlen((string) $keyA) > strlen($keyB) ? $keyA : $keyB
|
fn (string|int|null $keyA, string|int|null $keyB): string|int|null => $keyA !== null && strlen((string) $keyA) > strlen((string) $keyB) ? $keyA : $keyB
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($closestScopeDatasetKey === null) {
|
if ($closestScopeDatasetKey === null) {
|
||||||
|
|||||||
@ -159,10 +159,9 @@ final class Coverage
|
|||||||
* ['11', '20..25', '50', '60..80'];
|
* ['11', '20..25', '50', '60..80'];
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param File $file
|
|
||||||
* @return array<int, string>
|
* @return array<int, string>
|
||||||
*/
|
*/
|
||||||
public static function getMissingCoverage($file): array
|
public static function getMissingCoverage(File $file): array
|
||||||
{
|
{
|
||||||
$shouldBeNewLine = true;
|
$shouldBeNewLine = true;
|
||||||
|
|
||||||
|
|||||||
@ -18,11 +18,9 @@ final class ExceptionTrace
|
|||||||
/**
|
/**
|
||||||
* Ensures the given closure reports the good execution context.
|
* Ensures the given closure reports the good execution context.
|
||||||
*
|
*
|
||||||
* @return mixed
|
|
||||||
*
|
|
||||||
* @throws Throwable
|
* @throws Throwable
|
||||||
*/
|
*/
|
||||||
public static function ensure(Closure $closure)
|
public static function ensure(Closure $closure): mixed
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return $closure();
|
return $closure();
|
||||||
|
|||||||
@ -84,6 +84,6 @@ final class ExpectationPipeline
|
|||||||
*/
|
*/
|
||||||
public function carry(): Closure
|
public function carry(): Closure
|
||||||
{
|
{
|
||||||
return fn ($stack, $pipe): Closure => fn () => $pipe($stack, ...$this->passables);
|
return fn (mixed $stack, callable $pipe): Closure => fn () => $pipe($stack, ...$this->passables);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,9 +24,8 @@ final class Reflection
|
|||||||
* Calls the given method with args on the given object.
|
* Calls the given method with args on the given object.
|
||||||
*
|
*
|
||||||
* @param array<int, mixed> $args
|
* @param array<int, mixed> $args
|
||||||
* @return mixed
|
|
||||||
*/
|
*/
|
||||||
public static function call(object $object, string $method, array $args = [])
|
public static function call(object $object, string $method, array $args = []): mixed
|
||||||
{
|
{
|
||||||
$reflectionClass = new ReflectionClass($object);
|
$reflectionClass = new ReflectionClass($object);
|
||||||
|
|
||||||
@ -53,9 +52,8 @@ final class Reflection
|
|||||||
* Bind a callable to the TestCase and return the result.
|
* Bind a callable to the TestCase and return the result.
|
||||||
*
|
*
|
||||||
* @param array<int, mixed> $args
|
* @param array<int, mixed> $args
|
||||||
* @return mixed
|
|
||||||
*/
|
*/
|
||||||
public static function bindCallable(callable $callable, array $args = [])
|
public static function bindCallable(callable $callable, array $args = []): mixed
|
||||||
{
|
{
|
||||||
return Closure::fromCallable($callable)->bindTo(TestSuite::getInstance()->test)(...$args);
|
return Closure::fromCallable($callable)->bindTo(TestSuite::getInstance()->test)(...$args);
|
||||||
}
|
}
|
||||||
@ -63,10 +61,8 @@ final class Reflection
|
|||||||
/**
|
/**
|
||||||
* Bind a callable to the TestCase and return the result,
|
* Bind a callable to the TestCase and return the result,
|
||||||
* passing in the current dataset values as arguments.
|
* passing in the current dataset values as arguments.
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
*/
|
||||||
public static function bindCallableWithData(callable $callable)
|
public static function bindCallableWithData(callable $callable): mixed
|
||||||
{
|
{
|
||||||
$test = TestSuite::getInstance()->test;
|
$test = TestSuite::getInstance()->test;
|
||||||
|
|
||||||
@ -87,10 +83,8 @@ final class Reflection
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the property value from of the given object.
|
* Gets the property value from of the given object.
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
*/
|
||||||
public static function getPropertyValue(object $object, string $property)
|
public static function getPropertyValue(object $object, string $property): mixed
|
||||||
{
|
{
|
||||||
$reflectionClass = new ReflectionClass($object);
|
$reflectionClass = new ReflectionClass($object);
|
||||||
|
|
||||||
@ -206,10 +200,7 @@ final class Reflection
|
|||||||
return $arguments;
|
return $arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static function getFunctionVariable(Closure $function, string $key): mixed
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public static function getFunctionVariable(Closure $function, string $key)
|
|
||||||
{
|
{
|
||||||
return (new ReflectionFunction($function))->getStaticVariables()[$key] ?? null;
|
return (new ReflectionFunction($function))->getStaticVariables()[$key] ?? null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,13 +59,18 @@ final class GitDirtyTestCaseFilter implements TestCaseFilter
|
|||||||
$dirtyFiles[substr($dirtyFile, 3)] = trim(substr($dirtyFile, 0, 3));
|
$dirtyFiles[substr($dirtyFile, 3)] = trim(substr($dirtyFile, 0, 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
$dirtyFiles = array_filter($dirtyFiles, fn ($status): bool => $status !== 'D');
|
$dirtyFiles = array_filter($dirtyFiles, fn (string $status): bool => $status !== 'D');
|
||||||
|
|
||||||
$dirtyFiles = array_map(fn ($file, $status): string => in_array($status, ['R', 'RM'], true) ? explode(' -> ', $file)[1] : $file, array_keys($dirtyFiles), $dirtyFiles);
|
$dirtyFiles = array_map(
|
||||||
|
fn (string $file, string $status): string => in_array($status, ['R', 'RM'], true)
|
||||||
|
? explode(' -> ', $file)[1]
|
||||||
|
: $file, array_keys($dirtyFiles), $dirtyFiles,
|
||||||
|
);
|
||||||
|
|
||||||
$dirtyFiles = array_filter(
|
$dirtyFiles = array_filter(
|
||||||
$dirtyFiles,
|
$dirtyFiles,
|
||||||
fn ($file): bool => str_starts_with('.'.DIRECTORY_SEPARATOR.$file, TestSuite::getInstance()->testPath) || str_starts_with($file, TestSuite::getInstance()->testPath)
|
fn (string $file): bool => str_starts_with('.'.DIRECTORY_SEPARATOR.$file, TestSuite::getInstance()->testPath)
|
||||||
|
|| str_starts_with($file, TestSuite::getInstance()->testPath)
|
||||||
);
|
);
|
||||||
|
|
||||||
$dirtyFiles = array_values($dirtyFiles);
|
$dirtyFiles = array_values($dirtyFiles);
|
||||||
|
|||||||
@ -18,7 +18,7 @@ $run = function () {
|
|||||||
|
|
||||||
test('parallel', function () use ($run) {
|
test('parallel', function () use ($run) {
|
||||||
expect($run('--exclude-group=integration'))
|
expect($run('--exclude-group=integration'))
|
||||||
->toContain('Tests: 1 deprecated, 3 warnings, 4 incomplete, 1 notice, 8 todos, 15 skipped, 707 passed (1720 assertions)')
|
->toContain('Tests: 1 deprecated, 4 warnings, 5 incomplete, 2 notices, 13 todos, 15 skipped, 720 passed (1740 assertions)')
|
||||||
->toContain('Parallel: 3 processes');
|
->toContain('Parallel: 3 processes');
|
||||||
})->skipOnWindows();
|
})->skipOnWindows();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user