Release 3.8.2

This commit is contained in:
Nuno Maduro
2025-04-17 11:52:59 +01:00
parent eed68f2840
commit c6244a8712
5 changed files with 43 additions and 36 deletions

View File

@ -535,7 +535,7 @@ final class Expectation
{ {
return Targeted::make( return Targeted::make(
$this, $this,
fn (ObjectDescription $object): bool => ! enum_exists($object->name) && $object->reflectionClass->isFinal(), fn (ObjectDescription $object): bool => ! enum_exists($object->name) && isset($object->reflectionClass) && $object->reflectionClass->isFinal(),
'to be final', 'to be final',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -548,7 +548,7 @@ final class Expectation
{ {
return Targeted::make( return Targeted::make(
$this, $this,
fn (ObjectDescription $object): bool => ! enum_exists($object->name) && $object->reflectionClass->isReadOnly() && assert(true), // @phpstan-ignore-line fn (ObjectDescription $object): bool => ! enum_exists($object->name) && isset($object->reflectionClass) && $object->reflectionClass->isReadOnly() && assert(true), // @phpstan-ignore-line
'to be readonly', 'to be readonly',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -561,7 +561,7 @@ final class Expectation
{ {
return Targeted::make( return Targeted::make(
$this, $this,
fn (ObjectDescription $object): bool => $object->reflectionClass->isTrait(), fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isTrait(),
'to be trait', 'to be trait',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -582,7 +582,7 @@ final class Expectation
{ {
return Targeted::make( return Targeted::make(
$this, $this,
fn (ObjectDescription $object): bool => $object->reflectionClass->isAbstract(), fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isAbstract(),
'to be abstract', 'to be abstract',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -599,7 +599,7 @@ final class Expectation
return Targeted::make( return Targeted::make(
$this, $this,
fn (ObjectDescription $object): bool => count(array_filter($methods, fn (string $method): bool => $object->reflectionClass->hasMethod($method))) === count($methods), 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')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -670,7 +670,7 @@ final class Expectation
{ {
return Targeted::make( return Targeted::make(
$this, $this,
fn (ObjectDescription $object): bool => $object->reflectionClass->isEnum(), fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isEnum(),
'to be enum', 'to be enum',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -712,7 +712,7 @@ final class Expectation
{ {
return Targeted::make( return Targeted::make(
$this, $this,
fn (ObjectDescription $object): bool => $object->reflectionClass->isInterface(), fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isInterface(),
'to be interface', 'to be interface',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -733,7 +733,7 @@ final class Expectation
{ {
return Targeted::make( return Targeted::make(
$this, $this,
fn (ObjectDescription $object): bool => $class === $object->reflectionClass->getName() || $object->reflectionClass->isSubclassOf($class), 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')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -773,6 +773,10 @@ final class Expectation
$this, $this,
function (ObjectDescription $object) use ($traits): bool { function (ObjectDescription $object) use ($traits): bool {
foreach ($traits as $trait) { foreach ($traits as $trait) {
if (isset($object->reflectionClass) === false) {
return false;
}
if (! in_array($trait, $object->reflectionClass->getTraitNames(), true)) { if (! in_array($trait, $object->reflectionClass->getTraitNames(), true)) {
return false; return false;
} }
@ -792,7 +796,7 @@ final class Expectation
{ {
return Targeted::make( return Targeted::make(
$this, $this,
fn (ObjectDescription $object): bool => $object->reflectionClass->getInterfaceNames() === [], fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->getInterfaceNames() === [],
'to implement nothing', 'to implement nothing',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -809,7 +813,8 @@ final class Expectation
return Targeted::make( return Targeted::make(
$this, $this,
fn (ObjectDescription $object): bool => count($interfaces) === count($object->reflectionClass->getInterfaceNames()) fn (ObjectDescription $object): bool => isset($object->reflectionClass)
&& (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(fn (string $line): bool => str_contains($line, 'class')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
@ -823,7 +828,7 @@ final class Expectation
{ {
return Targeted::make( return Targeted::make(
$this, $this,
fn (ObjectDescription $object): bool => str_starts_with($object->reflectionClass->getShortName(), $prefix), 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')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -836,7 +841,7 @@ final class Expectation
{ {
return Targeted::make( return Targeted::make(
$this, $this,
fn (ObjectDescription $object): bool => str_ends_with($object->reflectionClass->getName(), $suffix), 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')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -855,7 +860,7 @@ final class Expectation
$this, $this,
function (ObjectDescription $object) use ($interfaces): bool { function (ObjectDescription $object) use ($interfaces): bool {
foreach ($interfaces as $interface) { foreach ($interfaces as $interface) {
if (! $object->reflectionClass->implementsInterface($interface)) { if (! isset($object->reflectionClass) || ! $object->reflectionClass->implementsInterface($interface)) {
return false; return false;
} }
} }
@ -928,7 +933,7 @@ final class Expectation
{ {
return Targeted::make( return Targeted::make(
$this, $this,
fn (ObjectDescription $object): bool => $object->reflectionClass->hasMethod('__invoke'), fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->hasMethod('__invoke'),
'to be invokable', 'to be invokable',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')) FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))
); );
@ -1037,7 +1042,7 @@ final class Expectation
{ {
return Targeted::make( return Targeted::make(
$this, $this,
fn (ObjectDescription $object): bool => $object->reflectionClass->getAttributes($attribute) !== [], 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')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -1066,7 +1071,8 @@ final class Expectation
{ {
return Targeted::make( return Targeted::make(
$this, $this,
fn (ObjectDescription $object): bool => $object->reflectionClass->isEnum() fn (ObjectDescription $object): bool => isset($object->reflectionClass)
&& $object->reflectionClass->isEnum()
&& (new ReflectionEnum($object->name))->isBacked() // @phpstan-ignore-line && (new ReflectionEnum($object->name))->isBacked() // @phpstan-ignore-line
&& (string) (new ReflectionEnum($object->name))->getBackingType() === $backingType, // @phpstan-ignore-line && (string) (new ReflectionEnum($object->name))->getBackingType() === $backingType, // @phpstan-ignore-line
'to be '.$backingType.' backed enum', 'to be '.$backingType.' backed enum',

View File

@ -193,7 +193,7 @@ final readonly class OppositeExpectation
return Targeted::make( return Targeted::make(
$original, $original,
fn (ObjectDescription $object): bool => ! enum_exists($object->name) && ! $object->reflectionClass->isFinal(), fn (ObjectDescription $object): bool => ! enum_exists($object->name) && (isset($object->reflectionClass) === false || ! $object->reflectionClass->isFinal()),
'not to be final', 'not to be final',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -209,7 +209,7 @@ final readonly class OppositeExpectation
return Targeted::make( return Targeted::make(
$original, $original,
fn (ObjectDescription $object): bool => ! enum_exists($object->name) && ! $object->reflectionClass->isReadOnly() && assert(true), // @phpstan-ignore-line fn (ObjectDescription $object): bool => ! enum_exists($object->name) && (isset($object->reflectionClass) === false || ! $object->reflectionClass->isReadOnly()) && assert(true), // @phpstan-ignore-line
'not to be readonly', 'not to be readonly',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -225,7 +225,7 @@ final readonly class OppositeExpectation
return Targeted::make( return Targeted::make(
$original, $original,
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isTrait(), fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isTrait(),
'not to be trait', 'not to be trait',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -249,7 +249,7 @@ final readonly class OppositeExpectation
return Targeted::make( return Targeted::make(
$original, $original,
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isAbstract(), fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isAbstract(),
'not to be abstract', 'not to be abstract',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -271,7 +271,7 @@ final readonly class OppositeExpectation
$original, $original,
fn (ObjectDescription $object): bool => array_filter( fn (ObjectDescription $object): bool => array_filter(
$methods, $methods,
fn (string $method): bool => $object->reflectionClass->hasMethod($method), fn (string $method): bool => isset($object->reflectionClass) === false || $object->reflectionClass->hasMethod($method),
) === [], ) === [],
'to not have methods: '.implode(', ', $methods), 'to not have methods: '.implode(', ', $methods),
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
@ -436,7 +436,7 @@ final readonly class OppositeExpectation
return Targeted::make( return Targeted::make(
$original, $original,
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isEnum(), fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isEnum(),
'not to be enum', 'not to be enum',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -484,7 +484,7 @@ final readonly class OppositeExpectation
return Targeted::make( return Targeted::make(
$original, $original,
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isInterface(), fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isInterface(),
'not to be interface', 'not to be interface',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -508,7 +508,7 @@ final readonly class OppositeExpectation
return Targeted::make( return Targeted::make(
$original, $original,
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isSubclassOf($class), 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')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -524,7 +524,7 @@ final readonly class OppositeExpectation
return Targeted::make( return Targeted::make(
$original, $original,
fn (ObjectDescription $object): bool => $object->reflectionClass->getParentClass() !== false, fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || $object->reflectionClass->getParentClass() !== false,
'to extend a class', 'to extend a class',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -554,7 +554,7 @@ final readonly class OppositeExpectation
$original, $original,
function (ObjectDescription $object) use ($traits): bool { function (ObjectDescription $object) use ($traits): bool {
foreach ($traits as $trait) { foreach ($traits as $trait) {
if (in_array($trait, $object->reflectionClass->getTraitNames(), true)) { if (isset($object->reflectionClass) && in_array($trait, $object->reflectionClass->getTraitNames(), true)) {
return false; return false;
} }
} }
@ -582,7 +582,7 @@ final readonly class OppositeExpectation
$original, $original,
function (ObjectDescription $object) use ($interfaces): bool { function (ObjectDescription $object) use ($interfaces): bool {
foreach ($interfaces as $interface) { foreach ($interfaces as $interface) {
if ($object->reflectionClass->implementsInterface($interface)) { if (isset($object->reflectionClass) && $object->reflectionClass->implementsInterface($interface)) {
return false; return false;
} }
} }
@ -604,7 +604,7 @@ final readonly class OppositeExpectation
return Targeted::make( return Targeted::make(
$original, $original,
fn (ObjectDescription $object): bool => $object->reflectionClass->getInterfaceNames() !== [], fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || $object->reflectionClass->getInterfaceNames() !== [],
'to implement an interface', 'to implement an interface',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -628,7 +628,7 @@ final readonly class OppositeExpectation
return Targeted::make( return Targeted::make(
$original, $original,
fn (ObjectDescription $object): bool => ! str_starts_with($object->reflectionClass->getShortName(), $prefix), 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')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -644,7 +644,7 @@ final readonly class OppositeExpectation
return Targeted::make( return Targeted::make(
$original, $original,
fn (ObjectDescription $object): bool => ! str_ends_with($object->reflectionClass->getName(), $suffix), 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')), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
); );
@ -715,7 +715,7 @@ final readonly class OppositeExpectation
return Targeted::make( return Targeted::make(
$original, $original,
fn (ObjectDescription $object): bool => ! $object->reflectionClass->hasMethod('__invoke'), fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->hasMethod('__invoke'),
'to not be invokable', 'to not be invokable',
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')) FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))
); );
@ -731,7 +731,7 @@ final readonly class OppositeExpectation
return Targeted::make( return Targeted::make(
$original, $original,
fn (ObjectDescription $object): bool => $object->reflectionClass->getAttributes($attribute) === [], 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')) FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))
); );
@ -826,7 +826,8 @@ final readonly class OppositeExpectation
return Targeted::make( return Targeted::make(
$original, $original,
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isEnum() fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false
|| ! $object->reflectionClass->isEnum()
|| ! (new \ReflectionEnum($object->name))->isBacked() // @phpstan-ignore-line || ! (new \ReflectionEnum($object->name))->isBacked() // @phpstan-ignore-line
|| (string) (new \ReflectionEnum($object->name))->getBackingType() !== $backingType, // @phpstan-ignore-line || (string) (new \ReflectionEnum($object->name))->getBackingType() !== $backingType, // @phpstan-ignore-line
'not to be '.$backingType.' backed enum', 'not to be '.$backingType.' backed enum',

View File

@ -6,7 +6,7 @@ namespace Pest;
function version(): string function version(): string
{ {
return '3.8.1'; return '3.8.2';
} }
function testDirectory(string $file = ''): string function testDirectory(string $file = ''): string

View File

@ -1,5 +1,5 @@
Pest Testing Framework 3.8.1. Pest Testing Framework 3.8.2.
USAGE: pest <file> [options] USAGE: pest <file> [options]

View File

@ -1,3 +1,3 @@
Pest Testing Framework 3.8.1. Pest Testing Framework 3.8.2.