Passed
Push — master ( bee159...00f7f8 )
by Chito
01:46
created

PaginatorTest::testPaginateCakeQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 6
c 1
b 0
f 0
dl 0
loc 13
rs 10
cc 1
nc 1
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Lampager\Cake\Test\TestCase\Datasource;
6
7
use Cake\Controller\Controller;
8
use Cake\Database\Expression\OrderClauseExpression;
9
use Cake\Datasource\QueryInterface;
10
use Cake\I18n\Time;
11
use Cake\ORM\Entity;
12
use Cake\ORM\Table;
13
use Exception;
14
use Generator;
15
use Lampager\Cake\Datasource\Paginator;
16
use Lampager\Cake\Model\Behavior\LampagerBehavior;
17
use Lampager\Cake\PaginationResult;
18
use Lampager\Cake\Test\TestCase\TestCase;
19
use Lampager\Exceptions\InvalidArgumentException;
20
use PHPUnit\Framework\MockObject\MockObject;
21
22
class PaginatorTest extends TestCase
23
{
24
    public $fixtures = [
25
        'plugin.Lampager\\Cake.Posts',
26
    ];
27
28
    /**
29
     * @dataProvider valueProvider
30
     * @dataProvider queryExpressionProvider
31
     */
32
    public function testPaginateTable(callable $factory, PaginationResult $expected): void
33
    {
34
        $controller = new Controller();
35
        $controller->loadComponent('Paginator');
36
        $controller->Paginator->setPaginator(new Paginator());
37
38
        /** @var Table $posts */
39
        $posts = $controller->loadModel('Posts');
40
41
        /** @var mixed[] $options */
42
        $options = $factory($posts);
43
44
        $this->assertJsonEquals($expected, $controller->paginate('Posts', $options));
45
    }
46
47
    /**
48
     * @dataProvider valueProvider
49
     * @dataProvider queryExpressionProvider
50
     */
51
    public function testPaginateCakeQuery(callable $factory, PaginationResult $expected): void
52
    {
53
        $controller = new Controller();
54
        $controller->loadComponent('Paginator');
55
        $controller->Paginator->setPaginator(new Paginator());
56
57
        /** @var Table $posts */
58
        $posts = $controller->loadModel('Posts');
59
60
        /** @var mixed[] $options */
61
        $options = $factory($posts);
62
63
        $this->assertJsonEquals($expected, $controller->paginate($posts->find('all'), $options));
64
    }
65
66
    /**
67
     * @dataProvider valueProvider
68
     * @dataProvider queryExpressionProvider
69
     */
70
    public function testPaginateLampagerCakeQuery(callable $factory): void
71
    {
72
        $this->expectException(InvalidArgumentException::class);
73
        $this->expectExceptionMessage('Lampager\Cake\ORM\Query cannot be paginated by Lampager\Cake\Datasource\Paginator::paginate()');
74
75
        $controller = new Controller();
76
        $controller->loadComponent('Paginator');
77
        $controller->Paginator->setPaginator(new Paginator());
78
79
        /** @var LampagerBehavior&Table $posts */
80
        $posts = $controller->loadModel('Posts');
81
        $posts->addBehavior(LampagerBehavior::class);
82
83
        /** @var mixed[] $options */
84
        $options = $factory($posts);
85
        $query = $posts->lampager()->applyOptions($options);
86
        $controller->paginate($query);
87
    }
88
89
    public function testPaginateInvalidQuery(): void
90
    {
91
        $this->expectException(Exception::class);
92
        $this->expectExceptionMessage('No repository set for query.');
93
94
        $controller = new Controller();
95
        $controller->loadComponent('Paginator');
96
        $controller->Paginator->setPaginator(new Paginator());
97
98
        /** @var MockObject&QueryInterface $query */
99
        $query = $this->getMockBuilder(QueryInterface::class)->getMock();
100
        $query->method('getRepository')->willReturn(null);
101
102
        $controller->paginate($query);
103
    }
104
105
    public function valueProvider(): Generator
106
    {
107
        yield 'Ascending forward start inclusive' => [
108
            function () {
109
                return [
110
                    'forward' => true,
111
                    'seekable' => true,
112
                    'limit' => 3,
113
                    'order' => [
114
                        'modified' => 'asc',
115
                        'id' => 'asc',
116
                    ],
117
                ];
118
            },
119
            new PaginationResult(
120
                [
121
                    new Entity([
122
                        'id' => 1,
123
                        'modified' => new Time('2017-01-01 10:00:00'),
124
                    ]),
125
                    new Entity([
126
                        'id' => 3,
127
                        'modified' => new Time('2017-01-01 10:00:00'),
128
                    ]),
129
                    new Entity([
130
                        'id' => 5,
131
                        'modified' => new Time('2017-01-01 10:00:00'),
132
                    ]),
133
                ],
134
                [
135
                    'hasPrevious' => null,
136
                    'previousCursor' => null,
137
                    'hasNext' => true,
138
                    'nextCursor' => [
139
                        'Posts.id' => 2,
140
                        'Posts.modified' => new Time('2017-01-01 11:00:00'),
141
                    ],
142
                ]
143
            ),
144
        ];
145
146
        yield 'Ascending forward start exclusive' => [
147
            function () {
148
                return [
149
                    'forward' => true,
150
                    'seekable' => true,
151
                    'exclusive' => true,
152
                    'limit' => 3,
153
                    'order' => [
154
                        'modified' => 'asc',
155
                        'id' => 'asc',
156
                    ],
157
                ];
158
            },
159
            new PaginationResult(
160
                [
161
                    new Entity([
162
                        'id' => 1,
163
                        'modified' => new Time('2017-01-01 10:00:00'),
164
                    ]),
165
                    new Entity([
166
                        'id' => 3,
167
                        'modified' => new Time('2017-01-01 10:00:00'),
168
                    ]),
169
                    new Entity([
170
                        'id' => 5,
171
                        'modified' => new Time('2017-01-01 10:00:00'),
172
                    ]),
173
                ],
174
                [
175
                    'hasPrevious' => null,
176
                    'previousCursor' => null,
177
                    'hasNext' => true,
178
                    'nextCursor' => [
179
                        'Posts.id' => 5,
180
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
181
                    ],
182
                ]
183
            ),
184
        ];
185
186
        yield 'Ascending forward inclusive' => [
187
            function () {
188
                return [
189
                    'forward' => true,
190
                    'seekable' => true,
191
                    'limit' => 3,
192
                    'order' => [
193
                        'modified' => 'asc',
194
                        'id' => 'asc',
195
                    ],
196
                    'cursor' => [
197
                        'Posts.id' => 3,
198
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
199
                    ],
200
                ];
201
            },
202
            new PaginationResult(
203
                [
204
                    new Entity([
205
                        'id' => 3,
206
                        'modified' => new Time('2017-01-01 10:00:00'),
207
                    ]),
208
                    new Entity([
209
                        'id' => 5,
210
                        'modified' => new Time('2017-01-01 10:00:00'),
211
                    ]),
212
                    new Entity([
213
                        'id' => 2,
214
                        'modified' => new Time('2017-01-01 11:00:00'),
215
                    ]),
216
                ],
217
                [
218
                    'hasPrevious' => true,
219
                    'previousCursor' => [
220
                        'Posts.id' => 1,
221
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
222
                    ],
223
                    'hasNext' => true,
224
                    'nextCursor' => [
225
                        'Posts.id' => 4,
226
                        'Posts.modified' => new Time('2017-01-01 11:00:00'),
227
                    ],
228
                ]
229
            ),
230
        ];
231
232
        yield 'Ascending forward exclusive' => [
233
            function () {
234
                return [
235
                    'forward' => true,
236
                    'seekable' => true,
237
                    'exclusive' => true,
238
                    'limit' => 3,
239
                    'order' => [
240
                        'modified' => 'asc',
241
                        'id' => 'asc',
242
                    ],
243
                    'cursor' => [
244
                        'Posts.id' => 3,
245
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
246
                    ],
247
                ];
248
            },
249
            new PaginationResult(
250
                [
251
                    new Entity([
252
                        'id' => 5,
253
                        'modified' => new Time('2017-01-01 10:00:00'),
254
                    ]),
255
                    new Entity([
256
                        'id' => 2,
257
                        'modified' => new Time('2017-01-01 11:00:00'),
258
                    ]),
259
                    new Entity([
260
                        'id' => 4,
261
                        'modified' => new Time('2017-01-01 11:00:00'),
262
                    ]),
263
                ],
264
                [
265
                    'hasPrevious' => true,
266
                    'previousCursor' => [
267
                        'Posts.id' => 5,
268
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
269
                    ],
270
                    'hasNext' => false,
271
                    'nextCursor' => null,
272
                ]
273
            ),
274
        ];
275
276
        yield 'Ascending backward start inclusive' => [
277
            function () {
278
                return [
279
                    'backward' => true,
280
                    'seekable' => true,
281
                    'limit' => 3,
282
                    'order' => [
283
                        'modified' => 'asc',
284
                        'id' => 'asc',
285
                    ],
286
                ];
287
            },
288
            new PaginationResult(
289
                [
290
                    new Entity([
291
                        'id' => 5,
292
                        'modified' => new Time('2017-01-01 10:00:00'),
293
                    ]),
294
                    new Entity([
295
                        'id' => 2,
296
                        'modified' => new Time('2017-01-01 11:00:00'),
297
                    ]),
298
                    new Entity([
299
                        'id' => 4,
300
                        'modified' => new Time('2017-01-01 11:00:00'),
301
                    ]),
302
                ],
303
                [
304
                    'hasPrevious' => true,
305
                    'previousCursor' => [
306
                        'Posts.id' => 3,
307
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
308
                    ],
309
                    'hasNext' => null,
310
                    'nextCursor' => null,
311
                ]
312
            ),
313
        ];
314
315
        yield 'Ascending backward start exclusive' => [
316
            function () {
317
                return [
318
                    'backward' => true,
319
                    'seekable' => true,
320
                    'exclusive' => true,
321
                    'limit' => 3,
322
                    'order' => [
323
                        'modified' => 'asc',
324
                        'id' => 'asc',
325
                    ],
326
                ];
327
            },
328
            new PaginationResult(
329
                [
330
                    new Entity([
331
                        'id' => 5,
332
                        'modified' => new Time('2017-01-01 10:00:00'),
333
                    ]),
334
                    new Entity([
335
                        'id' => 2,
336
                        'modified' => new Time('2017-01-01 11:00:00'),
337
                    ]),
338
                    new Entity([
339
                        'id' => 4,
340
                        'modified' => new Time('2017-01-01 11:00:00'),
341
                    ]),
342
                ],
343
                [
344
                    'hasPrevious' => true,
345
                    'previousCursor' => [
346
                        'Posts.id' => 5,
347
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
348
                    ],
349
                    'hasNext' => null,
350
                    'nextCursor' => null,
351
                ]
352
            ),
353
        ];
354
355
        yield 'Ascending backward inclusive' => [
356
            function () {
357
                return [
358
                    'backward' => true,
359
                    'seekable' => true,
360
                    'limit' => 3,
361
                    'order' => [
362
                        'modified' => 'asc',
363
                        'id' => 'asc',
364
                    ],
365
                    'cursor' => [
366
                        'Posts.id' => 3,
367
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
368
                    ],
369
                ];
370
            },
371
            new PaginationResult(
372
                [
373
                    new Entity([
374
                        'id' => 1,
375
                        'modified' => new Time('2017-01-01 10:00:00'),
376
                    ]),
377
                    new Entity([
378
                        'id' => 3,
379
                        'modified' => new Time('2017-01-01 10:00:00'),
380
                    ]),
381
                ],
382
                [
383
                    'hasPrevious' => false,
384
                    'previousCursor' => null,
385
                    'hasNext' => true,
386
                    'nextCursor' => [
387
                        'Posts.id' => 5,
388
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
389
                    ],
390
                ]
391
            ),
392
        ];
393
394
        yield 'Ascending backward exclusive' => [
395
            function () {
396
                return [
397
                    'backward' => true,
398
                    'seekable' => true,
399
                    'exclusive' => true,
400
                    'limit' => 3,
401
                    'order' => [
402
                        'modified' => 'asc',
403
                        'id' => 'asc',
404
                    ],
405
                    'cursor' => [
406
                        'Posts.id' => 3,
407
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
408
                    ],
409
                ];
410
            },
411
            new PaginationResult(
412
                [
413
                    new Entity([
414
                        'id' => 1,
415
                        'modified' => new Time('2017-01-01 10:00:00'),
416
                    ]),
417
                ],
418
                [
419
                    'hasPrevious' => false,
420
                    'previousCursor' => null,
421
                    'hasNext' => true,
422
                    'nextCursor' => [
423
                        'Posts.id' => 1,
424
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
425
                    ],
426
                ]
427
            ),
428
        ];
429
430
        yield 'Descending forward start inclusive' => [
431
            function () {
432
                return [
433
                    'forward' => true,
434
                    'seekable' => true,
435
                    'limit' => 3,
436
                    'order' => [
437
                        'modified' => 'desc',
438
                        'id' => 'desc',
439
                    ],
440
                ];
441
            },
442
            new PaginationResult(
443
                [
444
                    new Entity([
445
                        'id' => 4,
446
                        'modified' => new Time('2017-01-01 11:00:00'),
447
                    ]),
448
                    new Entity([
449
                        'id' => 2,
450
                        'modified' => new Time('2017-01-01 11:00:00'),
451
                    ]),
452
                    new Entity([
453
                        'id' => 5,
454
                        'modified' => new Time('2017-01-01 10:00:00'),
455
                    ]),
456
                ],
457
                [
458
                    'hasPrevious' => null,
459
                    'previousCursor' => null,
460
                    'hasNext' => true,
461
                    'nextCursor' => [
462
                        'Posts.id' => 3,
463
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
464
                    ],
465
                ]
466
            ),
467
        ];
468
469
        yield 'Descending forward start exclusive' => [
470
            function () {
471
                return [
472
                    'forward' => true,
473
                    'seekable' => true,
474
                    'exclusive' => true,
475
                    'limit' => 3,
476
                    'order' => [
477
                        'modified' => 'desc',
478
                        'id' => 'desc',
479
                    ],
480
                ];
481
            },
482
            new PaginationResult(
483
                [
484
                    new Entity([
485
                        'id' => 4,
486
                        'modified' => new Time('2017-01-01 11:00:00'),
487
                    ]),
488
                    new Entity([
489
                        'id' => 2,
490
                        'modified' => new Time('2017-01-01 11:00:00'),
491
                    ]),
492
                    new Entity([
493
                        'id' => 5,
494
                        'modified' => new Time('2017-01-01 10:00:00'),
495
                    ]),
496
                ],
497
                [
498
                    'hasPrevious' => null,
499
                    'previousCursor' => null,
500
                    'hasNext' => true,
501
                    'nextCursor' => [
502
                        'Posts.id' => 5,
503
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
504
                    ],
505
                ]
506
            ),
507
        ];
508
509
        yield 'Descending forward inclusive' => [
510
            function () {
511
                return [
512
                    'forward' => true,
513
                    'seekable' => true,
514
                    'limit' => 3,
515
                    'order' => [
516
                        'modified' => 'desc',
517
                        'id' => 'desc',
518
                    ],
519
                    'cursor' => [
520
                        'Posts.id' => 3,
521
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
522
                    ],
523
                ];
524
            },
525
            new PaginationResult(
526
                [
527
                    new Entity([
528
                        'id' => 3,
529
                        'modified' => new Time('2017-01-01 10:00:00'),
530
                    ]),
531
                    new Entity([
532
                        'id' => 1,
533
                        'modified' => new Time('2017-01-01 10:00:00'),
534
                    ]),
535
                ],
536
                [
537
                    'hasPrevious' => true,
538
                    'previousCursor' => [
539
                        'Posts.id' => 5,
540
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
541
                    ],
542
                    'hasNext' => false,
543
                    'nextCursor' => null,
544
                ]
545
            ),
546
        ];
547
548
        yield 'Descending forward exclusive' => [
549
            function () {
550
                return [
551
                    'forward' => true,
552
                    'seekable' => true,
553
                    'exclusive' => true,
554
                    'limit' => 3,
555
                    'order' => [
556
                        'modified' => 'desc',
557
                        'id' => 'desc',
558
                    ],
559
                    'cursor' => [
560
                        'Posts.id' => 3,
561
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
562
                    ],
563
                ];
564
            },
565
            new PaginationResult(
566
                [
567
                    new Entity([
568
                        'id' => 1,
569
                        'modified' => new Time('2017-01-01 10:00:00'),
570
                    ]),
571
                ],
572
                [
573
                    'hasPrevious' => true,
574
                    'previousCursor' => [
575
                        'Posts.id' => 1,
576
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
577
                    ],
578
                    'hasNext' => false,
579
                    'nextCursor' => null,
580
                ]
581
            ),
582
        ];
583
584
        yield 'Descending backward start inclusive' => [
585
            function () {
586
                return [
587
                    'backward' => true,
588
                    'seekable' => true,
589
                    'limit' => 3,
590
                    'order' => [
591
                        'modified' => 'desc',
592
                        'id' => 'desc',
593
                    ],
594
                ];
595
            },
596
            new PaginationResult(
597
                [
598
                    new Entity([
599
                        'id' => 5,
600
                        'modified' => new Time('2017-01-01 10:00:00'),
601
                    ]),
602
                    new Entity([
603
                        'id' => 3,
604
                        'modified' => new Time('2017-01-01 10:00:00'),
605
                    ]),
606
                    new Entity([
607
                        'id' => 1,
608
                        'modified' => new Time('2017-01-01 10:00:00'),
609
                    ]),
610
                ],
611
                [
612
                    'hasPrevious' => true,
613
                    'previousCursor' => [
614
                        'Posts.id' => 2,
615
                        'Posts.modified' => new Time('2017-01-01 11:00:00'),
616
                    ],
617
                    'hasNext' => null,
618
                    'nextCursor' => null,
619
                ]
620
            ),
621
        ];
622
623
        yield 'Descending backward start exclusive' => [
624
            function () {
625
                return [
626
                    'backward' => true,
627
                    'seekable' => true,
628
                    'exclusive' => true,
629
                    'limit' => 3,
630
                    'order' => [
631
                        'modified' => 'desc',
632
                        'id' => 'desc',
633
                    ],
634
                ];
635
            },
636
            new PaginationResult(
637
                [
638
                    new Entity([
639
                        'id' => 5,
640
                        'modified' => new Time('2017-01-01 10:00:00'),
641
                    ]),
642
                    new Entity([
643
                        'id' => 3,
644
                        'modified' => new Time('2017-01-01 10:00:00'),
645
                    ]),
646
                    new Entity([
647
                        'id' => 1,
648
                        'modified' => new Time('2017-01-01 10:00:00'),
649
                    ]),
650
                ],
651
                [
652
                    'hasPrevious' => true,
653
                    'previousCursor' => [
654
                        'Posts.id' => 5,
655
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
656
                    ],
657
                    'hasNext' => null,
658
                    'nextCursor' => null,
659
                ]
660
            ),
661
        ];
662
663
        yield 'Descending backward inclusive' => [
664
            function () {
665
                return [
666
                    'backward' => true,
667
                    'seekable' => true,
668
                    'limit' => 3,
669
                    'order' => [
670
                        'modified' => 'desc',
671
                        'id' => 'desc',
672
                    ],
673
                    'cursor' => [
674
                        'Posts.id' => 3,
675
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
676
                    ],
677
                ];
678
            },
679
            new PaginationResult(
680
                [
681
                    new Entity([
682
                        'id' => 2,
683
                        'modified' => new Time('2017-01-01 11:00:00'),
684
                    ]),
685
                    new Entity([
686
                        'id' => 5,
687
                        'modified' => new Time('2017-01-01 10:00:00'),
688
                    ]),
689
                    new Entity([
690
                        'id' => 3,
691
                        'modified' => new Time('2017-01-01 10:00:00'),
692
                    ]),
693
                ],
694
                [
695
                    'hasPrevious' => true,
696
                    'previousCursor' => [
697
                        'Posts.id' => 4,
698
                        'Posts.modified' => new Time('2017-01-01 11:00:00'),
699
                    ],
700
                    'hasNext' => true,
701
                    'nextCursor' => [
702
                        'Posts.id' => 1,
703
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
704
                    ],
705
                ]
706
            ),
707
        ];
708
709
        yield 'Descending backward exclusive' => [
710
            function () {
711
                return [
712
                    'backward' => true,
713
                    'seekable' => true,
714
                    'exclusive' => true,
715
                    'limit' => 3,
716
                    'order' => [
717
                        'modified' => 'desc',
718
                        'id' => 'desc',
719
                    ],
720
                    'cursor' => [
721
                        'Posts.id' => 3,
722
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
723
                    ],
724
                ];
725
            },
726
            new PaginationResult(
727
                [
728
                    new Entity([
729
                        'id' => 4,
730
                        'modified' => new Time('2017-01-01 11:00:00'),
731
                    ]),
732
                    new Entity([
733
                        'id' => 2,
734
                        'modified' => new Time('2017-01-01 11:00:00'),
735
                    ]),
736
                    new Entity([
737
                        'id' => 5,
738
                        'modified' => new Time('2017-01-01 10:00:00'),
739
                    ]),
740
                ],
741
                [
742
                    'hasPrevious' => false,
743
                    'previousCursor' => null,
744
                    'hasNext' => true,
745
                    'nextCursor' => [
746
                        'Posts.id' => 5,
747
                        'Posts.modified' => new Time('2017-01-01 10:00:00'),
748
                    ],
749
                ]
750
            ),
751
        ];
752
    }
753
754
    public function queryExpressionProvider(): Generator
755
    {
756
        yield 'Ascending forward start inclusive with QueryExpression' => [
757
            function () {
758
                return [
759
                    'forward' => true,
760
                    'seekable' => true,
761
                    'limit' => 3,
762
                    'order' => [
763
                        new OrderClauseExpression('modified', 'asc'),
764
                        new OrderClauseExpression('id', 'asc'),
765
                    ],
766
                ];
767
            },
768
            new PaginationResult(
769
                [
770
                    new Entity([
771
                        'id' => 1,
772
                        'modified' => new Time('2017-01-01 10:00:00'),
773
                    ]),
774
                    new Entity([
775
                        'id' => 3,
776
                        'modified' => new Time('2017-01-01 10:00:00'),
777
                    ]),
778
                    new Entity([
779
                        'id' => 5,
780
                        'modified' => new Time('2017-01-01 10:00:00'),
781
                    ]),
782
                ],
783
                [
784
                    'hasPrevious' => null,
785
                    'previousCursor' => null,
786
                    'hasNext' => true,
787
                    'nextCursor' => [
788
                        'id' => 2,
789
                        'modified' => new Time('2017-01-01 11:00:00'),
790
                    ],
791
                ]
792
            ),
793
        ];
794
795
        yield 'Ascending forward start exclusive with QueryExpression' => [
796
            function () {
797
                return [
798
                    'forward' => true,
799
                    'seekable' => true,
800
                    'exclusive' => true,
801
                    'limit' => 3,
802
                    'order' => [
803
                        new OrderClauseExpression('modified', 'asc'),
804
                        new OrderClauseExpression('id', 'asc'),
805
                    ],
806
                ];
807
            },
808
            new PaginationResult(
809
                [
810
                    new Entity([
811
                        'id' => 1,
812
                        'modified' => new Time('2017-01-01 10:00:00'),
813
                    ]),
814
                    new Entity([
815
                        'id' => 3,
816
                        'modified' => new Time('2017-01-01 10:00:00'),
817
                    ]),
818
                    new Entity([
819
                        'id' => 5,
820
                        'modified' => new Time('2017-01-01 10:00:00'),
821
                    ]),
822
                ],
823
                [
824
                    'hasPrevious' => null,
825
                    'previousCursor' => null,
826
                    'hasNext' => true,
827
                    'nextCursor' => [
828
                        'id' => 5,
829
                        'modified' => new Time('2017-01-01 10:00:00'),
830
                    ],
831
                ]
832
            ),
833
        ];
834
835
        yield 'Ascending forward inclusive with QueryExpression' => [
836
            function () {
837
                return [
838
                    'forward' => true,
839
                    'seekable' => true,
840
                    'limit' => 3,
841
                    'order' => [
842
                        new OrderClauseExpression('modified', 'asc'),
843
                        new OrderClauseExpression('id', 'asc'),
844
                    ],
845
                    'cursor' => [
846
                        'id' => 3,
847
                        'modified' => new Time('2017-01-01 10:00:00'),
848
                    ],
849
                ];
850
            },
851
            new PaginationResult(
852
                [
853
                    new Entity([
854
                        'id' => 3,
855
                        'modified' => new Time('2017-01-01 10:00:00'),
856
                    ]),
857
                    new Entity([
858
                        'id' => 5,
859
                        'modified' => new Time('2017-01-01 10:00:00'),
860
                    ]),
861
                    new Entity([
862
                        'id' => 2,
863
                        'modified' => new Time('2017-01-01 11:00:00'),
864
                    ]),
865
                ],
866
                [
867
                    'hasPrevious' => true,
868
                    'previousCursor' => [
869
                        'id' => 1,
870
                        'modified' => new Time('2017-01-01 10:00:00'),
871
                    ],
872
                    'hasNext' => true,
873
                    'nextCursor' => [
874
                        'id' => 4,
875
                        'modified' => new Time('2017-01-01 11:00:00'),
876
                    ],
877
                ]
878
            ),
879
        ];
880
881
        yield 'Ascending forward exclusive with QueryExpression' => [
882
            function () {
883
                return [
884
                    'forward' => true,
885
                    'seekable' => true,
886
                    'exclusive' => true,
887
                    'limit' => 3,
888
                    'order' => [
889
                        new OrderClauseExpression('modified', 'asc'),
890
                        new OrderClauseExpression('id', 'asc'),
891
                    ],
892
                    'cursor' => [
893
                        'id' => 3,
894
                        'modified' => new Time('2017-01-01 10:00:00'),
895
                    ],
896
                ];
897
            },
898
            new PaginationResult(
899
                [
900
                    new Entity([
901
                        'id' => 5,
902
                        'modified' => new Time('2017-01-01 10:00:00'),
903
                    ]),
904
                    new Entity([
905
                        'id' => 2,
906
                        'modified' => new Time('2017-01-01 11:00:00'),
907
                    ]),
908
                    new Entity([
909
                        'id' => 4,
910
                        'modified' => new Time('2017-01-01 11:00:00'),
911
                    ]),
912
                ],
913
                [
914
                    'hasPrevious' => true,
915
                    'previousCursor' => [
916
                        'id' => 5,
917
                        'modified' => new Time('2017-01-01 10:00:00'),
918
                    ],
919
                    'hasNext' => false,
920
                    'nextCursor' => null,
921
                ]
922
            ),
923
        ];
924
925
        yield 'Ascending backward start inclusive with QueryExpression' => [
926
            function () {
927
                return [
928
                    'backward' => true,
929
                    'seekable' => true,
930
                    'limit' => 3,
931
                    'order' => [
932
                        new OrderClauseExpression('modified', 'asc'),
933
                        new OrderClauseExpression('id', 'asc'),
934
                    ],
935
                ];
936
            },
937
            new PaginationResult(
938
                [
939
                    new Entity([
940
                        'id' => 5,
941
                        'modified' => new Time('2017-01-01 10:00:00'),
942
                    ]),
943
                    new Entity([
944
                        'id' => 2,
945
                        'modified' => new Time('2017-01-01 11:00:00'),
946
                    ]),
947
                    new Entity([
948
                        'id' => 4,
949
                        'modified' => new Time('2017-01-01 11:00:00'),
950
                    ]),
951
                ],
952
                [
953
                    'hasPrevious' => true,
954
                    'previousCursor' => [
955
                        'id' => 3,
956
                        'modified' => new Time('2017-01-01 10:00:00'),
957
                    ],
958
                    'hasNext' => null,
959
                    'nextCursor' => null,
960
                ]
961
            ),
962
        ];
963
964
        yield 'Ascending backward start exclusive with QueryExpression' => [
965
            function () {
966
                return [
967
                    'backward' => true,
968
                    'seekable' => true,
969
                    'exclusive' => true,
970
                    'limit' => 3,
971
                    'order' => [
972
                        new OrderClauseExpression('modified', 'asc'),
973
                        new OrderClauseExpression('id', 'asc'),
974
                    ],
975
                ];
976
            },
977
            new PaginationResult(
978
                [
979
                    new Entity([
980
                        'id' => 5,
981
                        'modified' => new Time('2017-01-01 10:00:00'),
982
                    ]),
983
                    new Entity([
984
                        'id' => 2,
985
                        'modified' => new Time('2017-01-01 11:00:00'),
986
                    ]),
987
                    new Entity([
988
                        'id' => 4,
989
                        'modified' => new Time('2017-01-01 11:00:00'),
990
                    ]),
991
                ],
992
                [
993
                    'hasPrevious' => true,
994
                    'previousCursor' => [
995
                        'id' => 5,
996
                        'modified' => new Time('2017-01-01 10:00:00'),
997
                    ],
998
                    'hasNext' => null,
999
                    'nextCursor' => null,
1000
                ]
1001
            ),
1002
        ];
1003
1004
        yield 'Ascending backward inclusive with QueryExpression' => [
1005
            function () {
1006
                return [
1007
                    'backward' => true,
1008
                    'seekable' => true,
1009
                    'limit' => 3,
1010
                    'order' => [
1011
                        new OrderClauseExpression('modified', 'asc'),
1012
                        new OrderClauseExpression('id', 'asc'),
1013
                    ],
1014
                    'cursor' => [
1015
                        'id' => 3,
1016
                        'modified' => new Time('2017-01-01 10:00:00'),
1017
                    ],
1018
                ];
1019
            },
1020
            new PaginationResult(
1021
                [
1022
                    new Entity([
1023
                        'id' => 1,
1024
                        'modified' => new Time('2017-01-01 10:00:00'),
1025
                    ]),
1026
                    new Entity([
1027
                        'id' => 3,
1028
                        'modified' => new Time('2017-01-01 10:00:00'),
1029
                    ]),
1030
                ],
1031
                [
1032
                    'hasPrevious' => false,
1033
                    'previousCursor' => null,
1034
                    'hasNext' => true,
1035
                    'nextCursor' => [
1036
                        'id' => 5,
1037
                        'modified' => new Time('2017-01-01 10:00:00'),
1038
                    ],
1039
                ]
1040
            ),
1041
        ];
1042
1043
        yield 'Ascending backward exclusive with QueryExpression' => [
1044
            function () {
1045
                return [
1046
                    'backward' => true,
1047
                    'seekable' => true,
1048
                    'exclusive' => true,
1049
                    'limit' => 3,
1050
                    'order' => [
1051
                        new OrderClauseExpression('modified', 'asc'),
1052
                        new OrderClauseExpression('id', 'asc'),
1053
                    ],
1054
                    'cursor' => [
1055
                        'id' => 3,
1056
                        'modified' => new Time('2017-01-01 10:00:00'),
1057
                    ],
1058
                ];
1059
            },
1060
            new PaginationResult(
1061
                [
1062
                    new Entity([
1063
                        'id' => 1,
1064
                        'modified' => new Time('2017-01-01 10:00:00'),
1065
                    ]),
1066
                ],
1067
                [
1068
                    'hasPrevious' => false,
1069
                    'previousCursor' => null,
1070
                    'hasNext' => true,
1071
                    'nextCursor' => [
1072
                        'id' => 1,
1073
                        'modified' => new Time('2017-01-01 10:00:00'),
1074
                    ],
1075
                ]
1076
            ),
1077
        ];
1078
1079
        yield 'Descending forward start inclusive with QueryExpression' => [
1080
            function () {
1081
                return [
1082
                    'forward' => true,
1083
                    'seekable' => true,
1084
                    'limit' => 3,
1085
                    'order' => [
1086
                        new OrderClauseExpression('modified', 'desc'),
1087
                        new OrderClauseExpression('id', 'desc'),
1088
                    ],
1089
                ];
1090
            },
1091
            new PaginationResult(
1092
                [
1093
                    new Entity([
1094
                        'id' => 4,
1095
                        'modified' => new Time('2017-01-01 11:00:00'),
1096
                    ]),
1097
                    new Entity([
1098
                        'id' => 2,
1099
                        'modified' => new Time('2017-01-01 11:00:00'),
1100
                    ]),
1101
                    new Entity([
1102
                        'id' => 5,
1103
                        'modified' => new Time('2017-01-01 10:00:00'),
1104
                    ]),
1105
                ],
1106
                [
1107
                    'hasPrevious' => null,
1108
                    'previousCursor' => null,
1109
                    'hasNext' => true,
1110
                    'nextCursor' => [
1111
                        'id' => 3,
1112
                        'modified' => new Time('2017-01-01 10:00:00'),
1113
                    ],
1114
                ]
1115
            ),
1116
        ];
1117
1118
        yield 'Descending forward start exclusive with QueryExpression' => [
1119
            function () {
1120
                return [
1121
                    'forward' => true,
1122
                    'seekable' => true,
1123
                    'exclusive' => true,
1124
                    'limit' => 3,
1125
                    'order' => [
1126
                        new OrderClauseExpression('modified', 'desc'),
1127
                        new OrderClauseExpression('id', 'desc'),
1128
                    ],
1129
                ];
1130
            },
1131
            new PaginationResult(
1132
                [
1133
                    new Entity([
1134
                        'id' => 4,
1135
                        'modified' => new Time('2017-01-01 11:00:00'),
1136
                    ]),
1137
                    new Entity([
1138
                        'id' => 2,
1139
                        'modified' => new Time('2017-01-01 11:00:00'),
1140
                    ]),
1141
                    new Entity([
1142
                        'id' => 5,
1143
                        'modified' => new Time('2017-01-01 10:00:00'),
1144
                    ]),
1145
                ],
1146
                [
1147
                    'hasPrevious' => null,
1148
                    'previousCursor' => null,
1149
                    'hasNext' => true,
1150
                    'nextCursor' => [
1151
                        'id' => 5,
1152
                        'modified' => new Time('2017-01-01 10:00:00'),
1153
                    ],
1154
                ]
1155
            ),
1156
        ];
1157
1158
        yield 'Descending forward inclusive with QueryExpression' => [
1159
            function () {
1160
                return [
1161
                    'forward' => true,
1162
                    'seekable' => true,
1163
                    'limit' => 3,
1164
                    'order' => [
1165
                        new OrderClauseExpression('modified', 'desc'),
1166
                        new OrderClauseExpression('id', 'desc'),
1167
                    ],
1168
                    'cursor' => [
1169
                        'id' => 3,
1170
                        'modified' => new Time('2017-01-01 10:00:00'),
1171
                    ],
1172
                ];
1173
            },
1174
            new PaginationResult(
1175
                [
1176
                    new Entity([
1177
                        'id' => 3,
1178
                        'modified' => new Time('2017-01-01 10:00:00'),
1179
                    ]),
1180
                    new Entity([
1181
                        'id' => 1,
1182
                        'modified' => new Time('2017-01-01 10:00:00'),
1183
                    ]),
1184
                ],
1185
                [
1186
                    'hasPrevious' => true,
1187
                    'previousCursor' => [
1188
                        'id' => 5,
1189
                        'modified' => new Time('2017-01-01 10:00:00'),
1190
                    ],
1191
                    'hasNext' => false,
1192
                    'nextCursor' => null,
1193
                ]
1194
            ),
1195
        ];
1196
1197
        yield 'Descending forward exclusive with QueryExpression' => [
1198
            function () {
1199
                return [
1200
                    'forward' => true,
1201
                    'seekable' => true,
1202
                    'exclusive' => true,
1203
                    'limit' => 3,
1204
                    'order' => [
1205
                        new OrderClauseExpression('modified', 'desc'),
1206
                        new OrderClauseExpression('id', 'desc'),
1207
                    ],
1208
                    'cursor' => [
1209
                        'id' => 3,
1210
                        'modified' => new Time('2017-01-01 10:00:00'),
1211
                    ],
1212
                ];
1213
            },
1214
            new PaginationResult(
1215
                [
1216
                    new Entity([
1217
                        'id' => 1,
1218
                        'modified' => new Time('2017-01-01 10:00:00'),
1219
                    ]),
1220
                ],
1221
                [
1222
                    'hasPrevious' => true,
1223
                    'previousCursor' => [
1224
                        'id' => 1,
1225
                        'modified' => new Time('2017-01-01 10:00:00'),
1226
                    ],
1227
                    'hasNext' => false,
1228
                    'nextCursor' => null,
1229
                ]
1230
            ),
1231
        ];
1232
1233
        yield 'Descending backward start inclusive with QueryExpression' => [
1234
            function () {
1235
                return [
1236
                    'backward' => true,
1237
                    'seekable' => true,
1238
                    'limit' => 3,
1239
                    'order' => [
1240
                        new OrderClauseExpression('modified', 'desc'),
1241
                        new OrderClauseExpression('id', 'desc'),
1242
                    ],
1243
                ];
1244
            },
1245
            new PaginationResult(
1246
                [
1247
                    new Entity([
1248
                        'id' => 5,
1249
                        'modified' => new Time('2017-01-01 10:00:00'),
1250
                    ]),
1251
                    new Entity([
1252
                        'id' => 3,
1253
                        'modified' => new Time('2017-01-01 10:00:00'),
1254
                    ]),
1255
                    new Entity([
1256
                        'id' => 1,
1257
                        'modified' => new Time('2017-01-01 10:00:00'),
1258
                    ]),
1259
                ],
1260
                [
1261
                    'hasPrevious' => true,
1262
                    'previousCursor' => [
1263
                        'id' => 2,
1264
                        'modified' => new Time('2017-01-01 11:00:00'),
1265
                    ],
1266
                    'hasNext' => null,
1267
                    'nextCursor' => null,
1268
                ]
1269
            ),
1270
        ];
1271
1272
        yield 'Descending backward start exclusive with QueryExpression' => [
1273
            function () {
1274
                return [
1275
                    'backward' => true,
1276
                    'seekable' => true,
1277
                    'exclusive' => true,
1278
                    'limit' => 3,
1279
                    'order' => [
1280
                        new OrderClauseExpression('modified', 'desc'),
1281
                        new OrderClauseExpression('id', 'desc'),
1282
                    ],
1283
                ];
1284
            },
1285
            new PaginationResult(
1286
                [
1287
                    new Entity([
1288
                        'id' => 5,
1289
                        'modified' => new Time('2017-01-01 10:00:00'),
1290
                    ]),
1291
                    new Entity([
1292
                        'id' => 3,
1293
                        'modified' => new Time('2017-01-01 10:00:00'),
1294
                    ]),
1295
                    new Entity([
1296
                        'id' => 1,
1297
                        'modified' => new Time('2017-01-01 10:00:00'),
1298
                    ]),
1299
                ],
1300
                [
1301
                    'hasPrevious' => true,
1302
                    'previousCursor' => [
1303
                        'id' => 5,
1304
                        'modified' => new Time('2017-01-01 10:00:00'),
1305
                    ],
1306
                    'hasNext' => null,
1307
                    'nextCursor' => null,
1308
                ]
1309
            ),
1310
        ];
1311
1312
        yield 'Descending backward inclusive with QueryExpression' => [
1313
            function () {
1314
                return [
1315
                    'backward' => true,
1316
                    'seekable' => true,
1317
                    'limit' => 3,
1318
                    'order' => [
1319
                        new OrderClauseExpression('modified', 'desc'),
1320
                        new OrderClauseExpression('id', 'desc'),
1321
                    ],
1322
                    'cursor' => [
1323
                        'id' => 3,
1324
                        'modified' => new Time('2017-01-01 10:00:00'),
1325
                    ],
1326
                ];
1327
            },
1328
            new PaginationResult(
1329
                [
1330
                    new Entity([
1331
                        'id' => 2,
1332
                        'modified' => new Time('2017-01-01 11:00:00'),
1333
                    ]),
1334
                    new Entity([
1335
                        'id' => 5,
1336
                        'modified' => new Time('2017-01-01 10:00:00'),
1337
                    ]),
1338
                    new Entity([
1339
                        'id' => 3,
1340
                        'modified' => new Time('2017-01-01 10:00:00'),
1341
                    ]),
1342
                ],
1343
                [
1344
                    'hasPrevious' => true,
1345
                    'previousCursor' => [
1346
                        'id' => 4,
1347
                        'modified' => new Time('2017-01-01 11:00:00'),
1348
                    ],
1349
                    'hasNext' => true,
1350
                    'nextCursor' => [
1351
                        'id' => 1,
1352
                        'modified' => new Time('2017-01-01 10:00:00'),
1353
                    ],
1354
                ]
1355
            ),
1356
        ];
1357
1358
        yield 'Descending backward exclusive with QueryExpression' => [
1359
            function () {
1360
                return [
1361
                    'backward' => true,
1362
                    'seekable' => true,
1363
                    'exclusive' => true,
1364
                    'limit' => 3,
1365
                    'order' => [
1366
                        new OrderClauseExpression('modified', 'desc'),
1367
                        new OrderClauseExpression('id', 'desc'),
1368
                    ],
1369
                    'cursor' => [
1370
                        'id' => 3,
1371
                        'modified' => new Time('2017-01-01 10:00:00'),
1372
                    ],
1373
                ];
1374
            },
1375
            new PaginationResult(
1376
                [
1377
                    new Entity([
1378
                        'id' => 4,
1379
                        'modified' => new Time('2017-01-01 11:00:00'),
1380
                    ]),
1381
                    new Entity([
1382
                        'id' => 2,
1383
                        'modified' => new Time('2017-01-01 11:00:00'),
1384
                    ]),
1385
                    new Entity([
1386
                        'id' => 5,
1387
                        'modified' => new Time('2017-01-01 10:00:00'),
1388
                    ]),
1389
                ],
1390
                [
1391
                    'hasPrevious' => false,
1392
                    'previousCursor' => null,
1393
                    'hasNext' => true,
1394
                    'nextCursor' => [
1395
                        'id' => 5,
1396
                        'modified' => new Time('2017-01-01 10:00:00'),
1397
                    ],
1398
                ]
1399
            ),
1400
        ];
1401
    }
1402
}
1403