From f464a2fae5e30a18d1d2fe45a54f6d0da74eb5f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Re=CC=81mi=20Pelhate?= Date: Fri, 5 Sep 2025 11:23:49 +0200 Subject: [PATCH 1/4] =?UTF-8?q?Don=E2=80=99t=20require=20at=20least=202=20?= =?UTF-8?q?options?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/PHPUnit/DataProviders/EnumCase.php | 10 +++---- src/PHPUnit/DataProviders/EnumCaseTest.php | 31 +++++++++++++++------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/PHPUnit/DataProviders/EnumCase.php b/src/PHPUnit/DataProviders/EnumCase.php index 86f06a4..9f30cc9 100644 --- a/src/PHPUnit/DataProviders/EnumCase.php +++ b/src/PHPUnit/DataProviders/EnumCase.php @@ -10,7 +10,7 @@ use function array_rand; use function array_search; -use function count; +use function in_array; /** * @template TValue of UnitEnum @@ -33,15 +33,13 @@ final class EnumCase } } - /** - * @param TValue $instance - * @param array ...$options - */ public function __construct( + /* @var TValue */ public readonly UnitEnum $instance, + /* @param array ...$options */ UnitEnum ...$options, ) { - count($options) >= 2 or throw new ValueError('At least 2 options should should be given.'); + in_array($instance, $options, true) or throw new ValueError('Options should contain the given instance.'); foreach ($options as $option) { $option::class === $instance::class or throw new ValueError( diff --git a/src/PHPUnit/DataProviders/EnumCaseTest.php b/src/PHPUnit/DataProviders/EnumCaseTest.php index 10fa961..f1d4fdc 100644 --- a/src/PHPUnit/DataProviders/EnumCaseTest.php +++ b/src/PHPUnit/DataProviders/EnumCaseTest.php @@ -9,6 +9,7 @@ use Craftzing\TestBench\PHPUnit\Doubles\Enums\UnitEnum; use Faker\Factory; use Faker\Generator; +use Illuminate\Support\Arr; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; @@ -48,16 +49,14 @@ public static function enumFQCNs(): iterable #[Test] #[DataProvider('enumFQCNs')] /** @param class-string $enumFQCN */ - public function itCannotConstructWithoutAtLeastTwoOptions(string $enumFQCN): void + public function itCannotConstructWhenInstanceIsNotInOptions(string $enumFQCN): void { - $cases = $enumFQCN::cases(); + $options = $enumFQCN::cases(); + $case = Arr::pull($options, array_rand($options)); $this->expectException(ValueError::class); - new EnumCase( - $this->faker->randomElement($cases), - $this->faker->randomElement($cases), - ); + new EnumCase($case, ...$options); } #[Test] @@ -79,12 +78,24 @@ public function itCannotConstructWhenOptionsHaveDifferentTypeComparedToGivenInst #[Test] #[DataProvider('enumFQCNs')] /** @param class-string $enumFQCN */ - public function itCanConstructWithOptions(string $enumFQCN): void + public function itCanConstructWithSingleOption(string $enumFQCN): void { - $cases = $enumFQCN::cases(); - $case = $cases[array_rand($cases)]; + $options = $enumFQCN::cases(); + $case = $options[array_rand($options)]; - $provider = new EnumCase($case, ...$cases); + $provider = new EnumCase($case, $case); + + $this->assertSame($case, $provider->instance); + } + + #[Test] + #[DataProvider('enumFQCNs')] /** @param class-string $enumFQCN */ + public function itCanConstructWithMultipleOptions(string $enumFQCN): void + { + $options = $enumFQCN::cases(); + $case = $options[array_rand($options)]; + + $provider = new EnumCase($case, ...$options); $this->assertSame($case, $provider->instance); } From e06753cea0661b8c6e5ab77e28d16806839df080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Re=CC=81mi=20Pelhate?= Date: Fri, 5 Sep 2025 11:36:37 +0200 Subject: [PATCH 2/4] Explicitly test that different instance cannot be returned when configured with single option --- src/PHPUnit/DataProviders/EnumCase.php | 6 ++++++ src/PHPUnit/DataProviders/EnumCaseTest.php | 24 +++++++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/PHPUnit/DataProviders/EnumCase.php b/src/PHPUnit/DataProviders/EnumCase.php index 9f30cc9..dae7ca4 100644 --- a/src/PHPUnit/DataProviders/EnumCase.php +++ b/src/PHPUnit/DataProviders/EnumCase.php @@ -4,12 +4,14 @@ namespace Craftzing\TestBench\PHPUnit\DataProviders; +use LogicException; use ReflectionEnum; use UnitEnum; use ValueError; use function array_rand; use function array_search; +use function count; use function in_array; /** @@ -55,6 +57,10 @@ public function __construct( */ public function differentInstance(): UnitEnum { + count($this->options) > 1 or throw new LogicException( + self::class . ' was configured with a single option and can therefore not return a different instance.', + ); + $differentOptions = $this->options; unset($differentOptions[$this->instanceKeyInOptions]); diff --git a/src/PHPUnit/DataProviders/EnumCaseTest.php b/src/PHPUnit/DataProviders/EnumCaseTest.php index f1d4fdc..a034949 100644 --- a/src/PHPUnit/DataProviders/EnumCaseTest.php +++ b/src/PHPUnit/DataProviders/EnumCaseTest.php @@ -10,6 +10,7 @@ use Faker\Factory; use Faker\Generator; use Illuminate\Support\Arr; +use LogicException; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; @@ -104,13 +105,26 @@ public function itCanConstructWithMultipleOptions(string $enumFQCN): void #[DataProvider('enumFQCNs')] /** @param class-string $enumFQCN */ public function itCanReturnDifferentInstances(string $enumFQCN): void { - $cases = $enumFQCN::cases(); - $case = $cases[array_rand($cases)]; + $options = $enumFQCN::cases(); + $instance = $options[array_rand($options)]; + $provider = new EnumCase($instance, ...$options); - $provider = new EnumCase($case, ...$cases); + $differentInstance = $provider->differentInstance(); - $this->assertSame($case, $provider->instance); - $this->assertNotEquals($case, $provider->differentInstance()); + $this->assertNotEquals($instance, $differentInstance); + } + + #[Test] + #[DataProvider('enumFQCNs')] /** @param class-string $enumFQCN */ + public function itCannotReturnDifferentInstancesWithASingleOption(string $enumFQCN): void + { + $options = $enumFQCN::cases(); + $instance = $options[array_rand($options)]; + $provider = new EnumCase($instance, $instance); + + $this->expectException(LogicException::class); + + $provider->differentInstance(); } #[Test] From 7d7caf4607e1bb4fdba85f0df4565594b49f4e5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Re=CC=81mi=20Pelhate?= Date: Fri, 5 Sep 2025 11:38:53 +0200 Subject: [PATCH 3/4] Cleanup EnumCaseTest --- src/PHPUnit/DataProviders/EnumCaseTest.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/PHPUnit/DataProviders/EnumCaseTest.php b/src/PHPUnit/DataProviders/EnumCaseTest.php index a034949..7f005ff 100644 --- a/src/PHPUnit/DataProviders/EnumCaseTest.php +++ b/src/PHPUnit/DataProviders/EnumCaseTest.php @@ -64,17 +64,17 @@ public function itCannotConstructWhenInstanceIsNotInOptions(string $enumFQCN): v #[DataProvider('enumFQCNs')] /** @param class-string $enumFQCN */ public function itCannotConstructWhenOptionsHaveDifferentTypeComparedToGivenInstance(string $enumFQCN): void { - $cases = $enumFQCN::cases(); - $case = $this->faker->randomElement($cases); + $options = $enumFQCN::cases(); + $instance = $this->faker->randomElement($options); $differentEnumFQCN = $this->faker->randomElement(array_filter( self::ENUM_FQCNS, - fn (string $enumFQCN): bool => $enumFQCN !== $case::class, + fn (string $enumFQCN): bool => $enumFQCN !== $instance::class, )); - $differentEnumCase = $this->faker->randomElement($differentEnumFQCN::cases()); + $differentEnumInstance = $this->faker->randomElement($differentEnumFQCN::cases()); $this->expectException(ValueError::class); - new EnumCase($case, $differentEnumCase, $differentEnumCase); + new EnumCase($instance, $differentEnumInstance, $differentEnumInstance); } #[Test] @@ -82,11 +82,11 @@ public function itCannotConstructWhenOptionsHaveDifferentTypeComparedToGivenInst public function itCanConstructWithSingleOption(string $enumFQCN): void { $options = $enumFQCN::cases(); - $case = $options[array_rand($options)]; + $instance = $options[array_rand($options)]; - $provider = new EnumCase($case, $case); + $provider = new EnumCase($instance, $instance); - $this->assertSame($case, $provider->instance); + $this->assertSame($instance, $provider->instance); } #[Test] @@ -94,11 +94,11 @@ public function itCanConstructWithSingleOption(string $enumFQCN): void public function itCanConstructWithMultipleOptions(string $enumFQCN): void { $options = $enumFQCN::cases(); - $case = $options[array_rand($options)]; + $instance = $options[array_rand($options)]; - $provider = new EnumCase($case, ...$options); + $provider = new EnumCase($instance, ...$options); - $this->assertSame($case, $provider->instance); + $this->assertSame($instance, $provider->instance); } #[Test] From 7ad63707113a6d17b79d434f917e6e315e706df1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Re=CC=81mi=20Pelhate?= Date: Fri, 5 Sep 2025 11:45:56 +0200 Subject: [PATCH 4/4] Cleanup EnumCase --- src/PHPUnit/DataProviders/EnumCase.php | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/src/PHPUnit/DataProviders/EnumCase.php b/src/PHPUnit/DataProviders/EnumCase.php index dae7ca4..096836b 100644 --- a/src/PHPUnit/DataProviders/EnumCase.php +++ b/src/PHPUnit/DataProviders/EnumCase.php @@ -9,35 +9,24 @@ use UnitEnum; use ValueError; +use function array_filter; use function array_rand; -use function array_search; use function count; use function in_array; /** * @template TValue of UnitEnum */ -final class EnumCase +final readonly class EnumCase { /** * @var array */ - private readonly array $options; - - private int|string $instanceKeyInOptions { - get { - $key = array_search($this->instance, $this->options, true); - - return match ($key) { - false => '', - default => $key, - }; - } - } + private array $options; public function __construct( /* @var TValue */ - public readonly UnitEnum $instance, + public UnitEnum $instance, /* @param array ...$options */ UnitEnum ...$options, ) { @@ -60,10 +49,7 @@ public function differentInstance(): UnitEnum count($this->options) > 1 or throw new LogicException( self::class . ' was configured with a single option and can therefore not return a different instance.', ); - - $differentOptions = $this->options; - - unset($differentOptions[$this->instanceKeyInOptions]); + $differentOptions = array_filter($this->options, fn (UnitEnum $option): bool => $option !== $this->instance); return $differentOptions[array_rand($differentOptions)]; }