Passed
Pull Request — master (#32)
by Ramsey
01:48
created

PaginationResultTest::testIteratorKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 16
c 1
b 0
f 1
dl 0
loc 23
rs 9.7333
cc 1
nc 1
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Lampager\Cake\Test\TestCase;
6
7
use ArrayIterator;
8
use Cake\Datasource\ConnectionManager;
9
use Cake\I18n\FrozenTime;
10
use Cake\ORM\Entity;
11
use Generator;
12
use IteratorAggregate;
13
use Lampager\Cake\PaginationResult;
14
use PHPUnit\Framework\MockObject\MockObject;
15
use Traversable;
16
17
class PaginationResultTest extends TestCase
18
{
19
    public function setUp(): void
20
    {
21
        set_error_handler(
22
            static function ($errno, $errstr) {
23
                throw new \Exception($errstr, $errno);
24
            },
25
            E_ALL
26
        );
27
    }
28
29
    public function tearDown(): void
30
    {
31
        restore_error_handler();
32
    }
33
34
    /**
35
     * @param Entity[]                     $entities
36
     * @param Entity[]|Traversable<Entity> $records
37
     * @param mixed[]                      $meta
38
     * @dataProvider arrayProvider
39
     * @dataProvider iteratorAggregateProvider
40
     */
41
    public function testIteratorCurrent(array $entities, $records, array $meta): void
42
    {
43
        $actual = new PaginationResult($records, $meta);
44
45
        $this->assertEquals($entities[0], $actual->current());
46
47
        $actual->next();
48
        $this->assertTrue($actual->valid());
49
        $this->assertEquals(1, $actual->key());
50
        $this->assertEquals($entities[1], $actual->current());
51
52
        $actual->next();
53
        $this->assertTrue($actual->valid());
54
        $this->assertEquals(2, $actual->key());
55
        $this->assertEquals($entities[2], $actual->current());
56
57
        $actual->next();
58
        $this->assertFalse($actual->valid());
59
60
        $actual->rewind();
61
        $this->assertTrue($actual->valid());
62
        $this->assertEquals(0, $actual->key());
63
        $this->assertEquals($entities[0], $actual->current());
64
    }
65
66
    /**
67
     * @param Entity[]                     $entities
68
     * @param Entity[]|Traversable<Entity> $records
69
     * @param mixed[]                      $meta
70
     * @dataProvider arrayProvider
71
     * @dataProvider iteratorAggregateProvider
72
     */
73
    public function testIteratorKey(array $entities, $records, array $meta): void
74
    {
75
        $actual = new PaginationResult($records, $meta);
76
77
        $this->assertEquals(0, $actual->key());
78
79
        $actual->next();
80
        $this->assertTrue($actual->valid());
81
        $this->assertEquals(1, $actual->key());
82
        $this->assertEquals($entities[1], $actual->current());
83
84
        $actual->next();
85
        $this->assertTrue($actual->valid());
86
        $this->assertEquals(2, $actual->key());
87
        $this->assertEquals($entities[2], $actual->current());
88
89
        $actual->next();
90
        $this->assertFalse($actual->valid());
91
92
        $actual->rewind();
93
        $this->assertTrue($actual->valid());
94
        $this->assertEquals(0, $actual->key());
95
        $this->assertEquals($entities[0], $actual->current());
96
    }
97
98
    /**
99
     * @param Entity[]                     $entities
100
     * @param Entity[]|Traversable<Entity> $records
101
     * @param mixed[]                      $meta
102
     * @dataProvider arrayProvider
103
     * @dataProvider iteratorAggregateProvider
104
     */
105
    public function testIteratorNext(array $entities, $records, array $meta): void
106
    {
107
        $actual = new PaginationResult($records, $meta);
108
109
        $actual->next();
110
        $this->assertTrue($actual->valid());
111
        $this->assertEquals(1, $actual->key());
112
        $this->assertEquals($entities[1], $actual->current());
113
114
        $actual->next();
115
        $this->assertTrue($actual->valid());
116
        $this->assertEquals(2, $actual->key());
117
        $this->assertEquals($entities[2], $actual->current());
118
119
        $actual->next();
120
        $this->assertFalse($actual->valid());
121
122
        $actual->rewind();
123
        $this->assertTrue($actual->valid());
124
        $this->assertEquals(0, $actual->key());
125
        $this->assertEquals($entities[0], $actual->current());
126
    }
127
128
    /**
129
     * @param Entity[]                     $entities
130
     * @param Entity[]|Traversable<Entity> $records
131
     * @param mixed[]                      $meta
132
     * @dataProvider arrayProvider
133
     * @dataProvider iteratorAggregateProvider
134
     */
135
    public function testIteratorValid(array $entities, $records, array $meta): void
136
    {
137
        $actual = new PaginationResult($records, $meta);
138
139
        $this->assertTrue($actual->valid());
140
        $this->assertEquals(0, $actual->key());
141
        $this->assertEquals($entities[0], $actual->current());
142
143
        $actual->next();
144
        $this->assertTrue($actual->valid());
145
        $this->assertEquals(1, $actual->key());
146
        $this->assertEquals($entities[1], $actual->current());
147
148
        $actual->next();
149
        $this->assertTrue($actual->valid());
150
        $this->assertEquals(2, $actual->key());
151
        $this->assertEquals($entities[2], $actual->current());
152
153
        $actual->next();
154
        $this->assertFalse($actual->valid());
155
156
        $actual->rewind();
157
        $this->assertTrue($actual->valid());
158
        $this->assertEquals(0, $actual->key());
159
        $this->assertEquals($entities[0], $actual->current());
160
    }
161
162
    /**
163
     * @param Entity[]                     $entities
164
     * @param Entity[]|Traversable<Entity> $records
165
     * @param mixed[]                      $meta
166
     * @dataProvider arrayProvider
167
     * @dataProvider iteratorAggregateProvider
168
     */
169
    public function testJsonSerialize(array $entities, $records, array $meta, string $expected): void
0 ignored issues
show
Unused Code introduced by
The parameter $entities is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

169
    public function testJsonSerialize(/** @scrutinizer ignore-unused */ array $entities, $records, array $meta, string $expected): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
170
    {
171
        $actual = json_encode(new PaginationResult($records, $meta));
172
        $this->assertJsonStringEqualsJsonString($expected, $actual);
173
    }
174
175
    /**
176
     * @param Entity[]                     $entities
177
     * @param Entity[]|Traversable<Entity> $records
178
     * @param mixed[]                      $meta
179
     * @dataProvider arrayProvider
180
     * @dataProvider iteratorAggregateProvider
181
     */
182
    public function testSerializeAndUnserialize(array $entities, $records, array $meta): void
0 ignored issues
show
Unused Code introduced by
The parameter $entities is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

182
    public function testSerializeAndUnserialize(/** @scrutinizer ignore-unused */ array $entities, $records, array $meta): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
183
    {
184
        $actual = unserialize(serialize(new PaginationResult($records, $meta)));
185
        $expected = new PaginationResult($records, $meta);
186
        $this->assertJsonEquals($expected, $actual);
187
    }
188
189
    /**
190
     * @param Entity[]                     $entities
191
     * @param Entity[]|Traversable<Entity> $records
192
     * @param mixed[]                      $meta
193
     * @dataProvider arrayProvider
194
     * @dataProvider iteratorAggregateProvider
195
     */
196
    public function testDebugInfo(array $entities, $records, array $meta): void
197
    {
198
        $actual = (new PaginationResult($records, $meta))->__debugInfo();
199
200
        $this->assertEquals([
201
            '(help)' => 'This is a Lampager Pagination Result object.',
202
            'records' => $entities,
203
            'hasPrevious' => $meta['hasPrevious'],
204
            'previousCursor' => $meta['previousCursor'],
205
            'hasNext' => $meta['hasNext'],
206
            'nextCursor' => $meta['nextCursor'],
207
        ], $actual);
208
    }
209
210
    /**
211
     * @param Entity[]                     $entities
212
     * @param Entity[]|Traversable<Entity> $records
213
     * @param mixed[]                      $meta
214
     * @dataProvider arrayProvider
215
     * @dataProvider iteratorAggregateProvider
216
     */
217
    public function testPublicProperties(array $entities, $records, array $meta): void
0 ignored issues
show
Unused Code introduced by
The parameter $entities is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

217
    public function testPublicProperties(/** @scrutinizer ignore-unused */ array $entities, $records, array $meta): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
218
    {
219
        $paginationResult = new PaginationResult($records, $meta);
220
221
        $this->assertEquals($meta['hasPrevious'], $paginationResult->hasPrevious);
222
        $this->assertEquals($meta['previousCursor'], $paginationResult->previousCursor);
223
        $this->assertEquals($meta['hasNext'], $paginationResult->hasNext);
224
        $this->assertEquals($meta['nextCursor'], $paginationResult->nextCursor);
225
    }
226
227
    /**
228
     * @param Entity[]                     $entities
229
     * @param Entity[]|Traversable<Entity> $records
230
     * @param mixed[]                      $meta
231
     * @dataProvider arrayProvider
232
     * @dataProvider iteratorAggregateProvider
233
     */
234
    public function testUndefinedProperties(array $entities, $records, array $meta): void
0 ignored issues
show
Unused Code introduced by
The parameter $entities is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

234
    public function testUndefinedProperties(/** @scrutinizer ignore-unused */ array $entities, $records, array $meta): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
235
    {
236
        $this->expectException(\Exception::class);
237
        $this->expectExceptionMessageMatches('/^Undefined property via __get\(\): undefinedProperty/');
238
239
        $paginationResult = new PaginationResult($records, $meta);
240
        $paginationResult->undefinedProperty;
0 ignored issues
show
Bug Best Practice introduced by
The property undefinedProperty does not exist on Lampager\Cake\PaginationResult. Since you implemented __get, consider adding a @property annotation.
Loading history...
241
    }
242
243
    public function arrayProvider(): Generator
244
    {
245
        yield 'Array iteration' => [
246
            [
247
                new Entity([
248
                    'id' => 1,
249
                    'modified' => new FrozenTime('2017-01-01 10:00:00'),
250
                ]),
251
                new Entity([
252
                    'id' => 3,
253
                    'modified' => new FrozenTime('2017-01-01 10:00:00'),
254
                ]),
255
                new Entity([
256
                    'id' => 5,
257
                    'modified' => new FrozenTime('2017-01-01 10:00:00'),
258
                ]),
259
            ],
260
            [
261
                new Entity([
262
                    'id' => 1,
263
                    'modified' => new FrozenTime('2017-01-01 10:00:00'),
264
                ]),
265
                new Entity([
266
                    'id' => 3,
267
                    'modified' => new FrozenTime('2017-01-01 10:00:00'),
268
                ]),
269
                new Entity([
270
                    'id' => 5,
271
                    'modified' => new FrozenTime('2017-01-01 10:00:00'),
272
                ]),
273
            ],
274
            [
275
                'hasPrevious' => null,
276
                'previousCursor' => null,
277
                'hasNext' => true,
278
                'nextCursor' => [
279
                    'Posts.id' => 2,
280
                    'Posts.modified' => new FrozenTime('2017-01-01 11:00:00'),
281
                ],
282
            ],
283
            '{
284
                "records": [
285
                    {
286
                        "id": 1,
287
                        "modified": "2017-01-01T10:00:00+00:00"
288
                    },
289
                    {
290
                        "id": 3,
291
                        "modified": "2017-01-01T10:00:00+00:00"
292
                    },
293
                    {
294
                        "id": 5,
295
                        "modified": "2017-01-01T10:00:00+00:00"
296
                    }
297
                ],
298
                "hasPrevious": null,
299
                "previousCursor": null,
300
                "hasNext": true,
301
                "nextCursor": {
302
                    "Posts.id": 2,
303
                    "Posts.modified": "2017-01-01T11:00:00+00:00"
304
                }
305
            }',
306
        ];
307
308
        yield 'ArrayIterator iteration' => [
309
            [
310
                new Entity([
311
                    'id' => 1,
312
                    'modified' => new FrozenTime('2017-01-01 10:00:00'),
313
                ]),
314
                new Entity([
315
                    'id' => 3,
316
                    'modified' => new FrozenTime('2017-01-01 10:00:00'),
317
                ]),
318
                new Entity([
319
                    'id' => 5,
320
                    'modified' => new FrozenTime('2017-01-01 10:00:00'),
321
                ]),
322
            ],
323
            new ArrayIterator([
324
                new Entity([
325
                    'id' => 1,
326
                    'modified' => new FrozenTime('2017-01-01 10:00:00'),
327
                ]),
328
                new Entity([
329
                    'id' => 3,
330
                    'modified' => new FrozenTime('2017-01-01 10:00:00'),
331
                ]),
332
                new Entity([
333
                    'id' => 5,
334
                    'modified' => new FrozenTime('2017-01-01 10:00:00'),
335
                ]),
336
            ]),
337
            [
338
                'hasPrevious' => null,
339
                'previousCursor' => null,
340
                'hasNext' => true,
341
                'nextCursor' => [
342
                    'Posts.id' => 2,
343
                    'Posts.modified' => new FrozenTime('2017-01-01 11:00:00'),
344
                ],
345
            ],
346
            '{
347
                "records": [
348
                    {
349
                        "id": 1,
350
                        "modified": "2017-01-01T10:00:00+00:00"
351
                    },
352
                    {
353
                        "id": 3,
354
                        "modified": "2017-01-01T10:00:00+00:00"
355
                    },
356
                    {
357
                        "id": 5,
358
                        "modified": "2017-01-01T10:00:00+00:00"
359
                    }
360
                ],
361
                "hasPrevious": null,
362
                "previousCursor": null,
363
                "hasNext": true,
364
                "nextCursor": {
365
                    "Posts.id": 2,
366
                    "Posts.modified": "2017-01-01T11:00:00+00:00"
367
                }
368
            }',
369
        ];
370
    }
371
372
    public function iteratorAggregateProvider(): Generator
373
    {
374
        /** @var IteratorAggregate&MockObject $iteratorAggregate */
375
        $iteratorAggregate = $this->getMockForAbstractClass(IteratorAggregate::class);
376
        $iteratorAggregate->method('getIterator')->willReturn(new ArrayIterator([
377
            new Entity([
378
                'id' => 1,
379
                'modified' => new FrozenTime('2017-01-01 10:00:00'),
380
            ]),
381
            new Entity([
382
                'id' => 3,
383
                'modified' => new FrozenTime('2017-01-01 10:00:00'),
384
            ]),
385
            new Entity([
386
                'id' => 5,
387
                'modified' => new FrozenTime('2017-01-01 10:00:00'),
388
            ]),
389
        ]));
390
391
        yield 'IteratorAggregate iteration' => [
392
            [
393
                new Entity([
394
                    'id' => 1,
395
                    'modified' => new FrozenTime('2017-01-01 10:00:00'),
396
                ]),
397
                new Entity([
398
                    'id' => 3,
399
                    'modified' => new FrozenTime('2017-01-01 10:00:00'),
400
                ]),
401
                new Entity([
402
                    'id' => 5,
403
                    'modified' => new FrozenTime('2017-01-01 10:00:00'),
404
                ]),
405
            ],
406
            $iteratorAggregate,
407
            [
408
                'hasPrevious' => null,
409
                'previousCursor' => null,
410
                'hasNext' => true,
411
                'nextCursor' => [
412
                    'Posts.id' => 2,
413
                    'Posts.modified' => new FrozenTime('2017-01-01 11:00:00'),
414
                ],
415
            ],
416
            '{
417
                "records": [
418
                    {
419
                        "id": 1,
420
                        "modified": "2017-01-01T10:00:00+00:00"
421
                    },
422
                    {
423
                        "id": 3,
424
                        "modified": "2017-01-01T10:00:00+00:00"
425
                    },
426
                    {
427
                        "id": 5,
428
                        "modified": "2017-01-01T10:00:00+00:00"
429
                    }
430
                ],
431
                "hasPrevious": null,
432
                "previousCursor": null,
433
                "hasNext": true,
434
                "nextCursor": {
435
                    "Posts.id": 2,
436
                    "Posts.modified": "2017-01-01T11:00:00+00:00"
437
                }
438
            }',
439
        ];
440
    }
441
}
442