Passed
Pull Request — main (#6)
by Anatoly
11:48
created

HydratorTest::testInvalidSyntaxJson()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 6
rs 10
1
<?php declare(strict_types=1);
2
3
namespace Sunrise\Hydrator\Tests;
4
5
/**
6
 * Import classes
7
 */
8
use PHPUnit\Framework\TestCase;
9
use Sunrise\Hydrator\Exception;
10
use Sunrise\Hydrator\Hydrator;
11
use Sunrise\Hydrator\HydratorInterface;
12
use DateTimeInterface;
13
14
/**
15
 * HydratorTest
16
 */
17
class HydratorTest extends TestCase
18
{
19
20
    /**
21
     * @return void
22
     */
23
    public function testContracts() : void
24
    {
25
        $hydrator = new Hydrator();
26
27
        $this->assertInstanceOf(HydratorInterface::class, $hydrator);
28
    }
29
30
    /**
31
     * @return void
32
     */
33
    public function testHydrate() : void
34
    {
35
        $data = [
36
            'static' => 'foo',
37
            'nullable' => null,
38
            'bool' => false,
39
            'int' => 0,
40
            'float' => 0.0,
41
            'string' => 'foo',
42
            'array' => [
43
                'foo',
44
                'bar',
45
                100,
46
            ],
47
            'dateTime' => '2005-08-15T15:52:01.000+00:00',
48
            'barDto' => [
49
                'value' => 'foo',
50
            ],
51
            'barDtoCollection' => [
52
                [
53
                    'value' => 'foo',
54
                ],
55
                [
56
                    'value' => 'bar',
57
                ],
58
            ],
59
            'simpleArray' => [
60
                'foo',
61
                'bar',
62
            ],
63
            'alias' => 'value',
64
        ];
65
66
        $object = new Fixture\FooDto();
67
        $hydrator = new Hydrator();
68
        $hydrator->hydrate($object, $data);
69
70
        $this->assertSame('default value', $object::$static);
71
        $this->assertSame('default value', $object->valuable);
72
        $this->assertSame($data['nullable'], $object->nullable);
73
        $this->assertSame($data['bool'], $object->bool);
74
        $this->assertSame($data['int'], $object->int);
75
        $this->assertSame($data['float'], $object->float);
76
        $this->assertSame($data['string'], $object->string);
77
        $this->assertSame($data['array'], $object->array->getArrayCopy());
78
        $this->assertSame($data['dateTime'], $object->dateTime->format(DateTimeInterface::RFC3339_EXTENDED));
79
        $this->assertSame($data['barDto']['value'], $object->barDto->value);
80
        $this->assertSame($data['barDtoCollection'][0]['value'], $object->barDtoCollection->getIterator()[0]->value);
81
        $this->assertSame($data['barDtoCollection'][1]['value'], $object->barDtoCollection->getIterator()[1]->value);
82
        $this->assertSame($data['simpleArray'], $object->simpleArray);
83
        $this->assertSame($data['alias'], $object->hidden);
84
    }
85
86
    /**
87
     * @return void
88
     */
89
    public function testJson() : void
90
    {
91
        $json = '{"foo":"foo:value","bar":"bar:value"}';
92
93
        $object = (new Hydrator)->hydrate(new Fixture\TestJsonDto(), ['json' => $json]);
94
95
        $this->assertSame('foo:value', $object->json->foo);
96
        $this->assertSame('bar:value', $object->json->bar);
97
    }
98
99
    /**
100
     * @return void
101
     */
102
    public function testInvalidSyntaxJson() : void
103
    {
104
        $this->expectException(Exception\InvalidValueException::class);
105
        $this->expectExceptionMessage('The <TestJsonDto.json> property only accepts valid JSON data (Syntax error).');
106
107
        (new Hydrator)->hydrate(new Fixture\TestJsonDto(), ['json' => '{']);
108
    }
109
110
    /**
111
     * @return void
112
     */
113
    public function testInvalidJsonType() : void
114
    {
115
        $this->expectException(Exception\InvalidValueException::class);
116
        $this->expectExceptionMessage('The <TestJsonDto.json> property only accepts a string.');
117
118
        (new Hydrator)->hydrate(new Fixture\TestJsonDto(), ['json' => []]);
119
    }
120
121
    /**
122
     * @return void
123
     */
124
    public function testMissingRequiredValueException() : void
125
    {
126
        $object = new Fixture\BarDto();
127
        $hydrator = new Hydrator();
128
129
        $this->expectException(Exception\MissingRequiredValueException::class);
130
        $this->expectExceptionMessage('The <BarDto.value> property is required.');
131
132
        $hydrator->hydrate($object, [
133
        ]);
134
    }
135
136
    /**
137
     * @return void
138
     */
139
    public function testUntypedObjectPropertyException() : void
140
    {
141
        $object = new Fixture\WithUntypedPropertyDto();
142
        $hydrator = new Hydrator();
143
144
        $this->expectException(Exception\UntypedObjectPropertyException::class);
145
        $this->expectExceptionMessage('The <WithUntypedPropertyDto.value> property is not typed.');
146
147
        $hydrator->hydrate($object, [
148
            'value' => 'foo',
149
        ]);
150
    }
151
152
    /**
153
     * @return void
154
     */
155
    public function testUnsupportedObjectPropertyTypeException() : void
156
    {
157
        $object = new Fixture\WithUnsupportedPropertyTypeDto();
158
        $hydrator = new Hydrator();
159
160
        $this->expectException(Exception\UnsupportedObjectPropertyTypeException::class);
161
        $this->expectExceptionMessage('The <WithUnsupportedPropertyTypeDto.value> property ' .
162
                                      'contains the <Traversable> unhydrable type.');
163
164
        $hydrator->hydrate($object, [
165
            'value' => 'foo',
166
        ]);
167
    }
168
169
    /**
170
     * @return void
171
     */
172
    public function testInvalidValueExceptionForNonNullableProperty() : void
173
    {
174
        $object = new Fixture\BazDto();
175
        $hydrator = new Hydrator();
176
177
        $this->expectException(Exception\InvalidValueException::class);
178
        $this->expectExceptionMessage('The <BazDto.nonNullable> property does not support null.');
179
180
        $hydrator->hydrate($object, [
181
            'nonNullable' => null,
182
        ]);
183
    }
184
185
    /**
186
     * @param mixed $nonScalarValue
187
     *
188
     * @return void
189
     *
190
     * @dataProvider nonScalarDataProvider
191
     */
192
    public function testInvalidValueExceptionForScalarProperty($nonScalarValue) : void
193
    {
194
        $object = new Fixture\BazDto();
195
        $hydrator = new Hydrator();
196
197
        $this->expectException(Exception\InvalidValueException::class);
198
        $this->expectExceptionMessage('The <BazDto.scalar> property only accepts a scalar value.');
199
200
        $hydrator->hydrate($object, [
201
            'scalar' => $nonScalarValue,
202
        ]);
203
    }
204
205
    /**
206
     * @param mixed $nonArrayValue
207
     *
208
     * @return void
209
     *
210
     * @dataProvider nonArrayDataProvider
211
     */
212
    public function testInvalidValueExceptionForArrayProperty($nonArrayValue) : void
213
    {
214
        $object = new Fixture\BazDto();
215
        $hydrator = new Hydrator();
216
217
        $this->expectException(Exception\InvalidValueException::class);
218
        $this->expectExceptionMessage('The <BazDto.array> property only accepts an array.');
219
220
        $hydrator->hydrate($object, [
221
            'array' => $nonArrayValue,
222
        ]);
223
    }
224
225
    /**
226
     * @param mixed $nonDateTimeValue
227
     *
228
     * @return void
229
     *
230
     * @dataProvider nonDateTimeDataProvider
231
     */
232
    public function testInvalidValueExceptionForDateTimeProperty($nonDateTimeValue) : void
233
    {
234
        $object = new Fixture\BazDto();
235
        $hydrator = new Hydrator();
236
237
        $this->expectException(Exception\InvalidValueException::class);
238
        $this->expectExceptionMessage('The <BazDto.dateTime> property only accepts a valid date-time string.');
239
240
        $hydrator->hydrate($object, [
241
            'dateTime' => $nonDateTimeValue,
242
        ]);
243
    }
244
245
    /**
246
     * @param mixed $nonArrayValue
247
     *
248
     * @return void
249
     *
250
     * @dataProvider nonArrayDataProvider
251
     */
252
    public function testInvalidValueExceptionForOneToOneProperty($nonArrayValue) : void
253
    {
254
        $object = new Fixture\BazDto();
255
        $hydrator = new Hydrator();
256
257
        $this->expectException(Exception\InvalidValueException::class);
258
        $this->expectExceptionMessage('The <BazDto.oneToOne> property only accepts an array.');
259
260
        $hydrator->hydrate($object, [
261
            'oneToOne' => $nonArrayValue,
262
        ]);
263
    }
264
265
    /**
266
     * @param mixed $nonArrayValue
267
     *
268
     * @return void
269
     *
270
     * @dataProvider nonArrayDataProvider
271
     */
272
    public function testInvalidValueExceptionForOneToManyProperty($nonArrayValue) : void
273
    {
274
        $object = new Fixture\BazDto();
275
        $hydrator = new Hydrator();
276
277
        $this->expectException(Exception\InvalidValueException::class);
278
        $this->expectExceptionMessage('The <BazDto.oneToMany> property only accepts an array.');
279
280
        $hydrator->hydrate($object, [
281
            'oneToMany' => $nonArrayValue,
282
        ]);
283
    }
284
285
    public function testEnumerableValue() : void
286
    {
287
        $object = (new Hydrator)->hydrate(new Fixture\TestEnumDto(), ['foo' => 'A']);
288
        $this->assertSame('A:value', $object->foo->getValue());
289
290
        $object = (new Hydrator)->hydrate(new Fixture\TestEnumDto(), ['foo' => 'B']);
291
        $this->assertSame('B:value', $object->foo->getValue());
292
293
        $object = (new Hydrator)->hydrate(new Fixture\TestEnumDto(), ['foo' => 'C']);
294
        $this->assertSame('C:value', $object->foo->getValue());
295
296
        $object = (new Hydrator)->hydrate(new Fixture\TestEnumDto(), ['foo' => '0']);
297
        $this->assertSame('0:value', $object->foo->getValue());
298
299
        $object = (new Hydrator)->hydrate(new Fixture\TestEnumDto(), ['foo' => '1']);
300
        $this->assertSame('1:value', $object->foo->getValue());
301
302
        $object = (new Hydrator)->hydrate(new Fixture\TestEnumDto(), ['foo' => '2']);
303
        $this->assertSame('2:value', $object->foo->getValue());
304
305
        $object = (new Hydrator)->hydrate(new Fixture\TestEnumDto(), ['foo' => 0]);
306
        $this->assertSame('0:value', $object->foo->getValue());
307
308
        $object = (new Hydrator)->hydrate(new Fixture\TestEnumDto(), ['foo' => 1]);
309
        $this->assertSame('1:value', $object->foo->getValue());
310
311
        $object = (new Hydrator)->hydrate(new Fixture\TestEnumDto(), ['foo' => 2]);
312
        $this->assertSame('2:value', $object->foo->getValue());
313
    }
314
315
    public function testUnknownEnumerableValue() : void
316
    {
317
        $this->expectException(Exception\InvalidValueException::class);
318
        $this->expectExceptionMessage('The <TestEnumDto.foo> property only accepts one of the <TestEnum> enum values.');
319
320
        (new Hydrator)->hydrate(new Fixture\TestEnumDto(), ['foo' => 'D']);
321
    }
322
323
    public function testInvalidEnumerableValue() : void
324
    {
325
        $this->expectException(Exception\InvalidValueException::class);
326
        $this->expectExceptionMessage('The <TestEnumDto.foo> property only accepts an integer or a string.');
327
328
        (new Hydrator)->hydrate(new Fixture\TestEnumDto(), ['foo' => []]);
329
    }
330
331
    /**
332
     * @return array<array>
333
     */
334
    public function nonScalarDataProvider() : array
335
    {
336
        return [
337
            [[]],
338
            [new \stdClass],
339
            [function () {
340
            }],
341
            [\STDOUT],
342
        ];
343
    }
344
345
    /**
346
     * @return array<array>
347
     */
348
    public function nonArrayDataProvider() : array
349
    {
350
        return [
351
            [true],
352
            [1],
353
            [1.1],
354
            [''],
355
            [new \stdClass],
356
            [function () {
357
            }],
358
            [\STDOUT],
359
        ];
360
    }
361
362
    /**
363
     * @return array<array>
364
     */
365
    public function nonDateTimeDataProvider() : array
366
    {
367
        return [
368
            [true],
369
            [1],
370
            [1.1],
371
            [''],
372
            ['0'],
373
            ['non-date-time-string'],
374
            [new \stdClass],
375
            [function () {
376
            }],
377
            [\STDOUT],
378
        ];
379
    }
380
}
381