From c6244a8712968dbac88eb998e7ff3b5caa556b0d Mon Sep 17 00:00:00 2001 From: Nuno Maduro Date: Thu, 17 Apr 2025 11:52:59 +0100 Subject: [PATCH] Release 3.8.2 --- src/Expectation.php | 38 +++++++++++-------- src/Expectations/OppositeExpectation.php | 35 ++++++++--------- src/Pest.php | 2 +- ...isual_snapshot_of_help_command_output.snap | 2 +- ...isual_snapshot_of_help_command_output.snap | 2 +- 5 files changed, 43 insertions(+), 36 deletions(-) diff --git a/src/Expectation.php b/src/Expectation.php index ebfd6302..1bef5a8c 100644 --- a/src/Expectation.php +++ b/src/Expectation.php @@ -535,7 +535,7 @@ final class Expectation { return Targeted::make( $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', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -548,7 +548,7 @@ final class Expectation { return Targeted::make( $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', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -561,7 +561,7 @@ final class Expectation { return Targeted::make( $this, - fn (ObjectDescription $object): bool => $object->reflectionClass->isTrait(), + fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isTrait(), 'to be trait', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -582,7 +582,7 @@ final class Expectation { return Targeted::make( $this, - fn (ObjectDescription $object): bool => $object->reflectionClass->isAbstract(), + fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isAbstract(), 'to be abstract', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -599,7 +599,7 @@ final class Expectation return Targeted::make( $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)), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -670,7 +670,7 @@ final class Expectation { return Targeted::make( $this, - fn (ObjectDescription $object): bool => $object->reflectionClass->isEnum(), + fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isEnum(), 'to be enum', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -712,7 +712,7 @@ final class Expectation { return Targeted::make( $this, - fn (ObjectDescription $object): bool => $object->reflectionClass->isInterface(), + fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isInterface(), 'to be interface', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -733,7 +733,7 @@ final class Expectation { return Targeted::make( $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), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -773,6 +773,10 @@ final class Expectation $this, function (ObjectDescription $object) use ($traits): bool { foreach ($traits as $trait) { + if (isset($object->reflectionClass) === false) { + return false; + } + if (! in_array($trait, $object->reflectionClass->getTraitNames(), true)) { return false; } @@ -792,7 +796,7 @@ final class Expectation { return Targeted::make( $this, - fn (ObjectDescription $object): bool => $object->reflectionClass->getInterfaceNames() === [], + fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->getInterfaceNames() === [], 'to implement nothing', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -809,7 +813,8 @@ final class Expectation return Targeted::make( $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()) === [], "to only implement '".implode("', '", $interfaces)."'", FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), @@ -823,7 +828,7 @@ final class Expectation { return Targeted::make( $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}'", FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -836,7 +841,7 @@ final class Expectation { return Targeted::make( $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}'", FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -855,7 +860,7 @@ final class Expectation $this, function (ObjectDescription $object) use ($interfaces): bool { foreach ($interfaces as $interface) { - if (! $object->reflectionClass->implementsInterface($interface)) { + if (! isset($object->reflectionClass) || ! $object->reflectionClass->implementsInterface($interface)) { return false; } } @@ -928,7 +933,7 @@ final class Expectation { return Targeted::make( $this, - fn (ObjectDescription $object): bool => $object->reflectionClass->hasMethod('__invoke'), + fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->hasMethod('__invoke'), 'to be invokable', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')) ); @@ -1037,7 +1042,7 @@ final class Expectation { return Targeted::make( $this, - fn (ObjectDescription $object): bool => $object->reflectionClass->getAttributes($attribute) !== [], + fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->getAttributes($attribute) !== [], "to have attribute '{$attribute}'", FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -1066,7 +1071,8 @@ final class Expectation { return Targeted::make( $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 && (string) (new ReflectionEnum($object->name))->getBackingType() === $backingType, // @phpstan-ignore-line 'to be '.$backingType.' backed enum', diff --git a/src/Expectations/OppositeExpectation.php b/src/Expectations/OppositeExpectation.php index c4b0a0a5..d5c3f083 100644 --- a/src/Expectations/OppositeExpectation.php +++ b/src/Expectations/OppositeExpectation.php @@ -193,7 +193,7 @@ final readonly class OppositeExpectation return Targeted::make( $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', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -209,7 +209,7 @@ final readonly class OppositeExpectation return Targeted::make( $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', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -225,7 +225,7 @@ final readonly class OppositeExpectation return Targeted::make( $original, - fn (ObjectDescription $object): bool => ! $object->reflectionClass->isTrait(), + fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isTrait(), 'not to be trait', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -249,7 +249,7 @@ final readonly class OppositeExpectation return Targeted::make( $original, - fn (ObjectDescription $object): bool => ! $object->reflectionClass->isAbstract(), + fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isAbstract(), 'not to be abstract', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -271,7 +271,7 @@ final readonly class OppositeExpectation $original, fn (ObjectDescription $object): bool => array_filter( $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), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), @@ -436,7 +436,7 @@ final readonly class OppositeExpectation return Targeted::make( $original, - fn (ObjectDescription $object): bool => ! $object->reflectionClass->isEnum(), + fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isEnum(), 'not to be enum', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -484,7 +484,7 @@ final readonly class OppositeExpectation return Targeted::make( $original, - fn (ObjectDescription $object): bool => ! $object->reflectionClass->isInterface(), + fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isInterface(), 'not to be interface', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -508,7 +508,7 @@ final readonly class OppositeExpectation return Targeted::make( $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), FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -524,7 +524,7 @@ final readonly class OppositeExpectation return Targeted::make( $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', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -554,7 +554,7 @@ final readonly class OppositeExpectation $original, function (ObjectDescription $object) use ($traits): bool { 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; } } @@ -582,7 +582,7 @@ final readonly class OppositeExpectation $original, function (ObjectDescription $object) use ($interfaces): bool { foreach ($interfaces as $interface) { - if ($object->reflectionClass->implementsInterface($interface)) { + if (isset($object->reflectionClass) && $object->reflectionClass->implementsInterface($interface)) { return false; } } @@ -604,7 +604,7 @@ final readonly class OppositeExpectation return Targeted::make( $original, - fn (ObjectDescription $object): bool => $object->reflectionClass->getInterfaceNames() !== [], + fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || $object->reflectionClass->getInterfaceNames() !== [], 'to implement an interface', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -628,7 +628,7 @@ final readonly class OppositeExpectation return Targeted::make( $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}'", FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -644,7 +644,7 @@ final readonly class OppositeExpectation return Targeted::make( $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}'", FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); @@ -715,7 +715,7 @@ final readonly class OppositeExpectation return Targeted::make( $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', FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')) ); @@ -731,7 +731,7 @@ final readonly class OppositeExpectation return Targeted::make( $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}'", FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')) ); @@ -826,7 +826,8 @@ final readonly class OppositeExpectation return Targeted::make( $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 || (string) (new \ReflectionEnum($object->name))->getBackingType() !== $backingType, // @phpstan-ignore-line 'not to be '.$backingType.' backed enum', diff --git a/src/Pest.php b/src/Pest.php index 077a04c2..db27e206 100644 --- a/src/Pest.php +++ b/src/Pest.php @@ -6,7 +6,7 @@ namespace Pest; function version(): string { - return '3.8.1'; + return '3.8.2'; } function testDirectory(string $file = ''): string diff --git a/tests/.pest/snapshots/Visual/Help/visual_snapshot_of_help_command_output.snap b/tests/.pest/snapshots/Visual/Help/visual_snapshot_of_help_command_output.snap index 5646dca8..da7acad7 100644 --- a/tests/.pest/snapshots/Visual/Help/visual_snapshot_of_help_command_output.snap +++ b/tests/.pest/snapshots/Visual/Help/visual_snapshot_of_help_command_output.snap @@ -1,5 +1,5 @@ - Pest Testing Framework 3.8.1. + Pest Testing Framework 3.8.2. USAGE: pest [options] diff --git a/tests/.pest/snapshots/Visual/Version/visual_snapshot_of_help_command_output.snap b/tests/.pest/snapshots/Visual/Version/visual_snapshot_of_help_command_output.snap index 7775b987..cd2d2cfb 100644 --- a/tests/.pest/snapshots/Visual/Version/visual_snapshot_of_help_command_output.snap +++ b/tests/.pest/snapshots/Visual/Version/visual_snapshot_of_help_command_output.snap @@ -1,3 +1,3 @@ - Pest Testing Framework 3.8.1. + Pest Testing Framework 3.8.2.