ArrayObjectTest   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 344
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 162
dl 0
loc 344
c 0
b 0
f 0
rs 10
wmc 13

13 Methods

Rating   Name   Duplication   Size   Complexity  
A testEachStopsIteratingIfTheCallbackReturnsFalse() 0 16 1
A testIsInstantiable() 0 10 1
A providesRecordsMissingTheRequiredColumn() 0 20 1
A testSetAddsOrUpdatesAnElement() 0 13 1
A testReindexbycolumnvalueThrowsAnExceptionIfAnElementDoesNotContainTheRequiredColumn() 0 9 1
A providesReindexedArrays() 0 60 1
B providesArraysSortedByKey() 0 109 1
A testSortbykeySortsTheElementsByKey() 0 8 1
A testReindexbycolumnvalueThrowsAnExceptionIfAnElementIsNotARecord() 0 9 1
A providesElementsThatAreNotAllRecords() 0 12 1
A testReindexbycolumnvalueReindexesTheElementsByTheSpecifiedColumn() 0 11 1
A testEachExecutesTheCallbackForEachOfTheElements() 0 15 1
A testAppendAddsAnElementAtTheEndOfTheArray() 0 9 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace DanBettles\Gestalt\Tests;
6
7
use PHPUnit\Framework\TestCase;
8
use DanBettles\Gestalt\ArrayObject;
9
use InvalidArgumentException;
10
11
use const false;
12
13
class ArrayObjectTest extends TestCase
14
{
15
    public function testIsInstantiable()
16
    {
17
        $emptyArrayObject = new ArrayObject();
18
19
        $this->assertSame([], $emptyArrayObject->getElements());
20
21
        $elements = ['foo' => 'bar', 'baz' => 'qux'];
22
        $arrayObject = new ArrayObject($elements);
23
24
        $this->assertSame($elements, $arrayObject->getElements());
25
    }
26
27
    public function providesArraysSortedByKey()
28
    {
29
        return [[
30
            [
31
                'baz' => 'qux',
32
                'foo' => 'bar',
33
            ],
34
            [
35
                'foo' => 'bar',
36
                'baz' => 'qux',
37
            ],
38
            [],
39
        ], [
40
            [
41
                'foo',
42
                'bar',
43
                'baz',
44
            ],
45
            [
46
                'foo',
47
                'bar',
48
                'baz',
49
            ],
50
            [],
51
        ], [
52
            [
53
                1 => 'baz',
54
                2 => 'bar',
55
                3 => 'foo',
56
            ],
57
            [
58
                3 => 'foo',
59
                2 => 'bar',
60
                1 => 'baz',
61
            ],
62
            [],
63
        ], [  //Order array contains the same number of keys.
64
            [
65
                'corge' => 'grault',
66
                'foo' => 'bar',
67
                'quux' => 'quuz',
68
                'baz' => 'qux',
69
            ],
70
            [
71
                'foo' => 'bar',
72
                'baz' => 'qux',
73
                'quux' => 'quuz',
74
                'corge' => 'grault',
75
            ],
76
            [
77
                'corge',
78
                'foo',
79
                'quux',
80
                'baz',
81
            ],
82
        ], [  //Order array contains fewer keys.
83
            [
84
                'corge' => 'grault',
85
                'foo' => 'bar',
86
                'baz' => 'qux',
87
                'quux' => 'quuz',
88
            ],
89
            [
90
                'foo' => 'bar',
91
                'baz' => 'qux',
92
                'quux' => 'quuz',
93
                'corge' => 'grault',
94
            ],
95
            [
96
                'corge',
97
                'foo',
98
            ],
99
        ], [  //Order array contains extra keys.
100
            [
101
                'corge' => 'grault',
102
                'foo' => 'bar',
103
                'quux' => 'quuz',
104
                'baz' => 'qux',
105
            ],
106
            [
107
                'foo' => 'bar',
108
                'baz' => 'qux',
109
                'quux' => 'quuz',
110
                'corge' => 'grault',
111
            ],
112
            [
113
                'corge',
114
                'foo',
115
                'quux',
116
                'baz',
117
                'garply',
118
                'waldo',
119
            ],
120
        ], [  //Numeric keys and explicit order.
121
            [
122
                56 => 'bar',
123
                2 => 'baz',
124
                23 => 'foo',
125
                17 => 'qux',
126
            ],
127
            [
128
                23 => 'foo',
129
                56 => 'bar',
130
                2 => 'baz',
131
                17 => 'qux',
132
            ],
133
            [
134
                56,
135
                2,
136
            ],
137
        ]];
138
    }
139
140
    /**
141
     * @dataProvider providesArraysSortedByKey
142
     */
143
    public function testSortbykeySortsTheElementsByKey(array $expectedElements, array $elements, array $order)
144
    {
145
        $actual = (new ArrayObject($elements))
146
            ->sortByKey($order)
147
            ->getElements()
148
        ;
149
150
        $this->assertSame($expectedElements, $actual);
151
    }
152
153
    public function testEachExecutesTheCallbackForEachOfTheElements()
154
    {
155
        $elements = [
156
            'foo' => 'bar',
157
            'baz' => 'qux',
158
            'quux' => 'quuz',
159
        ];
160
161
        $output = [];
162
163
        (new ArrayObject($elements))->each(function ($key, $value) use (&$output) {
164
            $output[$key] = $value;
165
        });
166
167
        $this->assertSame($elements, $output);
168
    }
169
170
    public function testEachStopsIteratingIfTheCallbackReturnsFalse()
171
    {
172
        $output = [];
173
174
        (new ArrayObject([
175
            'foo' => 'bar',
176
            'baz' => 'qux',
177
            'quux' => 'quuz',
178
        ]))->each(function ($key, $value) use (&$output) {
179
            $output[$key] = $value;
180
            return false;
181
        });
182
183
        $this->assertSame([
184
            'foo' => 'bar',
185
        ], $output);
186
    }
187
188
    public function testAppendAddsAnElementAtTheEndOfTheArray()
189
    {
190
        $arrayObject = (new ArrayObject())
191
            ->append('foo')
192
            ->append('bar')
193
            ->append('baz')
194
        ;
195
196
        $this->assertSame(['foo', 'bar', 'baz'], $arrayObject->getElements());
197
    }
198
199
    public function testSetAddsOrUpdatesAnElement()
200
    {
201
        $arrayObject = (new ArrayObject())
202
            ->set('foo', 'bar')
203
            ->set('baz', 'qux')
204
            ->set('quux', 'quuz')
205
        ;
206
207
        $this->assertSame([
208
            'foo' => 'bar',
209
            'baz' => 'qux',
210
            'quux' => 'quuz',
211
        ], $arrayObject->getElements());
212
    }
213
214
    public function providesReindexedArrays(): array
215
    {
216
        $fooArray = [
217
            'id' => 123,
218
            'name' => 'Foo',
219
        ];
220
221
        $barArray = [
222
            'id' => 456,
223
            'name' => 'Bar',
224
        ];
225
226
        $bazArray = [
227
            'id' => 789,
228
            'name' => 'Baz',
229
        ];
230
231
        $fooObject = (object) $fooArray;
232
        $barObject = (object) $barArray;
233
        $bazObject = (object) $bazArray;
234
235
        return [[
236
            //Only array records.
237
            [
238
                'Bar' => $barArray,
239
                'Foo' => $fooArray,
240
                'Baz' => $bazArray,
241
            ],
242
            [
243
                $barArray,
244
                $fooArray,
245
                $bazArray,
246
            ],
247
            'name',
248
        ], [
249
            //Only object records.
250
            [
251
                'Bar' => $barObject,
252
                'Foo' => $fooObject,
253
                'Baz' => $bazObject,
254
            ],
255
            [
256
                $barObject,
257
                $fooObject,
258
                $bazObject,
259
            ],
260
            'name',
261
        ], [
262
            //A mix of array and object records.
263
            [
264
                'Bar' => $barObject,
265
                'Foo' => $fooArray,
266
                'Baz' => $bazObject,
267
            ],
268
            [
269
                $barObject,
270
                $fooArray,
271
                $bazObject,
272
            ],
273
            'name',
274
        ]];
275
    }
276
277
    /**
278
     * @dataProvider providesReindexedArrays
279
     */
280
    public function testReindexbycolumnvalueReindexesTheElementsByTheSpecifiedColumn(
281
        array $expected,
282
        array $input,
283
        string $columnKey
284
    ) {
285
        $arrayObject = new ArrayObject($input);
286
287
        $something = $arrayObject->reindexByColumn($columnKey);
288
289
        $this->assertSame($arrayObject, $something);
290
        $this->assertSame($expected, $something->getElements());
291
    }
292
293
    public function providesElementsThatAreNotAllRecords(): array
294
    {
295
        return [[
296
            [
297
                [
298
                    'id' => 123,
299
                    'name' => 'Foo',
300
                ],
301
                'Bar',  //Not a record ;-)
302
            ],
303
            'name',
304
            1,
305
        ]];
306
    }
307
308
    /**
309
     * @dataProvider providesElementsThatAreNotAllRecords
310
     */
311
    public function testReindexbycolumnvalueThrowsAnExceptionIfAnElementIsNotARecord(
312
        array $input,
313
        string $columnKey,
314
        $faultyElementKey
315
    ) {
316
        $this->expectException(InvalidArgumentException::class);
317
        $this->expectExceptionMessage("The element at index `{$faultyElementKey}` is not a record.");
318
319
        (new ArrayObject($input))->reindexByColumn($columnKey);
320
    }
321
322
    public function providesRecordsMissingTheRequiredColumn(): array
323
    {
324
        return [[
325
            [
326
                [
327
                    'id' => 123,
328
                    'name' => 'Foo',
329
                ],
330
                [
331
                    'id' => 456,
332
                    'name' => 'Bar',
333
                ],
334
                [
335
                    'id' => 789,
336
                    'title' => 'Baz',
337
                    //`name` element does not exist.
338
                ],
339
            ],
340
            'name',
341
            2,
342
        ]];
343
    }
344
345
    /**
346
     * @dataProvider providesRecordsMissingTheRequiredColumn
347
     */
348
    public function testReindexbycolumnvalueThrowsAnExceptionIfAnElementDoesNotContainTheRequiredColumn(
349
        array $input,
350
        string $columnKey,
351
        $faultyElementKey
352
    ) {
353
        $this->expectException(InvalidArgumentException::class);
354
        $this->expectExceptionMessage("The record at index `{$faultyElementKey}` does not contain the field `{$columnKey}`.");
355
356
        (new ArrayObject($input))->reindexByColumn($columnKey);
357
    }
358
}
359