1010use InvalidArgumentException ;
1111use Tests \Fixtures \Enums \Color ;
1212use Tests \Fixtures \Enums \Status ;
13+ use Tests \Fixtures \Enums \StatusCode ;
1314
14- final class WithEnumCasting extends ImmutableDTO
15+ final class StatusDto extends ImmutableDTO
1516{
1617 public function __construct (
1718 #[CastWith(new EnumCaster (Status::class))]
1819 public Status $ status ,
20+ ) {}
21+ }
1922
23+ final class ColorDto extends ImmutableDTO
24+ {
25+ public function __construct (
2026 #[CastWith(new EnumCaster (Color::class))]
21- public Color $ color
27+ public Color $ color ,
28+ ) {}
29+ }
30+
31+ final class StatusCodeDto extends ImmutableDTO
32+ {
33+ public function __construct (
34+ #[CastWith(new EnumCaster (StatusCode::class))]
35+ public StatusCode $ statusCode ,
36+ ) {}
37+ }
38+
39+ final class CombinedDto extends ImmutableDTO
40+ {
41+ public function __construct (
42+ #[CastWith(new EnumCaster (Status::class))]
43+ public Status $ status ,
44+
45+ #[CastWith(new EnumCaster (StatusCode::class))]
46+ public ?StatusCode $ statusCode ,
2247 ) {}
2348}
2449
2550it ('can cast string to backed enum using exact value ' , function (): void {
26- $ dto = WithEnumCasting ::from ([
51+ $ dto = StatusDto ::from ([
2752 'status ' => 'active ' ,
28- 'color ' => 'RED ' ,
2953 ]);
3054
3155 expect ($ dto ->status )
32- ->toBe (Status::ACTIVE )
33- ->and ($ dto ->color )
34- ->toBe (Color::RED );
56+ ->toBe (Status::ACTIVE );
3557});
3658
3759it ('can cast string to backed enum using case-insensitive value ' , function (): void {
38- $ dto = WithEnumCasting ::from ([
60+ $ dto = StatusDto ::from ([
3961 'status ' => 'ACTIVE ' ,
40- 'color ' => 'RED ' ,
4162 ]);
4263
4364 expect ($ dto ->status )
4465 ->toBe (Status::ACTIVE );
4566});
4667
68+ it ('can cast int backed enum using int value ' , function (): void {
69+ $ dto = StatusCodeDto::from ([
70+ 'statusCode ' => 100 ,
71+ ]);
72+
73+ expect ($ dto ->statusCode )
74+ ->toBe (StatusCode::PENDING );
75+ });
76+
77+ it ('can cast int backed enum using string value ' , function (): void {
78+ $ dto = StatusCodeDto::from ([
79+ 'statusCode ' => '300 ' ,
80+ ]);
81+
82+ expect ($ dto ->statusCode )
83+ ->toBe (StatusCode::INACTIVE );
84+ });
85+
4786it ('can handle existing enum instances ' , function (): void {
48- $ dto = WithEnumCasting ::from ([
87+ $ dto1 = StatusDto ::from ([
4988 'status ' => Status::PENDING ,
89+ ]);
90+
91+ $ dto2 = ColorDto::from ([
5092 'color ' => Color::GREEN ,
5193 ]);
5294
53- expect ($ dto ->status )
95+ expect ($ dto1 ->status )
5496 ->toBe (Status::PENDING )
55- ->and ($ dto ->color )
97+ ->and ($ dto2 ->color )
5698 ->toBe (Color::GREEN );
5799});
58100
59101it ('can cast string to unit enum using case name ' , function (): void {
60- $ dto = WithEnumCasting ::from ([
102+ $ dto = ColorDto ::from ([
61103 'status ' => 'active ' ,
62104 'color ' => 'BLUE ' ,
63105 ]);
@@ -67,8 +109,7 @@ public function __construct(
67109});
68110
69111it ('can cast string to unit enum using case-insensitive name ' , function (): void {
70- $ dto = WithEnumCasting::from ([
71- 'status ' => 'active ' ,
112+ $ dto = ColorDto::from ([
72113 'color ' => 'blue ' ,
73114 ]);
74115
@@ -77,15 +118,13 @@ public function __construct(
77118});
78119
79120it ('throws exception for invalid backed enum value ' , function (): void {
80- WithEnumCasting ::from ([
121+ StatusDto ::from ([
81122 'status ' => 'unknown ' ,
82- 'color ' => 'RED ' ,
83123 ]);
84124})->throws (InvalidArgumentException::class, 'Cannot cast value to enum Tests\Fixtures\Enums\Status ' );
85125
86126it ('throws exception for invalid unit enum name ' , function (): void {
87- WithEnumCasting::from ([
88- 'status ' => 'active ' ,
127+ ColorDto::from ([
89128 'color ' => 'YELLOW ' ,
90129 ]);
91130})->throws (InvalidArgumentException::class, 'Cannot cast value to enum Tests\Fixtures\Enums\Color: no matching case found ' );
@@ -99,3 +138,28 @@ public function __construct(
99138 $ caster = new EnumCaster (Color::class);
100139 $ caster ->cast (123 );
101140})->throws (InvalidArgumentException::class, 'Cannot cast value to enum Tests\Fixtures\Enums\Color: no matching case found ' );
141+
142+ it ('can handle optional property ' , function (): void {
143+ $ dto = CombinedDto::from ([
144+ 'status ' => Status::PENDING ,
145+ ]);
146+
147+ expect ($ dto ->status )
148+ ->toBe (Status::PENDING );
149+
150+ expect ($ dto ->statusCode )
151+ ->toBeNull ();
152+ });
153+
154+ it ('can handle null property ' , function (): void {
155+ $ dto = CombinedDto::from ([
156+ 'status ' => Status::PENDING ,
157+ 'statusCode ' => null ,
158+ ]);
159+
160+ expect ($ dto ->status )
161+ ->toBe (Status::PENDING );
162+
163+ expect ($ dto ->statusCode )
164+ ->toBeNull ();
165+ });
0 commit comments