Skip to content

Commit c3ce9bf

Browse files
committed
feat: faker improvements
1 parent 478547c commit c3ce9bf

File tree

8 files changed

+87
-25
lines changed

8 files changed

+87
-25
lines changed

src/Core/Fake/Faker.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ public function __construct(
199199
Notation $case = Notation::SNAKE,
200200
array $formatters = [],
201201
?string $locale = null,
202+
private readonly bool $ignoreFromDefaultValue = false,
202203
) {
203204
parent::__construct($case, $formatters);
204205

@@ -238,10 +239,14 @@ public function generator(): Generator
238239

239240
/**
240241
* @param array<ReflectionParameter> $parameters
242+
* @throws ReflectionException
241243
*/
242244
private function resolveParameters(array $parameters, Set $presets): Set
243245
{
244246
$values = [];
247+
$fromDefaultValue = $this->ignoreFromDefaultValue
248+
? null
249+
: new FromDefaultValue($this->notation, $this->formatters);
245250
foreach ($parameters as $parameter) {
246251
$field = $this->casedField($parameter);
247252
$generated = (new FromDependency($this->notation, $this->formatters))
@@ -250,7 +255,7 @@ private function resolveParameters(array $parameters, Set $presets): Set
250255
->then(new FromTypeBuiltin($this->notation, $this->formatters))
251256
->then(new FromTypeAttributes($this->notation, $this->formatters))
252257
->then(new FromEnum($this->notation, $this->formatters))
253-
->then(new FromDefaultValue($this->notation, $this->formatters))
258+
->then($fromDefaultValue)
254259
->then(new FromPreset($this->notation, $this->formatters))
255260
->resolve($parameter, $presets);
256261

src/Core/Fake/Resolver.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@ abstract class Resolver extends Faker
1717
{
1818
protected ?Resolver $previous = null;
1919

20-
final public function then(Resolver $resolver): Resolver
20+
final public function then(?Resolver $resolver): Resolver
2121
{
22+
if ($resolver === null) {
23+
return $this;
24+
}
2225
$resolver->previous($this);
2326
return $resolver;
2427
}

src/Core/Fake/Resolver/FromDefaultValue.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,13 @@
77
use Constructo\Core\Fake\Resolver;
88
use Constructo\Support\Set;
99
use Constructo\Support\Value;
10-
use ReflectionException;
1110
use ReflectionParameter;
1211

1312
final class FromDefaultValue extends Resolver
1413
{
15-
/**
16-
* @throws ReflectionException
17-
*/
1814
public function resolve(ReflectionParameter $parameter, Set $presets): ?Value
1915
{
20-
if ($parameter->isOptional() || $parameter->isDefaultValueAvailable()) {
16+
if ($parameter->isDefaultValueAvailable()) {
2117
return new Value($parameter->getDefaultValue());
2218
}
2319
if ($parameter->allowsNull()) {

src/Core/Fake/Resolver/FromEnum.php

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
use Constructo\Support\Set;
1010
use Constructo\Support\Value;
1111
use Random\RandomException;
12+
use ReflectionEnum;
13+
use ReflectionEnumUnitCase;
1214
use ReflectionNamedType;
1315
use ReflectionParameter;
1416

@@ -24,26 +26,28 @@ public function resolve(ReflectionParameter $parameter, Set $presets): ?Value
2426
return parent::resolve($parameter, $presets);
2527
}
2628
$enum = $type->getName();
27-
return enum_exists($enum)
28-
? $this->resolveEnumValue($enum, $parameter, $presets)
29-
: parent::resolve($parameter, $presets);
29+
if (! enum_exists($enum)) {
30+
return parent::resolve($parameter, $presets);
31+
}
32+
$reflectionEnum = new ReflectionEnum($enum);
33+
return $this->resolveEnumValue($reflectionEnum, $parameter, $presets);
3034
}
3135

3236
/**
3337
* @throws RandomException
3438
*/
35-
private function resolveEnumValue(string $enum, ReflectionParameter $parameter, Set $presets): ?Value
39+
private function resolveEnumValue(ReflectionEnum $reflectionEnum, ReflectionParameter $parameter, Set $presets): ?Value
3640
{
37-
if (! is_subclass_of($enum, BackedEnum::class)) {
41+
/** @var ReflectionEnumUnitCase[] $enumCases */
42+
$enumCases = $reflectionEnum->getCases();
43+
if (empty($enumCases)) {
3844
return parent::resolve($parameter, $presets);
3945
}
4046

41-
$enumValues = $enum::cases();
42-
if (empty($enumValues)) {
43-
return parent::resolve($parameter, $presets);
47+
$case = $enumCases[random_int(0, count($enumCases) - 1)]->getValue();
48+
if ($case instanceof BackedEnum) {
49+
return new Value($case->value);
4450
}
45-
46-
$randomValue = $enumValues[random_int(0, count($enumValues) - 1)]->value;
47-
return new Value($randomValue);
51+
return new Value($case);
4852
}
4953
}

src/Testing/FakerExtension.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,28 @@
55
namespace Constructo\Testing;
66

77
use Constructo\Core\Fake\Faker;
8+
use Constructo\Support\Reflective\Notation;
89
use Faker\Generator;
910

1011
trait FakerExtension
1112
{
1213
private ?Faker $faker = null;
1314

14-
protected function faker(): Faker
15+
protected function faker(
16+
Notation $case = Notation::SNAKE,
17+
array $formatters = [],
18+
?string $locale = null,
19+
bool $ignoreFromDefaultValue = false,
20+
): Faker
1521
{
1622
if ($this->faker === null) {
17-
$this->faker = $this->make(Faker::class);
23+
$args = [
24+
'case' => $case,
25+
'formatters' => $formatters,
26+
'locale' => $locale,
27+
'ignoreFromDefaultValue' => $ignoreFromDefaultValue,
28+
];
29+
$this->faker = $this->make(Faker::class, $args);
1830
}
1931
return $this->faker;
2032
}

tests/Core/Fake/FakerTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55
namespace Constructo\Test\Core\Fake;
66

77
use Constructo\Core\Fake\Faker;
8+
use Constructo\Core\Fake\Options;
9+
use Constructo\Core\Serialize\Builder;
810
use Constructo\Support\Reflective\Notation;
911
use Constructo\Test\Stub\Builtin;
1012
use Constructo\Test\Stub\EnumVariety;
13+
use Constructo\Test\Stub\EnumerationAndNullable;
1114
use PHPUnit\Framework\TestCase;
1215

1316
final class FakerTest extends TestCase
@@ -231,6 +234,19 @@ public function testShouldHandleComplexParameterResolution(): void
231234
$this->assertIsArray($result->get('array'));
232235
}
233236

237+
public function testShouldHandleNullableAndNotBackedEnum(): void
238+
{
239+
$faker = new Faker(ignoreFromDefaultValue: true);
240+
$builder = new Builder();
241+
242+
$values = $faker->fake(EnumerationAndNullable::class);
243+
$instance = $builder->build(EnumerationAndNullable::class, $values);
244+
245+
$this->assertSame($values->get('unit'), $instance->unit);
246+
$this->assertSame($values->get('backed'), $instance->backed->value);
247+
$this->assertSame($values->get('builtin')['string'], $instance->builtin->string);
248+
}
249+
234250
public function testShouldGenerateWithArguments(): void
235251
{
236252
$faker = new Faker();

tests/Core/Fake/Resolver/FromEnumTest.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@
44

55
namespace Constructo\Test\Core\Fake\Resolver;
66

7+
use Constructo\Core\Fake\Resolver\FromEnum;
8+
use Constructo\Support\Reflective\Factory\Target;
79
use Constructo\Support\Reflective\Notation;
810
use Constructo\Support\Set;
9-
use PHPUnit\Framework\TestCase;
10-
use Constructo\Support\Reflective\Factory\Target;
1111
use Constructo\Test\Stub\DeepDeepDown;
1212
use Constructo\Test\Stub\EnumVariety;
1313
use Constructo\Test\Stub\NotNative;
14+
use Constructo\Test\Stub\Type\Enumeration;
1415
use Constructo\Test\Stub\Variety;
15-
use Constructo\Core\Fake\Resolver\FromEnum;
16+
use PHPUnit\Framework\TestCase;
1617

1718
final class FromEnumTest extends TestCase
1819
{
@@ -28,7 +29,13 @@ public function testShouldResolveBackedEnum(): void
2829
$value = $resolver->resolve($backed, $set);
2930

3031
$this->assertNotNull($value);
31-
$this->assertContains($value->content, ['foo', 'bar', 'baz']);
32+
$this->assertContains($value->content,
33+
[
34+
'foo',
35+
'bar',
36+
'baz',
37+
]
38+
);
3239
}
3340

3441
public function testShouldNotResolveNonBackedEnum(): void
@@ -42,7 +49,7 @@ public function testShouldNotResolveNonBackedEnum(): void
4249
$set = Set::createFrom([]);
4350
$value = $resolver->resolve($enum, $set);
4451

45-
$this->assertNull($value);
52+
$this->assertInstanceOf(Enumeration::class, $value->content);
4653
}
4754

4855
public function testShouldResolveEnumInUnionType(): void
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Constructo\Test\Stub;
6+
7+
use Constructo\Test\Stub\Type\BackedEnumeration;
8+
use Constructo\Test\Stub\Type\Enumeration;
9+
10+
readonly class EnumerationAndNullable
11+
{
12+
public function __construct(
13+
public Enumeration $unit,
14+
public BackedEnumeration $backed,
15+
public ?Builtin $builtin,
16+
public ?array $drivers,
17+
) {
18+
}
19+
}

0 commit comments

Comments
 (0)