Test Failed
Pull Request — main (#19)
by Anatoly
04:48 queued 02:08
created

testHydratePropertyWithStringIntegerTimestamp()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 7
rs 10
cc 1
nc 1
nop 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A HydratorTest::testHydrateWithJson() 0 5 1
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 testInvalidObject() : void
23
    {
24
        $this->expectException(InvalidArgumentException::class);
25
        $this->expectExceptionMessage('The ' . Hydrator::class . '::hydrate() method ' .
26
                                      'expects an object or name of an existing class.');
27
28
        (new Hydrator)->hydrate('Undefined', []);
29
    }
30
31
    public function testUninitializableObject() : void
32
    {
33
        $this->expectException(InvalidArgumentException::class);
34
        $this->expectExceptionMessage('The ' . Fixtures\UninitializableObject::class . ' object ' .
35
                                      'cannot be hydrated because its constructor has required parameters.');
36
37
        (new Hydrator)->hydrate(Fixtures\UninitializableObject::class, []);
38
    }
39
40
    public function testInvalidData() : void
41
    {
42
        $this->expectException(InvalidArgumentException::class);
43
        $this->expectExceptionMessage('The ' . Hydrator::class . '::hydrate(data) parameter ' .
44
                                      'expects an associative array or object.');
45
46
        (new Hydrator)->hydrate(Fixtures\ObjectWithString::class, null);
47
    }
48
49
    public function testInvalidJson() : void
50
    {
51
        $this->expectException(InvalidArgumentException::class);
52
        $this->expectExceptionMessage('Unable to decode JSON: Syntax error');
53
54
        (new Hydrator)->hydrateWithJson(Fixtures\ObjectWithString::class, '!');
55
    }
56
57
    public function testIgnoreStaticalProperty() : void
58
    {
59
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithStaticalProperty::class, ['value' => 'foo']);
60
61
        $this->assertNotSame('foo', $object::$value);
62
    }
63
64
    public function testUntypedProperty() : void
65
    {
66
        $this->expectException(Exception\UntypedPropertyException::class);
67
        $this->expectExceptionMessage('The ObjectWithUntypedProperty.value property ' .
68
                                      'is not typed.');
69
70
        (new Hydrator)->hydrate(Fixtures\ObjectWithUntypedProperty::class, []);
71
    }
72
73
    public function testUnionPropertyType() : void
74
    {
75
        if (\PHP_MAJOR_VERSION < 8) {
76
            $this->markTestSkipped('php >= 8 is required.');
77
        }
78
79
        $this->expectException(Exception\UnsupportedPropertyTypeException::class);
80
        $this->expectExceptionMessage('The ObjectWithIntOrFloat.value property ' .
81
                                      'contains an union type that is not supported.');
82
83
        (new Hydrator)->hydrate(Fixtures\ObjectWithIntOrFloat::class, []);
84
    }
85
86
    public function testHydrateAnnotatedProperty() : void
87
    {
88
        $object = (new Hydrator)
89
            ->useAnnotations()
90
            ->hydrate(Fixtures\ObjectWithAnnotatedAlias::class, ['non-normalized-value' => 'foo']);
91
92
        $this->assertSame('foo', $object->value);
93
    }
94
95
    public function testHydrateAnnotatedPropertyUsingNormalizedKey() : void
96
    {
97
        $object = (new Hydrator)
98
            ->useAnnotations()
99
            ->hydrate(Fixtures\ObjectWithAnnotatedAlias::class, ['value' => 'foo']);
100
101
        $this->assertSame('foo', $object->value);
102
    }
103
104
    public function testHydrateAnnotatedPropertyWhenDisabledAliasSupport() : void
105
    {
106
        $this->expectException(Exception\MissingRequiredValueException::class);
107
        $this->expectExceptionMessage('The ObjectWithAnnotatedAlias.value property ' .
108
                                      'is required.');
109
110
        (new Hydrator)
111
            ->useAnnotations()
112
            ->aliasSupport(false)
113
            ->hydrate(Fixtures\ObjectWithAnnotatedAlias::class, ['non-normalized-value' => 'foo']);
114
    }
115
116
    public function testHydrateAnnotatedPropertyWhenDisabledAnnotations() : void
117
    {
118
        $this->expectException(Exception\MissingRequiredValueException::class);
119
        $this->expectExceptionMessage('The ObjectWithAnnotatedAlias.value property ' .
120
                                      'is required.');
121
122
        (new Hydrator)->hydrate(Fixtures\ObjectWithAnnotatedAlias::class, ['non-normalized-value' => 'foo']);
123
    }
124
125
    public function testHydrateAttributedProperty() : void
126
    {
127
        if (\PHP_MAJOR_VERSION < 8) {
128
            $this->markTestSkipped('php >= 8 is required.');
129
        }
130
131
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithAttributedAlias::class, ['non-normalized-value' => 'foo']);
132
133
        $this->assertSame('foo', $object->value);
134
    }
135
136
    public function testHydrateAttributedPropertyUsingNormalizedKey() : void
137
    {
138
        if (\PHP_MAJOR_VERSION < 8) {
139
            $this->markTestSkipped('php >= 8 is required.');
140
        }
141
142
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithAttributedAlias::class, ['value' => 'foo']);
143
144
        $this->assertSame('foo', $object->value);
145
    }
146
147
    public function testHydrateAttributedPropertyWhenDisabledAliasSupport() : void
148
    {
149
        if (\PHP_MAJOR_VERSION < 8) {
150
            $this->markTestSkipped('php >= 8 is required.');
151
        }
152
153
        $this->expectException(Exception\MissingRequiredValueException::class);
154
        $this->expectExceptionMessage('The ObjectWithAttributedAlias.value property ' .
155
                                      'is required.');
156
157
        (new Hydrator)
158
            ->aliasSupport(false)
159
            ->hydrate(Fixtures\ObjectWithAttributedAlias::class, ['non-normalized-value' => 'foo']);
160
    }
161
162
    public function testRequiredProperty() : void
163
    {
164
        $this->expectException(Exception\MissingRequiredValueException::class);
165
        $this->expectExceptionMessage('The ObjectWithString.value property ' .
166
                                      'is required.');
167
168
        (new Hydrator)->hydrate(Fixtures\ObjectWithString::class, []);
169
    }
170
171
    public function testUnsupportedPropertyType() : void
172
    {
173
        $this->expectException(Exception\UnsupportedPropertyTypeException::class);
174
        $this->expectExceptionMessage('The ObjectWithUnsupportedType.value property ' .
175
                                      'contains an unsupported type iterable.');
176
177
        (new Hydrator)->hydrate(Fixtures\ObjectWithUnsupportedType::class, ['value' => false]);
178
    }
179
180
    public function testOptionalProperty() : void
181
    {
182
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithOptionalString::class, []);
183
184
        $this->assertSame('75c4c2a0-e352-4eda-b2ed-b7f713ffb9ff', $object->value);
185
    }
186
187
    public function testHydrateObject() : void
188
    {
189
        $source = new Fixtures\ObjectWithString();
190
191
        // should return the source object...
192
        $object = (new Hydrator)->hydrate($source, ['value' => 'foo']);
193
194
        $this->assertSame($source, $object);
195
        $this->assertSame('foo', $source->value);
196
    }
197
198
    public function testHydrateUsingDataObject() : void
199
    {
200
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithString::class, (object) ['value' => 'foo']);
201
202
        $this->assertSame('foo', $object->value);
203
    }
204
205
    public function testHydrateWithJson() : void
206
    {
207
        $object = (new Hydrator)->hydrateWithJson(Fixtures\ObjectWithString::class, '{"value": "foo"}');
208
209
        $this->assertSame('foo', $object->value);
210
    }
211
212
    public function testConvertEmptyStringToNullForNonStringType() : void
213
    {
214
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithNullableInt::class, ['value' => '']);
215
216
        $this->assertNull($object->value);
217
    }
218
219
    public function testHydrateNullablePropertyWithNull() : void
220
    {
221
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithNullableString::class, ['value' => null]);
222
223
        $this->assertNull($object->value);
224
    }
225
226
    public function testHydrateUnnullablePropertyWithNull() : void
227
    {
228
        $this->expectException(Exception\InvalidValueException::class);
229
        $this->expectExceptionMessage('The ObjectWithString.value property ' .
230
                                      'cannot accept null.');
231
232
        (new Hydrator)->hydrate(Fixtures\ObjectWithString::class, ['value' => null]);
233
    }
234
235
    /**
236
     * @dataProvider booleanValueProvider
237
     */
238
    public function testHydrateBooleanProperty($value, $expected) : void
239
    {
240
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithBool::class, ['value' => $value]);
241
242
        $this->assertSame($expected, $object->value);
243
    }
244
245
    public function booleanValueProvider() : array
246
    {
247
        return [
248
            [true, true],
249
            [1, true],
250
            ['1', true],
251
            ['on', true],
252
            ['yes', true],
253
            [false, false],
254
            [0, false],
255
            ['0', false],
256
            ['off', false],
257
            ['no', false],
258
        ];
259
    }
260
261
    public function testHydrateBooleanPropertyWithInvalidValue() : void
262
    {
263
        $this->expectException(Exception\InvalidValueException::class);
264
        $this->expectExceptionMessage('The ObjectWithBool.value property expects a boolean.');
265
266
        (new Hydrator)->hydrate(Fixtures\ObjectWithBool::class, ['value' => 'foo']);
267
    }
268
269
    /**
270
     * @dataProvider integerValueProvider
271
     */
272
    public function testHydrateIntegerProperty($value, $expected) : void
273
    {
274
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithInt::class, ['value' => $value]);
275
276
        $this->assertSame($expected, $object->value);
277
    }
278
279
    public function integerValueProvider() : array
280
    {
281
        return [
282
            [42, 42],
283
            ['42', 42],
284
        ];
285
    }
286
287
    public function testHydrateIntegerPropertyWithInvalidValue() : void
288
    {
289
        $this->expectException(Exception\InvalidValueException::class);
290
        $this->expectExceptionMessage('The ObjectWithInt.value property expects an integer.');
291
292
        (new Hydrator)->hydrate(Fixtures\ObjectWithInt::class, ['value' => 'foo']);
293
    }
294
295
    /**
296
     * @dataProvider numberValueProvider
297
     */
298
    public function testHydrateNumberProperty($value, $expected) : void
299
    {
300
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithFloat::class, ['value' => $value]);
301
302
        $this->assertSame($expected, $object->value);
303
    }
304
305
    public function numberValueProvider() : array
306
    {
307
        return [
308
            [42, 42.0],
309
            ['42', 42.0],
310
            [42.0, 42.0],
311
            ['42.0', 42.0],
312
        ];
313
    }
314
315
    public function testHydrateNumberPropertyWithInvalidValue() : void
316
    {
317
        $this->expectException(Exception\InvalidValueException::class);
318
        $this->expectExceptionMessage('The ObjectWithFloat.value property expects a number.');
319
320
        (new Hydrator)->hydrate(Fixtures\ObjectWithFloat::class, ['value' => 'foo']);
321
    }
322
323
    public function testHydrateStringableProperty() : void
324
    {
325
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithString::class, ['value' => 'foo']);
326
327
        $this->assertSame('foo', $object->value);
328
    }
329
330
    public function testHydrateStringablePropertyWithEmptyString() : void
331
    {
332
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithString::class, ['value' => '']);
333
334
        $this->assertSame('', $object->value);
335
    }
336
337
    public function testHydrateStringablePropertyWithInvalidValue() : void
338
    {
339
        $this->expectException(Exception\InvalidValueException::class);
340
        $this->expectExceptionMessage('The ObjectWithString.value property expects a string.');
341
342
        (new Hydrator)->hydrate(Fixtures\ObjectWithString::class, ['value' => 42]);
343
    }
344
345
    public function testHydrateArrayableProperty() : void
346
    {
347
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithArray::class, ['value' => ['foo']]);
348
349
        $this->assertSame(['foo'], $object->value);
350
    }
351
352
    public function testHydrateArrayablePropertyWithInvalidValue() : void
353
    {
354
        $this->expectException(Exception\InvalidValueException::class);
355
        $this->expectExceptionMessage('The ObjectWithArray.value property expects an array.');
356
357
        (new Hydrator)->hydrate(Fixtures\ObjectWithArray::class, ['value' => 'foo']);
358
    }
359
360
    public function testHydrateObjectableProperty() : void
361
    {
362
        $value = (object) ['value' => 'foo'];
363
364
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithObject::class, ['value' => $value]);
365
366
        $this->assertSame($value, $object->value);
367
    }
368
369
    public function testHydrateObjectablePropertyWithInvalidValue() : void
370
    {
371
        $this->expectException(Exception\InvalidValueException::class);
372
        $this->expectExceptionMessage('The ObjectWithObject.value property expects an object.');
373
374
        (new Hydrator)->hydrate(Fixtures\ObjectWithObject::class, ['value' => 'foo']);
375
    }
376
377
    /**
378
     * @dataProvider timestampValueProvider
379
     */
380
    public function testHydrateDateTimeProperty($value, $expected) : void
381
    {
382
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithDateTime::class, ['value' => $value]);
383
384
        $this->assertSame($expected, $object->value->format('Y-m-d'));
385
    }
386
387
    /**
388
     * @dataProvider timestampValueProvider
389
     */
390
    public function testHydrateDateTimeImmutableProperty($value, $expected) : void
391
    {
392
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithDateTimeImmutable::class, ['value' => $value]);
393
394
        $this->assertSame($expected, $object->value->format('Y-m-d'));
395
    }
396
397
    public function timestampValueProvider() : array
398
    {
399
        return [
400
            [1262304000, '2010-01-01'],
401
            ['1262304000', '2010-01-01'],
402
            ['2010-01-01', '2010-01-01'],
403
        ];
404
    }
405
406
    public function testHydrateDateTimePropertyWithInvalidValue() : void
407
    {
408
        $this->expectException(Exception\InvalidValueException::class);
409
        $this->expectExceptionMessage('The ObjectWithDateTime.value property ' .
410
                                      'expects a valid date-time string or timestamp.');
411
412
        (new Hydrator)->hydrate(Fixtures\ObjectWithDateTime::class, ['value' => 'foo']);
413
    }
414
415
    public function testHydrateDateTimeImmutablePropertyWithInvalidValue() : void
416
    {
417
        $this->expectException(Exception\InvalidValueException::class);
418
        $this->expectExceptionMessage('The ObjectWithDateTimeImmutable.value property ' .
419
                                      'expects a valid date-time string or timestamp.');
420
421
        (new Hydrator)->hydrate(Fixtures\ObjectWithDateTimeImmutable::class, ['value' => 'foo']);
422
    }
423
424
    public function testHydrateDateIntervalProperty() : void
425
    {
426
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithDateInterval::class, ['value' => 'P33Y']);
427
428
        $this->assertSame(33, $object->value->y);
429
    }
430
431
    public function testHydrateDateIntervalPropertyWithInvalidValue() : void
432
    {
433
        $this->expectException(Exception\InvalidValueException::class);
434
        $this->expectExceptionMessage('The ObjectWithDateInterval.value property ' .
435
                                      'expects a string.');
436
437
        (new Hydrator)->hydrate(Fixtures\ObjectWithDateInterval::class, ['value' => 42]);
438
    }
439
440
    public function testHydrateDateIntervalPropertyWithInvalidFormat() : void
441
    {
442
        $this->expectException(Exception\InvalidValueException::class);
443
        $this->expectExceptionMessage('The ObjectWithDateInterval.value property ' .
444
                                      'expects a valid date-interval string based on ISO 8601.');
445
446
        (new Hydrator)->hydrate(Fixtures\ObjectWithDateInterval::class, ['value' => 'foo']);
447
    }
448
449
    /**
450
     * @dataProvider stringableEnumValueProvider
451
     */
452
    public function testHydrateStringableEnumProperty($value, $expected) : void
453
    {
454
        if (\PHP_VERSION_ID < 80100) {
455
            $this->markTestSkipped('php >= 8.1 is required.');
456
        }
457
458
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithStringableEnum::class, ['value' => $value]);
459
460
        $this->assertSame($expected, $object->value);
461
    }
462
463
    public function stringableEnumValueProvider() : array
464
    {
465
        return [
466
            ['c1200a7e-136e-4a11-9bc3-cc937046e90f', Fixtures\StringableEnum::foo],
467
            ['a2b29b37-1c5a-4b36-9981-097ddd25c740', Fixtures\StringableEnum::bar],
468
            ['c1ea3762-9827-4c0c-808b-53be3febae6d', Fixtures\StringableEnum::baz],
469
        ];
470
    }
471
472
    public function testHydrateStringableEnumPropertyWithInvalidValue() : void
473
    {
474
        if (\PHP_VERSION_ID < 80100) {
475
            $this->markTestSkipped('php >= 8.1 is required.');
476
        }
477
478
        $this->expectException(Exception\InvalidValueException::class);
479
        $this->expectExceptionMessage('The ObjectWithStringableEnum.value property ' .
480
                                      'expects the following type: string.');
481
482
        (new Hydrator)->hydrate(Fixtures\ObjectWithStringableEnum::class, ['value' => 42]);
483
    }
484
485
    public function testHydrateStringableEnumPropertyWithInvalidUnknownCase() : void
486
    {
487
        if (\PHP_VERSION_ID < 80100) {
488
            $this->markTestSkipped('php >= 8.1 is required.');
489
        }
490
491
        $this->expectException(Exception\InvalidValueException::class);
492
        $this->expectExceptionMessage('The ObjectWithStringableEnum.value property ' .
493
                                      'expects one of the following values: ' .
494
                                      \implode(', ', Fixtures\StringableEnum::values()) . '.');
495
496
        (new Hydrator)->hydrate(Fixtures\ObjectWithStringableEnum::class, ['value' => 'foo']);
497
    }
498
499
    /**
500
     * @dataProvider numerableEnumValueProvider
501
     */
502
    public function testHydrateNumerableEnumProperty($value, $expected) : void
503
    {
504
        if (\PHP_VERSION_ID < 80100) {
505
            $this->markTestSkipped('php >= 8.1 is required.');
506
        }
507
508
        $object = (new Hydrator)->hydrate(Fixtures\ObjectWithNumerableEnum::class, ['value' => $value]);
509
510
        $this->assertSame($expected, $object->value);
511
    }
512
513
    public function numerableEnumValueProvider() : array
514
    {
515
        return [
516
            [1, Fixtures\NumerableEnum::foo],
517
            [2, Fixtures\NumerableEnum::bar],
518
            [3, Fixtures\NumerableEnum::baz],
519
520
            // should convert strings to integers...
521
            ['1', Fixtures\NumerableEnum::foo],
522
            ['2', Fixtures\NumerableEnum::bar],
523
            ['3', Fixtures\NumerableEnum::baz],
524
        ];
525
    }
526
527
    public function testHydrateNumerableEnumPropertyWithInvalidValue() : void
528
    {
529
        if (\PHP_VERSION_ID < 80100) {
530
            $this->markTestSkipped('php >= 8.1 is required.');
531
        }
532
533
        $this->expectException(Exception\InvalidValueException::class);
534
        $this->expectExceptionMessage('The ObjectWithNumerableEnum.value property ' .
535
                                      'expects the following type: int.');
536
537
        (new Hydrator)->hydrate(Fixtures\ObjectWithNumerableEnum::class, ['value' => 'foo']);
538
    }
539
540
    public function testHydrateNumerableEnumPropertyWithInvalidUnknownCase() : void
541
    {
542
        if (\PHP_VERSION_ID < 80100) {
543
            $this->markTestSkipped('php >= 8.1 is required.');
544
        }
545
546
        $this->expectException(Exception\InvalidValueException::class);
547
        $this->expectExceptionMessage('The ObjectWithNumerableEnum.value property ' .
548
                                      'expects one of the following values: ' .
549
                                      \implode(', ', Fixtures\NumerableEnum::values()) . '.');
550
551
        (new Hydrator)->hydrate(Fixtures\ObjectWithNumerableEnum::class, ['value' => 42]);
552
    }
553
554
    public function testHydrateAssociatedProperty() : void
555
    {
556
        $o = (new Hydrator)->hydrate(Fixtures\ObjectWithAssociation::class, ['value' => ['value' => 'foo']]);
557
558
        $this->assertSame('foo', $o->value->value);
559
    }
560
561
    public function testHydrateAssociatedPropertyUsingDataObject() : void
562
    {
563
        $o = (new Hydrator)->hydrate(Fixtures\ObjectWithAssociation::class, ['value' => (object) ['value' => 'foo']]);
564
565
        $this->assertSame('foo', $o->value->value);
566
    }
567
568
    public function testHydrateAssociatedPropertyWithInvalidData() : void
569
    {
570
        $this->expectException(Exception\InvalidValueException::class);
571
        $this->expectExceptionMessage('The ObjectWithAssociation.value property ' .
572
                                      'expects an associative array or object.');
573
574
        (new Hydrator)->hydrate(Fixtures\ObjectWithAssociation::class, ['value' => 'foo']);
575
    }
576
577
    public function testHydrateAssociationCollectionProperty() : void
578
    {
579
        $o = (new Hydrator)->hydrate(Fixtures\ObjectWithAssociations::class, ['value' => [
580
            'foo' => ['value' => 'foo'],
581
            'bar' => ['value' => 'bar'],
582
        ]]);
583
584
        $this->assertTrue($o->value->has('foo'));
585
        $this->assertSame('foo', $o->value->get('foo')->value);
586
587
        $this->assertTrue($o->value->has('bar'));
588
        $this->assertSame('bar', $o->value->get('bar')->value);
589
    }
590
591
    public function testHydrateAssociationCollectionPropertyUsingDataObject() : void
592
    {
593
        $o = (new Hydrator)->hydrate(Fixtures\ObjectWithAssociations::class, ['value' => (object) [
594
            'foo' => (object) ['value' => 'foo'],
595
            'bar' => (object) ['value' => 'bar'],
596
        ]]);
597
598
        $this->assertTrue($o->value->has('foo'));
599
        $this->assertSame('foo', $o->value->get('foo')->value);
600
601
        $this->assertTrue($o->value->has('bar'));
602
        $this->assertSame('bar', $o->value->get('bar')->value);
603
    }
604
605
    public function testHydrateAssociationCollectionPropertyWithInvalidData() : void
606
    {
607
        $this->expectException(Exception\InvalidValueException::class);
608
        $this->expectExceptionMessage('The ObjectWithAssociations.value property ' .
609
                                      'expects an associative array or object.');
610
611
        (new Hydrator)->hydrate(Fixtures\ObjectWithAssociations::class, ['value' => 'foo']);
612
    }
613
614
    public function testHydrateAssociationCollectionPropertyWithInvalidChild() : void
615
    {
616
        $this->expectException(Exception\InvalidValueException::class);
617
        $this->expectExceptionMessage('The ObjectWithAssociations.value[0] property ' .
618
                                      'expects an associative array or object.');
619
620
        (new Hydrator)->hydrate(Fixtures\ObjectWithAssociations::class, ['value' => ['foo']]);
621
    }
622
623
    public function testInvalidValueExceptionProperty() : void
624
    {
625
        try {
626
            (new Hydrator)->hydrate(Fixtures\ObjectWithString::class, ['value' => 42]);
627
        } catch (Exception\InvalidValueException $e) {
628
            $this->assertSame('value', $e->getProperty()->getName());
629
            $this->assertSame('ObjectWithString.value', $e->getPropertyPath());
630
        }
631
    }
632
633
    public function testHydrateProductWithJsonAsArray() : void
634
    {
635
        if (\PHP_VERSION_ID < 80100) {
636
            $this->markTestSkipped('php >= 8.1 is required.');
637
        }
638
639
        $json = <<<JSON
640
        {
641
            "name": "ac7ce13e-9b2e-4b09-ae7a-973769ea43df",
642
            "category": {
643
                "name": "a0127d1b-28b6-40a9-9a62-cfb2e2b44abd"
644
            },
645
            "tags": [
646
                {
647
                    "name": "a9878435-506c-4757-92b0-69ea2bd15bc3"
648
                },
649
                {
650
                    "name": "73dc4db1-7965-41b6-88cb-4dc9df6fb3ea"
651
                }
652
            ],
653
            "status": 2
654
        }
655
        JSON;
656
657
        $product = (new Hydrator)->hydrateWithJson(Fixtures\Store\Product::class, $json);
658
659
        $this->assertSame('ac7ce13e-9b2e-4b09-ae7a-973769ea43df', $product->name);
660
        $this->assertSame('a0127d1b-28b6-40a9-9a62-cfb2e2b44abd', $product->category->name);
661
        $this->assertSame('a9878435-506c-4757-92b0-69ea2bd15bc3', $product->tags->get(0)->name);
662
        $this->assertSame('73dc4db1-7965-41b6-88cb-4dc9df6fb3ea', $product->tags->get(1)->name);
663
        $this->assertSame(2, $product->status->value);
664
    }
665
666
    public function testHydrateProductWithJsonAsObject() : void
667
    {
668
        if (\PHP_VERSION_ID < 80100) {
669
            $this->markTestSkipped('php >= 8.1 is required.');
670
        }
671
672
        $json = <<<JSON
673
        {
674
            "name": "0f61ac0e-f732-4088-8082-cc396e7dcb80",
675
            "category": {
676
                "name": "d342d030-3c0c-431e-be54-2e933b722b7c"
677
            },
678
            "tags": [
679
                {
680
                    "name": "3635627a-e348-4ca4-8e62-4e5cd78043d2"
681
                },
682
                {
683
                    "name": "dccd816f-bb28-41f3-b1a9-ddaff1fdec5b"
684
                }
685
            ],
686
            "status": 2
687
        }
688
        JSON;
689
690
        $product = (new Hydrator)->hydrateWithJson(Fixtures\Store\Product::class, $json, 0);
691
692
        $this->assertSame('0f61ac0e-f732-4088-8082-cc396e7dcb80', $product->name);
693
        $this->assertSame('d342d030-3c0c-431e-be54-2e933b722b7c', $product->category->name);
694
        $this->assertSame('3635627a-e348-4ca4-8e62-4e5cd78043d2', $product->tags->get(0)->name);
695
        $this->assertSame('dccd816f-bb28-41f3-b1a9-ddaff1fdec5b', $product->tags->get(1)->name);
696
        $this->assertSame(2, $product->status->value);
697
    }
698
}
699