Passed
Pull Request — main (#8)
by Anatoly
02:36
created

testHydratePropertyWithInvalidString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 7
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Sunrise\Hydrator\Tests;
6
7
use PHPUnit\Framework\TestCase;
8
use Sunrise\Hydrator\Exception;
9
use Sunrise\Hydrator\Hydrator;
10
use Sunrise\Hydrator\HydratorInterface;
11
use InvalidArgumentException;
12
13
class HydratorTest extends TestCase
14
{
15
    public function testContracts() : void
16
    {
17
        $hydrator = new Hydrator();
18
19
        $this->assertInstanceOf(HydratorInterface::class, $hydrator);
20
    }
21
22
    public function testHydrate() : void
23
    {
24
        $data = [];
25
        $data['statical'] = '813ea72c-6763-4596-a4d6-b478efed61bb';
26
        $data['nullable'] = null;
27
        $data['required'] = '9f5c273e-1dca-4c2d-ac81-7d6b03b169f4';
28
        $data['boolean'] = true;
29
        $data['integer'] = 42;
30
        $data['number'] = 123.45;
31
        $data['string'] = 'db7614d4-0a81-437b-b2cf-c536ad229c97';
32
        $data['array'] = ['foo' => 'bar'];
33
        $data['object'] = (object) ['foo' => 'bar'];
34
        $data['dateTime'] = '2038-01-19 03:14:08';
35
        $data['dateTimeImmutable'] = '2038-01-19 03:14:08';
36
        $data['bar'] = ['value' => '9898fb3b-ffb0-406c-bda6-b516423abde7'];
37
        $data['barCollection'][] = ['value' => 'd85c17b6-6e2c-4e2d-9eba-e1dd59b75fe3'];
38
        $data['barCollection'][] = ['value' => '5a8019aa-1c15-4c7c-8beb-1783c3d8996b'];
39
        $data['non-normalized'] = 'f76c4656-431a-4337-9ba9-5440611b37f1';
40
41
        $object = (new Hydrator)
42
            ->useAnnotations()
43
            ->useAnnotations() // CC
44
            ->hydrate(new Fixtures\Foo(), $data);
45
46
        $this->assertNotSame($data['statical'], $object::$statical);
47
        $this->assertSame($data['nullable'], $object->nullable);
48
        $this->assertSame($data['required'], $object->required);
49
        $this->assertSame($data['boolean'], $object->boolean);
50
        $this->assertSame($data['integer'], $object->integer);
51
        $this->assertSame($data['number'], $object->number);
52
        $this->assertSame($data['string'], $object->string);
53
        $this->assertSame($data['array'], $object->array);
54
        $this->assertSame($data['object'], $object->object);
55
        $this->assertSame($data['dateTime'], $object->dateTime->format('Y-m-d H:i:s'));
56
        $this->assertSame($data['dateTimeImmutable'], $object->dateTimeImmutable->format('Y-m-d H:i:s'));
57
        $this->assertSame($data['bar']['value'], $object->bar->value);
58
        $this->assertSame($data['barCollection'][0]['value'], $object->barCollection->get(0)->value);
59
        $this->assertSame($data['barCollection'][1]['value'], $object->barCollection->get(1)->value);
60
        $this->assertSame($data['non-normalized'], $object->normalized);
61
    }
62
63
    public function testHydrateUndefinedObject() : void
64
    {
65
        $this->expectException(InvalidArgumentException::class);
66
        $this->expectExceptionMessage('The method ' . Hydrator::class . '::hydrate() ' .
67
                                      'expects an object or name of an existing class.');
68
69
        (new Hydrator)->hydrate('Undefined', []);
70
    }
71
72
    public function testHydrateUninitializableObject() : void
73
    {
74
        $this->expectException(InvalidArgumentException::class);
75
        $this->expectExceptionMessage('The object ' . Fixtures\UninitializableObject::class . ' ' .
76
                                      'cannot be hydrated because its constructor has required parameters.');
77
78
        (new Hydrator)->hydrate(Fixtures\UninitializableObject::class, []);
79
    }
80
81
    public function testHydrateWithJson() : void
82
    {
83
        $json = '{"value": "4c1e3453-7b76-4d5d-b4b8-bc6b0afcd835"}';
84
85
        $object = (new Hydrator)->useAnnotations()->hydrateWithJson(Fixtures\Bar::class, $json);
86
87
        $this->assertSame($object->value, '4c1e3453-7b76-4d5d-b4b8-bc6b0afcd835');
88
    }
89
90
    public function testHydrateWithInvalidJson() : void
91
    {
92
        $this->expectException(InvalidArgumentException::class);
93
        $this->expectExceptionMessage('Unable to decode JSON: Syntax error');
94
95
        (new Hydrator)->useAnnotations()->hydrateWithJson(Fixtures\Bar::class, '!');
96
    }
97
98
    public function testUntypedProperty() : void
99
    {
100
        $this->expectException(Exception\UntypedPropertyException::class);
101
        $this->expectExceptionMessage('The ObjectWithUntypedProperty.value property is not typed.');
102
103
        (new Hydrator)->hydrate(Fixtures\ObjectWithUntypedProperty::class, []);
104
    }
105
106
    public function testUnsupportedPropertyType() : void
107
    {
108
        $this->expectException(Exception\UnsupportedPropertyTypeException::class);
109
        $this->expectExceptionMessage('The ObjectWithUnsupportedPropertyType.value property ' .
110
                                      'contains an unsupported type iterable.');
111
112
        (new Hydrator)->hydrate(Fixtures\ObjectWithUnsupportedPropertyType::class, [
113
            'value' => 'b25c08e8-4771-42c0-b01b-fe7fd3689602',
114
        ]);
115
    }
116
117
    public function testUnionPropertyType() : void
118
    {
119
        $this->expectException(Exception\UnsupportedPropertyTypeException::class);
120
        $this->expectExceptionMessage('The ObjectWithUnionPropertyType.value property ' .
121
                                      'contains an union type that is not supported.');
122
123
        (new Hydrator)->hydrate(Fixtures\ObjectWithUnionPropertyType::class, []);
124
    }
125
126
    public function testRequiredProperty() : void
127
    {
128
        $this->expectException(Exception\MissingRequiredValueException::class);
129
        $this->expectExceptionMessage('The ObjectWithRequiredProperty.value property ' .
130
                                      'is required.');
131
132
        try {
133
            (new Hydrator)->hydrate(Fixtures\ObjectWithRequiredProperty::class, []);
134
        } catch (Exception\MissingRequiredValueException $e) {
135
            $this->assertSame('value', $e->getProperty()->getName());
136
137
            throw $e;
138
        }
139
    }
140
141
    public function testAnnotatedProperty() : void
142
    {
143
        $data = [
144
            'non-normalized-value' => '87019bbd-643b-45b8-94f8-0abd56be9851',
145
        ];
146
147
        $object = (new Hydrator)->useAnnotations()->hydrate(Fixtures\ObjectWithAnnotatedProperty::class, $data);
148
149
        $this->assertSame($object->value, '87019bbd-643b-45b8-94f8-0abd56be9851');
150
    }
151
152
    public function testUnnullableProperty() : void
153
    {
154
        $this->expectException(Exception\InvalidValueException::class);
155
        $this->expectExceptionMessage('The Bar.value property cannot accept null.');
156
157
        (new Hydrator)->hydrate(Fixtures\Bar::class, [
158
            'value' => null,
159
        ]);
160
    }
161
162
    public function testHydratePropertyWithStringBooleanValue() : void
163
    {
164
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithBooleanProperty::class, [
165
            'value' => 'yes',
166
        ]);
167
168
        $this->assertSame(true, $object->value);
169
    }
170
171
    public function testHydratePropertyWithStringIntegerNumber() : void
172
    {
173
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithIntegerProperty::class, [
174
            'value' => '42',
175
        ]);
176
177
        $this->assertSame(42, $object->value);
178
    }
179
180
    public function testHydratePropertyWithStringableNumber() : void
181
    {
182
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithNumberProperty::class, [
183
            'value' => '123.45',
184
        ]);
185
186
        $this->assertSame(123.45, $object->value);
187
    }
188
189
    public function testHydratePropertyWithIntegerTimestamp() : void
190
    {
191
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithTimestampProperty::class, [
192
            'value' => 1262304000,
193
        ]);
194
195
        $this->assertSame('2010-01-01', $object->value->format('Y-m-d'));
196
    }
197
198
    public function testHydratePropertyWithStringIntegerTimestamp() : void
199
    {
200
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithTimestampProperty::class, [
201
            'value' => '1262304000',
202
        ]);
203
204
        $this->assertSame('2010-01-01', $object->value->format('Y-m-d'));
205
    }
206
207
    public function testHydratePropertyWithStringDateTime() : void
208
    {
209
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithTimestampProperty::class, [
210
            'value' => '2010-01-01',
211
        ]);
212
213
        $this->assertSame('2010-01-01', $object->value->format('Y-m-d'));
214
    }
215
216
    public function testHydratePropertyWithInvalidBooleanValue() : void
217
    {
218
        $this->expectException(Exception\InvalidValueException::class);
219
        $this->expectExceptionMessage('The ObjectWithBooleanProperty.value property accepts a boolean value only.');
220
221
        (new Hydrator)->hydrate(Fixtures\ObjectWithBooleanProperty::class, [
222
            'value' => [],
223
        ]);
224
    }
225
226
    public function testHydratePropertyWithInvalidIntegerNumber() : void
227
    {
228
        $this->expectException(Exception\InvalidValueException::class);
229
        $this->expectExceptionMessage('The ObjectWithIntegerProperty.value property accepts an integer number only.');
230
231
        (new Hydrator)->hydrate(Fixtures\ObjectWithIntegerProperty::class, [
232
            'value' => [],
233
        ]);
234
    }
235
236
    public function testHydratePropertyWithInvalidNumber() : void
237
    {
238
        $this->expectException(Exception\InvalidValueException::class);
239
        $this->expectExceptionMessage('The ObjectWithNumberProperty.value property accepts a number only.');
240
241
        (new Hydrator)->hydrate(Fixtures\ObjectWithNumberProperty::class, [
242
            'value' => [],
243
        ]);
244
    }
245
246
    public function testHydratePropertyWithInvalidString() : void
247
    {
248
        $this->expectException(Exception\InvalidValueException::class);
249
        $this->expectExceptionMessage('The ObjectWithStringProperty.value property accepts a string only.');
250
251
        (new Hydrator)->hydrate(Fixtures\ObjectWithStringProperty::class, [
252
            'value' => [],
253
        ]);
254
    }
255
256
    public function testHydratePropertyWithInvalidArray() : void
257
    {
258
        $this->expectException(Exception\InvalidValueException::class);
259
        $this->expectExceptionMessage('The ObjectWithArrayProperty.value property accepts an array only.');
260
261
        (new Hydrator)->hydrate(Fixtures\ObjectWithArrayProperty::class, [
262
            'value' => 0,
263
        ]);
264
    }
265
266
    public function testHydratePropertyWithInvalidObject() : void
267
    {
268
        $this->expectException(Exception\InvalidValueException::class);
269
        $this->expectExceptionMessage('The ObjectWithObjectProperty.value property accepts an object only.');
270
271
        (new Hydrator)->hydrate(Fixtures\ObjectWithObjectProperty::class, [
272
            'value' => 0,
273
        ]);
274
    }
275
276
    public function testHydratePropertyWithInvalidTimestamp() : void
277
    {
278
        $this->expectException(Exception\InvalidValueException::class);
279
        $this->expectExceptionMessage('The ObjectWithTimestampProperty.value property ' .
280
                                      'accepts a valid date-time string or a timestamp only.');
281
282
        (new Hydrator)->hydrate(Fixtures\ObjectWithTimestampProperty::class, [
283
            'value' => [],
284
        ]);
285
    }
286
287
    public function testHydratePropertyWithInvalidAssociation() : void
288
    {
289
        $this->expectException(Exception\InvalidValueException::class);
290
        $this->expectExceptionMessage('The ObjectWithAssociation.value property accepts an array only.');
291
292
        (new Hydrator)->hydrate(Fixtures\ObjectWithAssociation::class, [
293
            'value' => 0,
294
        ]);
295
    }
296
297
    public function testHydratePropertyWithInvalidAssociations() : void
298
    {
299
        $this->expectException(Exception\InvalidValueException::class);
300
        $this->expectExceptionMessage('The ObjectWithAssociations.value property accepts an array only.');
301
302
        (new Hydrator)->hydrate(Fixtures\ObjectWithAssociations::class, [
303
            'value' => 0,
304
        ]);
305
    }
306
307
    public function testHydratePropertyWithInvalidOneOfAssociations() : void
308
    {
309
        $this->expectException(Exception\InvalidValueException::class);
310
        $this->expectExceptionMessage('The ObjectWithAssociations.value property accepts an array with arrays only.');
311
312
        (new Hydrator)->hydrate(Fixtures\ObjectWithAssociations::class, [
313
            'value' => [0],
314
        ]);
315
    }
316
}
317