forked from CuyZ/Valinor
-
Notifications
You must be signed in to change notification settings - Fork 0
/
UnionOfObjectsMappingTest.php
151 lines (127 loc) · 4.09 KB
/
UnionOfObjectsMappingTest.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
<?php
declare(strict_types=1);
namespace CuyZ\Valinor\Tests\Integration\Mapping\Object;
use CuyZ\Valinor\Mapper\MappingError;
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
use CuyZ\Valinor\Tests\Integration\Mapping\Fixture\NativeUnionOfObjects;
final class UnionOfObjectsMappingTest extends IntegrationTest
{
/**
* @requires PHP >= 8
*/
public function test_object_type_is_narrowed_correctly_for_simple_case(): void
{
try {
$resultFoo = $this->mapperBuilder->mapper()->map(NativeUnionOfObjects::class, [
'foo' => 'foo'
]);
$resultBar = $this->mapperBuilder->mapper()->map(NativeUnionOfObjects::class, [
'bar' => 'bar'
]);
} catch (MappingError $error) {
$this->mappingFail($error);
}
self::assertInstanceOf(\CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SomeFooObject::class, $resultFoo->object);
self::assertInstanceOf(\CuyZ\Valinor\Tests\Integration\Mapping\Fixture\SomeBarObject::class, $resultBar->object);
}
public function test_object_type_is_narrowed_correctly_for_simple_array_case(): void
{
try {
$result = $this->mapperBuilder->mapper()->map(UnionOfFooAndBar::class, [
'foo' => ['foo' => 'foo'],
'bar' => ['bar' => 'bar'],
]);
} catch (MappingError $error) {
$this->mappingFail($error);
}
self::assertInstanceOf(SomeFooObject::class, $result->objects['foo']);
self::assertInstanceOf(SomeBarObject::class, $result->objects['bar']);
}
public function test_objects_sharing_one_property_are_resolved_correctly(): void
{
try {
$result = $this->mapperBuilder->mapper()->map(UnionOfFooAndBarAndFoo::class, [
['foo' => 'foo'],
['foo' => 'foo', 'bar' => 'bar'],
]);
} catch (MappingError $error) {
$this->mappingFail($error);
}
self::assertInstanceOf(SomeFooObject::class, $result->objects[0]);
self::assertInstanceOf(SomeFooAndBarObject::class, $result->objects[1]);
}
/**
*
* @dataProvider mapping_error_when_cannot_resolve_union_data_provider
*
* @param class-string $className
* @param mixed[] $source
*/
public function test_mapping_error_when_cannot_resolve_union(string $className, array $source): void
{
try {
$this->mapperBuilder->mapper()->map($className, $source);
self::fail('No mapping error when one was expected');
} catch (MappingError $exception) {
$error = $exception->node()->children()['objects']->children()[0]->messages()[0];
self::assertSame('1641406600', $error->code());
}
}
public function mapping_error_when_cannot_resolve_union_data_provider(): iterable
{
yield [
'className' => UnionOfFooAndBar::class,
'source' => [['foo' => 'foo', 'bar' => 'bar']],
];
yield [
'className' => UnionOfFooAndBarAndFiz::class,
'source' => [['foo' => 'foo', 'bar' => 'bar', 'fiz' => 'fiz']],
];
yield [
'className' => UnionOfFooAndAnotherFoo::class,
'source' => [['foo' => 'foo']],
];
}
}
final class UnionOfFooAndBar
{
/** @var array<SomeFooObject|SomeBarObject> */
public array $objects;
}
final class UnionOfFooAndAnotherFoo
{
/** @var array<SomeFooObject|SomeOtherFooObject> */
public array $objects;
}
final class UnionOfFooAndBarAndFoo
{
/** @var array<SomeFooAndBarObject|SomeFooObject> */
public array $objects;
}
final class UnionOfFooAndBarAndFiz
{
/** @var array<SomeFooObject|SomeBarAndFizObject> */
public array $objects;
}
final class SomeFooObject
{
public string $foo;
}
final class SomeOtherFooObject
{
public string $foo;
}
final class SomeBarObject
{
public string $bar;
}
final class SomeFooAndBarObject
{
public string $foo;
public string $bar;
}
final class SomeBarAndFizObject
{
public string $bar;
public string $fiz;
}