Passed
Push — main ( c5ac27...5a77c7 )
by Anatoly
13:01 queued 10:26
created

HydratorTest::testEnumerableValue()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 6
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 10
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 testMissingRequiredValueException() : void
90
    {
91
        $object = new Fixture\BarDto();
92
        $hydrator = new Hydrator();
93
94
        $this->expectException(Exception\MissingRequiredValueException::class);
95
        $this->expectExceptionMessage('The <BarDto.value> property is required.');
96
97
        $hydrator->hydrate($object, [
98
        ]);
99
    }
100
101
    /**
102
     * @return void
103
     */
104
    public function testUntypedObjectPropertyException() : void
105
    {
106
        $object = new Fixture\WithUntypedPropertyDto();
107
        $hydrator = new Hydrator();
108
109
        $this->expectException(Exception\UntypedObjectPropertyException::class);
110
        $this->expectExceptionMessage('The <WithUntypedPropertyDto.value> property is not typed.');
111
112
        $hydrator->hydrate($object, [
113
            'value' => 'foo',
114
        ]);
115
    }
116
117
    /**
118
     * @return void
119
     */
120
    public function testUnsupportedObjectPropertyTypeException() : void
121
    {
122
        $object = new Fixture\WithUnsupportedPropertyTypeDto();
123
        $hydrator = new Hydrator();
124
125
        $this->expectException(Exception\UnsupportedObjectPropertyTypeException::class);
126
        $this->expectExceptionMessage('The <WithUnsupportedPropertyTypeDto.value> property ' .
127
                                      'contains the <Traversable> unhydrable type.');
128
129
        $hydrator->hydrate($object, [
130
            'value' => 'foo',
131
        ]);
132
    }
133
134
    /**
135
     * @return void
136
     */
137
    public function testInvalidValueExceptionForNonNullableProperty() : void
138
    {
139
        $object = new Fixture\BazDto();
140
        $hydrator = new Hydrator();
141
142
        $this->expectException(Exception\InvalidValueException::class);
143
        $this->expectExceptionMessage('The <BazDto.nonNullable> property does not support null.');
144
145
        $hydrator->hydrate($object, [
146
            'nonNullable' => null,
147
        ]);
148
    }
149
150
    /**
151
     * @param mixed $nonScalarValue
152
     *
153
     * @return void
154
     *
155
     * @dataProvider nonScalarDataProvider
156
     */
157
    public function testInvalidValueExceptionForScalarProperty($nonScalarValue) : void
158
    {
159
        $object = new Fixture\BazDto();
160
        $hydrator = new Hydrator();
161
162
        $this->expectException(Exception\InvalidValueException::class);
163
        $this->expectExceptionMessage('The <BazDto.scalar> property only accepts a scalar value.');
164
165
        $hydrator->hydrate($object, [
166
            'scalar' => $nonScalarValue,
167
        ]);
168
    }
169
170
    /**
171
     * @param mixed $nonArrayValue
172
     *
173
     * @return void
174
     *
175
     * @dataProvider nonArrayDataProvider
176
     */
177
    public function testInvalidValueExceptionForArrayProperty($nonArrayValue) : void
178
    {
179
        $object = new Fixture\BazDto();
180
        $hydrator = new Hydrator();
181
182
        $this->expectException(Exception\InvalidValueException::class);
183
        $this->expectExceptionMessage('The <BazDto.array> property only accepts an array.');
184
185
        $hydrator->hydrate($object, [
186
            'array' => $nonArrayValue,
187
        ]);
188
    }
189
190
    /**
191
     * @param mixed $nonDateTimeValue
192
     *
193
     * @return void
194
     *
195
     * @dataProvider nonDateTimeDataProvider
196
     */
197
    public function testInvalidValueExceptionForDateTimeProperty($nonDateTimeValue) : void
198
    {
199
        $object = new Fixture\BazDto();
200
        $hydrator = new Hydrator();
201
202
        $this->expectException(Exception\InvalidValueException::class);
203
        $this->expectExceptionMessage('The <BazDto.dateTime> property only accepts a valid date-time string.');
204
205
        $hydrator->hydrate($object, [
206
            'dateTime' => $nonDateTimeValue,
207
        ]);
208
    }
209
210
    /**
211
     * @param mixed $nonArrayValue
212
     *
213
     * @return void
214
     *
215
     * @dataProvider nonArrayDataProvider
216
     */
217
    public function testInvalidValueExceptionForOneToOneProperty($nonArrayValue) : void
218
    {
219
        $object = new Fixture\BazDto();
220
        $hydrator = new Hydrator();
221
222
        $this->expectException(Exception\InvalidValueException::class);
223
        $this->expectExceptionMessage('The <BazDto.oneToOne> property only accepts an array.');
224
225
        $hydrator->hydrate($object, [
226
            'oneToOne' => $nonArrayValue,
227
        ]);
228
    }
229
230
    /**
231
     * @param mixed $nonArrayValue
232
     *
233
     * @return void
234
     *
235
     * @dataProvider nonArrayDataProvider
236
     */
237
    public function testInvalidValueExceptionForOneToManyProperty($nonArrayValue) : void
238
    {
239
        $object = new Fixture\BazDto();
240
        $hydrator = new Hydrator();
241
242
        $this->expectException(Exception\InvalidValueException::class);
243
        $this->expectExceptionMessage('The <BazDto.oneToMany> property only accepts an array.');
244
245
        $hydrator->hydrate($object, [
246
            'oneToMany' => $nonArrayValue,
247
        ]);
248
    }
249
250
    public function testEnumerableValue() : void
251
    {
252
        $object = (new Hydrator)->hydrate(new Fixture\TestEnumDto(), ['foo' => 'A']);
253
        $this->assertSame('A:value', $object->foo->getValue());
254
255
        $object = (new Hydrator)->hydrate(new Fixture\TestEnumDto(), ['foo' => 'B']);
256
        $this->assertSame('B:value', $object->foo->getValue());
257
258
        $object = (new Hydrator)->hydrate(new Fixture\TestEnumDto(), ['foo' => 'C']);
259
        $this->assertSame('C:value', $object->foo->getValue());
260
    }
261
262
    public function testUnknownEnumerableValue() : void
263
    {
264
        $this->expectException(Exception\InvalidValueException::class);
265
        $this->expectExceptionMessage('The <TestEnumDto.foo> property only accepts one of the <TestEnum> enum values.');
266
267
        (new Hydrator)->hydrate(new Fixture\TestEnumDto(), ['foo' => 'D']);
268
    }
269
270
    public function testInvalidEnumerableValue() : void
271
    {
272
        $this->expectException(Exception\InvalidValueException::class);
273
        $this->expectExceptionMessage('The <TestEnumDto.foo> property only accepts a string.');
274
275
        (new Hydrator)->hydrate(new Fixture\TestEnumDto(), ['foo' => []]);
276
    }
277
278
    /**
279
     * @return array<array>
280
     */
281
    public function nonScalarDataProvider() : array
282
    {
283
        return [
284
            [[]],
285
            [new \stdClass],
286
            [function () {
287
            }],
288
            [\STDOUT],
289
        ];
290
    }
291
292
    /**
293
     * @return array<array>
294
     */
295
    public function nonArrayDataProvider() : array
296
    {
297
        return [
298
            [true],
299
            [1],
300
            [1.1],
301
            [''],
302
            [new \stdClass],
303
            [function () {
304
            }],
305
            [\STDOUT],
306
        ];
307
    }
308
309
    /**
310
     * @return array<array>
311
     */
312
    public function nonDateTimeDataProvider() : array
313
    {
314
        return [
315
            [true],
316
            [1],
317
            [1.1],
318
            [''],
319
            ['0'],
320
            ['non-date-time-string'],
321
            [new \stdClass],
322
            [function () {
323
            }],
324
            [\STDOUT],
325
        ];
326
    }
327
}
328