Passed
Push — master ( a9f887...bd7a1f )
by Chito
02:04
created

QueryTest::orderProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 75
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 50
c 1
b 1
f 0
dl 0
loc 75
rs 9.0909
cc 1
nc 1
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Lampager\Cake\Test\TestCase\ORM;
6
7
use Cake\Database\Expression\OrderClauseExpression;
8
use Cake\I18n\DateTime;
9
use Cake\ORM\Entity;
10
use Cake\ORM\Table;
11
use Cake\ORM\TableRegistry;
12
use Generator;
13
use Lampager\Cake\Model\Behavior\LampagerBehavior;
14
use Lampager\Cake\ORM\Query;
15
use Lampager\Cake\PaginationResult;
16
use Lampager\Cake\Paginator;
17
use Lampager\Cake\Test\TestCase\TestCase;
18
use Lampager\Contracts\Exceptions\LampagerException;
19
use Lampager\Exceptions\Query\BadKeywordException;
20
use Lampager\Exceptions\Query\InsufficientConstraintsException;
21
use Lampager\Exceptions\Query\LimitParameterException;
22
use PHPUnit\Framework\Attributes\DataProvider;
23
use PHPUnit\Framework\MockObject\MockObject;
24
25
class QueryTest extends TestCase
26
{
27
    public array $fixtures = [
28
        'plugin.Lampager\\Cake.Posts',
29
    ];
30
31
    public function setUp(): void
32
    {
33
        parent::setUp();
34
35
        set_error_handler(
36
            static function ($errno, $errstr, $errfile, $errline) {
37
                throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
38
            },
39
            E_ALL
40
        );
41
    }
42
43
    public function tearDown(): void
44
    {
45
        restore_error_handler();
46
47
        parent::tearDown();
48
    }
49
50
    #[DataProvider('orderProvider')]
51
    public function testOrderBy(callable $factory, PaginationResult $expected): void
52
    {
53
        /** @var LampagerBehavior&Table $posts */
54
        $posts = TableRegistry::getTableLocator()->get('Posts');
55
        $posts->addBehavior(LampagerBehavior::class);
56
57
        /** @var Query $query */
58
        $query = $factory($posts);
59
        $this->assertJsonEquals($expected, $query->paginate());
60
    }
61
62
    #[DataProvider('orderProvider')]
63
    public function testOrderClear(callable $factory): void
64
    {
65
        $this->expectException(LampagerException::class);
66
        $this->expectExceptionMessage('At least one order constraint required');
67
68
        /** @var LampagerBehavior&Table $posts */
69
        $posts = TableRegistry::getTableLocator()->get('Posts');
70
        $posts->addBehavior(LampagerBehavior::class);
71
72
        /** @var Query $query */
73
        $query = $factory($posts);
74
        $query->orderBy([], true);
75
        $query->paginate();
76
    }
77
78
    public function testOrderIllegal(): void
79
    {
80
        $this->expectException(BadKeywordException::class);
81
        $this->expectExceptionMessage('OrderClauseExpression does not have direction');
82
83
        /** @var MockObject&OrderClauseExpression $expression */
84
        $expression = $this->getMockBuilder(OrderClauseExpression::class)->disableOriginalConstructor()->getMock();
85
        $expression->method('sql')->willReturn('modified');
86
87
        /** @var LampagerBehavior&Table $posts */
88
        $posts = TableRegistry::getTableLocator()->get('Posts');
89
        $posts->addBehavior(LampagerBehavior::class);
90
        $posts->lampager()
91
            ->orderBy([$expression])
92
            ->paginate();
93
    }
94
95
    public function testOrderQueryExpression(): void
96
    {
97
        /** @var LampagerBehavior&Table $posts */
98
        $posts = TableRegistry::getTableLocator()->get('Posts');
99
        $posts->addBehavior(LampagerBehavior::class);
100
101
        $expected = new PaginationResult(
102
            [
103
                new Entity([
104
                    'id' => 1,
105
                    'modified' => new DateTime('2017-01-01 10:00:00'),
106
                ]),
107
            ],
108
            [
109
                'hasPrevious' => null,
110
                'previousCursor' => null,
111
                'hasNext' => true,
112
                'nextCursor' => [
113
                    'id' => 3,
114
                    'modified' => new DateTime('2017-01-01 10:00:00'),
115
                ],
116
            ]
117
        );
118
119
        $actual = $posts->lampager()
120
            ->orderBy([$posts->selectQuery()->expr('modified')])
121
            ->orderBy([$posts->selectQuery()->expr('id')])
122
            ->limit(1)
123
            ->paginate();
124
125
        $this->assertJsonEquals($expected, $actual);
126
    }
127
128
    public function testLimitQueryExpression(): void
129
    {
130
        /** @var LampagerBehavior&Table $posts */
131
        $posts = TableRegistry::getTableLocator()->get('Posts');
132
        $posts->addBehavior(LampagerBehavior::class);
133
134
        $expected = new PaginationResult(
135
            [
136
                new Entity([
137
                    'id' => 1,
138
                    'modified' => new DateTime('2017-01-01 10:00:00'),
139
                ]),
140
            ],
141
            [
142
                'hasPrevious' => null,
143
                'previousCursor' => null,
144
                'hasNext' => true,
145
                'nextCursor' => [
146
                    'id' => 3,
147
                    'modified' => new DateTime('2017-01-01 10:00:00'),
148
                ],
149
            ]
150
        );
151
152
        $actual = $posts->lampager()
153
            ->orderByAsc('modified')
154
            ->orderByAsc('id')
155
            ->limit($posts->selectQuery()->expr('1'))
156
            ->paginate();
157
158
        $this->assertJsonEquals($expected, $actual);
159
    }
160
161
    public function testLimitIllegalQueryExpression(): void
162
    {
163
        $this->expectException(LimitParameterException::class);
164
        $this->expectExceptionMessage('Limit must be positive integer');
165
166
        /** @var LampagerBehavior&Table $posts */
167
        $posts = TableRegistry::getTableLocator()->get('Posts');
168
        $posts->addBehavior(LampagerBehavior::class);
169
        $posts->lampager()
170
            ->orderByAsc('modified')
171
            ->orderByAsc('id')
172
            ->limit($posts->selectQuery()->expr('1 + 1'))
173
            ->paginate();
174
    }
175
176
    public function testWhere(): void
177
    {
178
        /** @var LampagerBehavior&Table $posts */
179
        $posts = TableRegistry::getTableLocator()->get('Posts');
180
        $posts->addBehavior(LampagerBehavior::class);
181
182
        $expected = new PaginationResult(
183
            [
184
                new Entity([
185
                    'id' => 3,
186
                    'modified' => new DateTime('2017-01-01 10:00:00'),
187
                ]),
188
            ],
189
            [
190
                'hasPrevious' => null,
191
                'previousCursor' => null,
192
                'hasNext' => true,
193
                'nextCursor' => [
194
                    'id' => 5,
195
                    'modified' => new DateTime('2017-01-01 10:00:00'),
196
                ],
197
            ]
198
        );
199
200
        $actual = $posts->lampager()
201
            ->where(['id >' => 1])
202
            ->orderByAsc('modified')
203
            ->orderByAsc('id')
204
            ->limit(1)
205
            ->paginate();
206
207
        $this->assertJsonEquals($expected, $actual);
208
    }
209
210
    public function testGroup(): void
211
    {
212
        $this->expectException(InsufficientConstraintsException::class);
213
        $this->expectExceptionMessage('group()/union() are not supported');
214
215
        /** @var LampagerBehavior&Table $posts */
216
        $posts = TableRegistry::getTableLocator()->get('Posts');
217
        $posts->addBehavior(LampagerBehavior::class);
218
        $posts->lampager()
219
            ->orderByAsc('modified')
220
            ->orderByAsc('id')
221
            ->groupBy('modified')
222
            ->paginate();
223
    }
224
225
    public function testUnion(): void
226
    {
227
        $this->expectException(InsufficientConstraintsException::class);
228
        $this->expectExceptionMessage('group()/union() are not supported');
229
230
        /** @var LampagerBehavior&Table $posts */
231
        $posts = TableRegistry::getTableLocator()->get('Posts');
232
        $posts->addBehavior(LampagerBehavior::class);
233
        $posts->lampager()
234
            ->orderByAsc('modified')
235
            ->orderByAsc('id')
236
            ->union($posts->selectQuery()->select())
237
            ->paginate();
238
    }
239
240
    public function testCall(): void
241
    {
242
        $this->expectException(\BadMethodCallException::class);
243
        $this->expectExceptionMessage('Method Lampager\Cake\ORM\Query::take does not exist');
244
245
        /** @var LampagerBehavior&Table $posts */
246
        $posts = TableRegistry::getTableLocator()->get('Posts');
247
        $posts->addBehavior(LampagerBehavior::class);
248
        $posts->lampager()
249
            ->orderByAsc('id')
250
            ->take();
251
    }
252
253
    public function testDebugInfo(): void
254
    {
255
        /** @var LampagerBehavior&Table $posts */
256
        $posts = TableRegistry::getTableLocator()->get('Posts');
257
        $posts->addBehavior(LampagerBehavior::class);
258
259
        $actual = $posts->lampager()
260
            ->orderByAsc('modified')
261
            ->orderByAsc('id')
262
            ->limit(3)
263
            ->__debugInfo();
264
265
        $this->assertSame('This is a Lampager Query object to get the paginated results.', $actual['(help)']);
266
        $this->assertInstanceOf(Paginator::class, $actual['paginator']);
267
        $this->assertTextStartsWith('SELECT ', $actual['sql']);
268
        $this->assertSame($posts, $actual['repository']);
269
270
        $this->assertArrayHasKey('params', $actual);
271
        $this->assertArrayHasKey('defaultTypes', $actual);
272
        $this->assertArrayHasKey('decorators', $actual);
273
        $this->assertArrayHasKey('executed', $actual);
274
        $this->assertArrayHasKey('hydrate', $actual);
275
        $this->assertArrayHasKey('formatters', $actual);
276
        $this->assertArrayHasKey('mapReducers', $actual);
277
        $this->assertArrayHasKey('contain', $actual);
278
        $this->assertArrayHasKey('matching', $actual);
279
        $this->assertArrayHasKey('extraOptions', $actual);
280
    }
281
282
    public function testDebugInfoIncomplete(): void
283
    {
284
        /** @var LampagerBehavior&Table $posts */
285
        $posts = TableRegistry::getTableLocator()->get('Posts');
286
        $posts->addBehavior(LampagerBehavior::class);
287
288
        $actual = $posts->lampager()
289
            ->limit(3)
290
            ->__debugInfo();
291
292
        $this->assertSame('This is a Lampager Query object to get the paginated results.', $actual['(help)']);
293
        $this->assertInstanceOf(Paginator::class, $actual['paginator']);
294
        $this->assertSame('SQL could not be generated for this query as it is incomplete: At least one order constraint required', $actual['sql']);
295
        $this->assertSame($posts, $actual['repository']);
296
297
        $this->assertArrayHasKey('params', $actual);
298
        $this->assertArrayHasKey('defaultTypes', $actual);
299
        $this->assertArrayHasKey('decorators', $actual);
300
        $this->assertArrayHasKey('executed', $actual);
301
        $this->assertArrayHasKey('hydrate', $actual);
302
        $this->assertArrayHasKey('formatters', $actual);
303
        $this->assertArrayHasKey('mapReducers', $actual);
304
        $this->assertArrayHasKey('contain', $actual);
305
        $this->assertArrayHasKey('matching', $actual);
306
        $this->assertArrayHasKey('extraOptions', $actual);
307
    }
308
309
    #[DataProvider('countProvider')]
310
    public function testCount(callable $factory, int $expected): void
311
    {
312
        /** @var LampagerBehavior&Table $posts */
313
        $posts = TableRegistry::getTableLocator()->get('Posts');
314
        $posts->addBehavior(LampagerBehavior::class);
315
316
        $this->assertSame($expected, $factory($posts));
317
    }
318
319
    public static function orderProvider(): Generator
320
    {
321
        yield 'Ascending and ascending' => [
322
            function (Table $posts) {
323
                /** @var LampagerBehavior&Table $posts */
324
                return $posts->lampager()
325
                    ->forward()
326
                    ->seekable()
327
                    ->limit(3)
328
                    ->orderBy([
329
                        'modified' => 'asc',
330
                        'id' => 'asc',
331
                    ]);
332
            },
333
            new PaginationResult(
334
                [
335
                    new Entity([
336
                        'id' => 1,
337
                        'modified' => new DateTime('2017-01-01 10:00:00'),
338
                    ]),
339
                    new Entity([
340
                        'id' => 3,
341
                        'modified' => new DateTime('2017-01-01 10:00:00'),
342
                    ]),
343
                    new Entity([
344
                        'id' => 5,
345
                        'modified' => new DateTime('2017-01-01 10:00:00'),
346
                    ]),
347
                ],
348
                [
349
                    'hasPrevious' => null,
350
                    'previousCursor' => null,
351
                    'hasNext' => true,
352
                    'nextCursor' => [
353
                        'id' => 2,
354
                        'modified' => new DateTime('2017-01-01 11:00:00'),
355
                    ],
356
                ]
357
            ),
358
        ];
359
360
        yield 'Descending and descending' => [
361
            function (Table $posts) {
362
                /** @var LampagerBehavior&Table $posts */
363
                return $posts->lampager()
364
                    ->forward()
365
                    ->seekable()
366
                    ->limit(3)
367
                    ->orderBy([
368
                        'modified' => 'desc',
369
                        'id' => 'desc',
370
                    ]);
371
            },
372
            new PaginationResult(
373
                [
374
                    new Entity([
375
                        'id' => 4,
376
                        'modified' => new DateTime('2017-01-01 11:00:00'),
377
                    ]),
378
                    new Entity([
379
                        'id' => 2,
380
                        'modified' => new DateTime('2017-01-01 11:00:00'),
381
                    ]),
382
                    new Entity([
383
                        'id' => 5,
384
                        'modified' => new DateTime('2017-01-01 10:00:00'),
385
                    ]),
386
                ],
387
                [
388
                    'hasPrevious' => null,
389
                    'previousCursor' => null,
390
                    'hasNext' => true,
391
                    'nextCursor' => [
392
                        'id' => 3,
393
                        'modified' => new DateTime('2017-01-01 10:00:00'),
394
                    ],
395
                ]
396
            ),
397
        ];
398
    }
399
400
    public static function countProvider(): Generator
401
    {
402
        yield 'Ascending forward start inclusive' => [
403
            function (Table $posts) {
404
                /** @var LampagerBehavior&Table $posts */
405
                return $posts->lampager()
406
                    ->forward()
407
                    ->seekable()
408
                    ->limit(3)
409
                    ->orderByAsc('modified')
410
                    ->orderByAsc('id')
411
                    ->count();
412
            },
413
            3,
414
        ];
415
416
        yield 'Ascending forward start exclusive' => [
417
            function (Table $posts) {
418
                /** @var LampagerBehavior&Table $posts */
419
                return $posts->lampager()
420
                    ->forward()
421
                    ->seekable()
422
                    ->exclusive()
423
                    ->limit(3)
424
                    ->orderByAsc('modified')
425
                    ->orderByAsc('id')
426
                    ->count();
427
            },
428
            3,
429
        ];
430
431
        yield 'Ascending forward inclusive' => [
432
            function (Table $posts) {
433
                /** @var LampagerBehavior&Table $posts */
434
                return $posts->lampager()
435
                    ->forward()
436
                    ->seekable()
437
                    ->limit(3)
438
                    ->orderByAsc('modified')
439
                    ->orderByAsc('id')
440
                    ->cursor([
441
                        'id' => 3,
442
                        'modified' => new DateTime('2017-01-01 10:00:00'),
443
                    ])
444
                    ->count();
445
            },
446
            3,
447
        ];
448
449
        yield 'Ascending forward exclusive' => [
450
            function (Table $posts) {
451
                /** @var LampagerBehavior&Table $posts */
452
                return $posts->lampager()
453
                    ->forward()
454
                    ->seekable()
455
                    ->exclusive()
456
                    ->limit(3)
457
                    ->orderByAsc('modified')
458
                    ->orderByAsc('id')
459
                    ->cursor([
460
                        'id' => 3,
461
                        'modified' => new DateTime('2017-01-01 10:00:00'),
462
                    ])
463
                    ->count();
464
            },
465
            3,
466
        ];
467
468
        yield 'Ascending backward start inclusive' => [
469
            function (Table $posts) {
470
                /** @var LampagerBehavior&Table $posts */
471
                return $posts->lampager()
472
                    ->backward()
473
                    ->seekable()
474
                    ->limit(3)
475
                    ->orderByAsc('modified')
476
                    ->orderByAsc('id')
477
                    ->count();
478
            },
479
            3,
480
        ];
481
482
        yield 'Ascending backward start exclusive' => [
483
            function (Table $posts) {
484
                /** @var LampagerBehavior&Table $posts */
485
                return $posts->lampager()
486
                    ->backward()
487
                    ->seekable()
488
                    ->exclusive()
489
                    ->limit(3)
490
                    ->orderByAsc('modified')
491
                    ->orderByAsc('id')
492
                    ->count();
493
            },
494
            3,
495
        ];
496
497
        yield 'Ascending backward inclusive' => [
498
            function (Table $posts) {
499
                /** @var LampagerBehavior&Table $posts */
500
                return $posts->lampager()
501
                    ->backward()
502
                    ->seekable()
503
                    ->limit(3)
504
                    ->orderByAsc('modified')
505
                    ->orderByAsc('id')
506
                    ->cursor([
507
                        'id' => 3,
508
                        'modified' => new DateTime('2017-01-01 10:00:00'),
509
                    ])
510
                    ->count();
511
            },
512
            2,
513
        ];
514
515
        yield 'Ascending backward exclusive' => [
516
            function (Table $posts) {
517
                /** @var LampagerBehavior&Table $posts */
518
                return $posts->lampager()
519
                    ->backward()
520
                    ->seekable()
521
                    ->exclusive()
522
                    ->limit(3)
523
                    ->orderByAsc('modified')
524
                    ->orderByAsc('id')
525
                    ->cursor([
526
                        'id' => 3,
527
                        'modified' => new DateTime('2017-01-01 10:00:00'),
528
                    ])
529
                    ->count();
530
            },
531
            1,
532
        ];
533
534
        yield 'Descending forward start inclusive' => [
535
            function (Table $posts) {
536
                /** @var LampagerBehavior&Table $posts */
537
                return $posts->lampager()
538
                    ->forward()
539
                    ->seekable()
540
                    ->limit(3)
541
                    ->orderByDesc('modified')
542
                    ->orderByDesc('id')
543
                    ->count();
544
            },
545
            3,
546
        ];
547
548
        yield 'Descending forward start exclusive' => [
549
            function (Table $posts) {
550
                /** @var LampagerBehavior&Table $posts */
551
                return $posts->lampager()
552
                    ->forward()
553
                    ->seekable()
554
                    ->exclusive()
555
                    ->limit(3)
556
                    ->orderByDesc('modified')
557
                    ->orderByDesc('id')
558
                    ->count();
559
            },
560
            3,
561
        ];
562
563
        yield 'Descending forward inclusive' => [
564
            function (Table $posts) {
565
                /** @var LampagerBehavior&Table $posts */
566
                return $posts->lampager()
567
                    ->forward()
568
                    ->seekable()
569
                    ->limit(3)
570
                    ->orderByDesc('modified')
571
                    ->orderByDesc('id')
572
                    ->cursor([
573
                        'id' => 3,
574
                        'modified' => new DateTime('2017-01-01 10:00:00'),
575
                    ])
576
                    ->count();
577
            },
578
            2,
579
        ];
580
581
        yield 'Descending forward exclusive' => [
582
            function (Table $posts) {
583
                /** @var LampagerBehavior&Table $posts */
584
                return $posts->lampager()
585
                    ->forward()
586
                    ->seekable()
587
                    ->exclusive()
588
                    ->limit(3)
589
                    ->orderByDesc('modified')
590
                    ->orderByDesc('id')
591
                    ->cursor([
592
                        'id' => 3,
593
                        'modified' => new DateTime('2017-01-01 10:00:00'),
594
                    ])
595
                    ->count();
596
            },
597
            1,
598
        ];
599
600
        yield 'Descending backward start inclusive' => [
601
            function (Table $posts) {
602
                /** @var LampagerBehavior&Table $posts */
603
                return $posts->lampager()
604
                    ->backward()
605
                    ->seekable()
606
                    ->limit(3)
607
                    ->orderByDesc('modified')
608
                    ->orderByDesc('id')
609
                    ->count();
610
            },
611
            3,
612
        ];
613
614
        yield 'Descending backward start exclusive' => [
615
            function (Table $posts) {
616
                /** @var LampagerBehavior&Table $posts */
617
                return $posts->lampager()
618
                    ->backward()
619
                    ->seekable()
620
                    ->exclusive()
621
                    ->limit(3)
622
                    ->orderByDesc('modified')
623
                    ->orderByDesc('id')
624
                    ->count();
625
            },
626
            3,
627
        ];
628
629
        yield 'Descending backward inclusive' => [
630
            function (Table $posts) {
631
                /** @var LampagerBehavior&Table $posts */
632
                return $posts->lampager()
633
                    ->backward()
634
                    ->seekable()
635
                    ->limit(3)
636
                    ->orderByDesc('modified')
637
                    ->orderByDesc('id')
638
                    ->cursor([
639
                        'id' => 3,
640
                        'modified' => new DateTime('2017-01-01 10:00:00'),
641
                    ])
642
                    ->count();
643
            },
644
            3,
645
        ];
646
647
        yield 'Descending backward exclusive' => [
648
            function (Table $posts) {
649
                /** @var LampagerBehavior&Table $posts */
650
                return $posts->lampager()
651
                    ->backward()
652
                    ->seekable()
653
                    ->exclusive()
654
                    ->limit(3)
655
                    ->orderByDesc('modified')
656
                    ->orderByDesc('id')
657
                    ->cursor([
658
                        'id' => 3,
659
                        'modified' => new DateTime('2017-01-01 10:00:00'),
660
                    ])
661
                    ->count();
662
            },
663
            3,
664
        ];
665
    }
666
}
667