Skip to content

Commit fef2978

Browse files
authored
fix: EnumCase provider should not require at least 2 options (#18)
* Don’t require at least 2 options * Explicitly test that different instance cannot be returned when configured with single option * Cleanup EnumCaseTest * Cleanup EnumCase
1 parent c37fcd3 commit fef2978

File tree

2 files changed

+59
-44
lines changed

2 files changed

+59
-44
lines changed

src/PHPUnit/DataProviders/EnumCase.php

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,33 @@
44

55
namespace Craftzing\TestBench\PHPUnit\DataProviders;
66

7+
use LogicException;
78
use ReflectionEnum;
89
use UnitEnum;
910
use ValueError;
1011

12+
use function array_filter;
1113
use function array_rand;
12-
use function array_search;
1314
use function count;
15+
use function in_array;
1416

1517
/**
1618
* @template TValue of UnitEnum
1719
*/
18-
final class EnumCase
20+
final readonly class EnumCase
1921
{
2022
/**
2123
* @var array<int, TValue>
2224
*/
23-
private readonly array $options;
25+
private array $options;
2426

25-
private int|string $instanceKeyInOptions {
26-
get {
27-
$key = array_search($this->instance, $this->options, true);
28-
29-
return match ($key) {
30-
false => '',
31-
default => $key,
32-
};
33-
}
34-
}
35-
36-
/**
37-
* @param TValue $instance
38-
* @param array<int, TValue> ...$options
39-
*/
4027
public function __construct(
41-
public readonly UnitEnum $instance,
28+
/* @var TValue */
29+
public UnitEnum $instance,
30+
/* @param array<int, TValue> ...$options */
4231
UnitEnum ...$options,
4332
) {
44-
count($options) >= 2 or throw new ValueError('At least 2 options should should be given.');
33+
in_array($instance, $options, true) or throw new ValueError('Options should contain the given instance.');
4534

4635
foreach ($options as $option) {
4736
$option::class === $instance::class or throw new ValueError(
@@ -57,9 +46,10 @@ public function __construct(
5746
*/
5847
public function differentInstance(): UnitEnum
5948
{
60-
$differentOptions = $this->options;
61-
62-
unset($differentOptions[$this->instanceKeyInOptions]);
49+
count($this->options) > 1 or throw new LogicException(
50+
self::class . ' was configured with a single option and can therefore not return a different instance.',
51+
);
52+
$differentOptions = array_filter($this->options, fn (UnitEnum $option): bool => $option !== $this->instance);
6353

6454
return $differentOptions[array_rand($differentOptions)];
6555
}

src/PHPUnit/DataProviders/EnumCaseTest.php

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
use Craftzing\TestBench\PHPUnit\Doubles\Enums\UnitEnum;
1010
use Faker\Factory;
1111
use Faker\Generator;
12+
use Illuminate\Support\Arr;
13+
use LogicException;
1214
use PHPUnit\Framework\Attributes\DataProvider;
1315
use PHPUnit\Framework\Attributes\Test;
1416
use PHPUnit\Framework\TestCase;
@@ -48,58 +50,81 @@ public static function enumFQCNs(): iterable
4850

4951
#[Test]
5052
#[DataProvider('enumFQCNs')] /** @param class-string<UnitEnumInterface> $enumFQCN */
51-
public function itCannotConstructWithoutAtLeastTwoOptions(string $enumFQCN): void
53+
public function itCannotConstructWhenInstanceIsNotInOptions(string $enumFQCN): void
5254
{
53-
$cases = $enumFQCN::cases();
55+
$options = $enumFQCN::cases();
56+
$case = Arr::pull($options, array_rand($options));
5457

5558
$this->expectException(ValueError::class);
5659

57-
new EnumCase(
58-
$this->faker->randomElement($cases),
59-
$this->faker->randomElement($cases),
60-
);
60+
new EnumCase($case, ...$options);
6161
}
6262

6363
#[Test]
6464
#[DataProvider('enumFQCNs')] /** @param class-string<UnitEnumInterface> $enumFQCN */
6565
public function itCannotConstructWhenOptionsHaveDifferentTypeComparedToGivenInstance(string $enumFQCN): void
6666
{
67-
$cases = $enumFQCN::cases();
68-
$case = $this->faker->randomElement($cases);
67+
$options = $enumFQCN::cases();
68+
$instance = $this->faker->randomElement($options);
6969
$differentEnumFQCN = $this->faker->randomElement(array_filter(
7070
self::ENUM_FQCNS,
71-
fn (string $enumFQCN): bool => $enumFQCN !== $case::class,
71+
fn (string $enumFQCN): bool => $enumFQCN !== $instance::class,
7272
));
73-
$differentEnumCase = $this->faker->randomElement($differentEnumFQCN::cases());
73+
$differentEnumInstance = $this->faker->randomElement($differentEnumFQCN::cases());
7474

7575
$this->expectException(ValueError::class);
7676

77-
new EnumCase($case, $differentEnumCase, $differentEnumCase);
77+
new EnumCase($instance, $differentEnumInstance, $differentEnumInstance);
7878
}
7979

8080
#[Test]
8181
#[DataProvider('enumFQCNs')] /** @param class-string<UnitEnumInterface> $enumFQCN */
82-
public function itCanConstructWithOptions(string $enumFQCN): void
82+
public function itCanConstructWithSingleOption(string $enumFQCN): void
8383
{
84-
$cases = $enumFQCN::cases();
85-
$case = $cases[array_rand($cases)];
84+
$options = $enumFQCN::cases();
85+
$instance = $options[array_rand($options)];
8686

87-
$provider = new EnumCase($case, ...$cases);
87+
$provider = new EnumCase($instance, $instance);
8888

89-
$this->assertSame($case, $provider->instance);
89+
$this->assertSame($instance, $provider->instance);
90+
}
91+
92+
#[Test]
93+
#[DataProvider('enumFQCNs')] /** @param class-string<UnitEnumInterface> $enumFQCN */
94+
public function itCanConstructWithMultipleOptions(string $enumFQCN): void
95+
{
96+
$options = $enumFQCN::cases();
97+
$instance = $options[array_rand($options)];
98+
99+
$provider = new EnumCase($instance, ...$options);
100+
101+
$this->assertSame($instance, $provider->instance);
90102
}
91103

92104
#[Test]
93105
#[DataProvider('enumFQCNs')] /** @param class-string<UnitEnumInterface> $enumFQCN */
94106
public function itCanReturnDifferentInstances(string $enumFQCN): void
95107
{
96-
$cases = $enumFQCN::cases();
97-
$case = $cases[array_rand($cases)];
108+
$options = $enumFQCN::cases();
109+
$instance = $options[array_rand($options)];
110+
$provider = new EnumCase($instance, ...$options);
111+
112+
$differentInstance = $provider->differentInstance();
113+
114+
$this->assertNotEquals($instance, $differentInstance);
115+
}
116+
117+
#[Test]
118+
#[DataProvider('enumFQCNs')] /** @param class-string<UnitEnumInterface> $enumFQCN */
119+
public function itCannotReturnDifferentInstancesWithASingleOption(string $enumFQCN): void
120+
{
121+
$options = $enumFQCN::cases();
122+
$instance = $options[array_rand($options)];
123+
$provider = new EnumCase($instance, $instance);
98124

99-
$provider = new EnumCase($case, ...$cases);
125+
$this->expectException(LogicException::class);
100126

101-
$this->assertSame($case, $provider->instance);
102-
$this->assertNotEquals($case, $provider->differentInstance());
127+
$provider->differentInstance();
103128
}
104129

105130
#[Test]

0 commit comments

Comments
 (0)