Passed
Push — master ( c18fa9...3960b6 )
by Eric
01:48
created

PaginatorTest::testPaginateLowVolume()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 77
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 51
c 2
b 0
f 0
nc 1
nop 0
dl 0
loc 77
rs 9.069

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
/**
6
 * This file is part of Esi\Pagination.
7
 *
8
 * Copyright (C) Eric Sizemore <https://www.secondversion.com/>.
9
 * Copyright (c) Ashley Dawson <[email protected]>.
10
 *
11
 * This source file is subject to the MIT license. For the full copyright,
12
 * license information, and credits/acknowledgements, please view the LICENSE
13
 * and README files that were distributed with this source code.
14
 */
15
/**
16
 * Esi\Pagination is a fork of AshleyDawson\SimplePagination (https://github.com/AshleyDawson/SimplePagination) which is:
17
 *     Copyright (c) 2015-2019 Ashley Dawson
18
 *
19
 * For a list of changes made in Esi\Pagination in comparison to the original library {@see CHANGELOG.md}.
20
 */
21
22
namespace Esi\Pagination\Tests;
23
24
use ArrayIterator;
25
use Esi\Pagination\Exception\CallbackNotFoundException;
26
use Esi\Pagination\Exception\InvalidPageNumberException;
27
use Esi\Pagination\Pagination;
28
use Esi\Pagination\Paginator;
29
use PDO;
30
use PDOStatement;
31
use PHPUnit\Framework\Attributes\CoversClass;
32
use PHPUnit\Framework\Attributes\UsesClass;
33
use PHPUnit\Framework\TestCase;
34
35
use function array_merge;
36
use function range;
37
use function sprintf;
38
39
/**
40
 * @internal
41
 */
42
#[CoversClass(Paginator::class)]
43
#[CoversClass(Pagination::class)]
44
#[UsesClass(CallbackNotFoundException::class)]
45
#[UsesClass(InvalidPageNumberException::class)]
46
class PaginatorTest extends TestCase
47
{
48
    /**
49
     * Paginator object used throughout testing.
50
     */
51
    protected Paginator $paginator;
52
53
    /**
54
     * PDO_SQLITE object for the database testing.
55
     */
56
    protected static PDO $dbObj;
57
58
    /**
59
     * Creates our Paginator and PDO objects.
60
     */
61
    protected function setUp(): void
62
    {
63
        parent::setUp();
64
65
        $this->paginator = new Paginator();
66
        self::$dbObj     = new PDO(sprintf('sqlite:%s/fixtures/factbook.db', __DIR__));
67
    }
68
69
    public function testBeforeAndAfterQueryCallbacks(): void
70
    {
71
        $items = range(0, 27);
72
73
        $paginator = new Paginator([
74
            'itemTotalCallback' => static fn (): int => \count($items),
75
            'sliceCallback'     => static fn (int $offset, int $length): array => \array_slice($items, $offset, $length),
76
            'itemsPerPage'      => 10,
77
            'pagesInRange'      => 5,
78
        ]);
79
80
        $beforeQueryFired = false;
81
        $paginator->setBeforeQueryCallback(static function () use (&$beforeQueryFired): void {
82
            $beforeQueryFired = true;
83
        });
84
85
        $afterQueryFired = false;
86
        $paginator->setAfterQueryCallback(static function () use (&$afterQueryFired): void {
87
            $afterQueryFired = true;
88
        });
89
90
        self::assertFalse($beforeQueryFired);
91
        self::assertFalse($afterQueryFired);
92
93
        $paginator->paginate();
94
95
        self::assertTrue($beforeQueryFired);
96
        self::assertTrue($afterQueryFired);
97
98
        $beforeCallback = $paginator->getBeforeQueryCallback();
99
        $afterCallback  = $paginator->getAfterQueryCallback();
100
101
        self::assertInstanceOf(\Closure::class, $beforeCallback);
102
        self::assertInstanceOf(\Closure::class, $afterCallback);
103
104
        self::assertNull($beforeCallback());
105
        self::assertNull($afterCallback());
106
    }
107
108
    public function testBeforeAndAfterQueryCallbacksZeroPageNumber(): void
109
    {
110
        $items = range(0, 27);
111
112
        $paginator = new Paginator([
113
            'itemTotalCallback' => static fn (): int => \count($items),
114
            'sliceCallback'     => static fn (int $offset, int $length): array => \array_slice($items, $offset, $length),
115
            'itemsPerPage'      => 10,
116
            'pagesInRange'      => 5,
117
        ]);
118
119
        $beforeQueryFired = false;
120
        $paginator->setBeforeQueryCallback(static function () use (&$beforeQueryFired): void {
121
            $beforeQueryFired = true;
122
        });
123
124
        $afterQueryFired = false;
125
        $paginator->setAfterQueryCallback(static function () use (&$afterQueryFired): void {
126
            $afterQueryFired = true;
127
        });
128
129
        self::assertFalse($beforeQueryFired);
130
        self::assertFalse($afterQueryFired);
131
132
        $this->expectException(InvalidPageNumberException::class);
133
        $paginator->paginate(0);
134
    }
135
136
    /**
137
     */
138
    public function testConstructionWithInvalidConfig(): void
139
    {
140
        $paginator = new Paginator([
141
            'itemTotalCallback' => '',
142
            'sliceCallback'     => '',
143
            'itemsPerPage'      => '',
144
            'pagesInRange'      => '',
145
            'nonexistent'       => '',
146
        ]);
147
148
        self::assertNull($paginator->getItemTotalCallback());
149
        self::assertNull($paginator->getSliceCallback());
150
        self::assertSame(10, $paginator->getItemsPerPage());
151
        self::assertSame(5, $paginator->getPagesInRange());
152
    }
153
154
    public function testItemTotalCallbackNotFound(): void
155
    {
156
        $this->paginator->setItemsPerPage(10)->setPagesInRange(5);
157
158
        $this->expectException(CallbackNotFoundException::class);
159
        $this->paginator->setItemTotalCallback(null);
160
        $this->paginator->setSliceCallback(static fn (): string => 'slice_callback');
161
        $this->paginator->paginate();
162
    }
163
164
    /**
165
     * Test pagination of database results. This test uses PDO and a SQLite db, though this is perfectly
166
     * valid for MySQL, etc. as well.
167
     *
168
     * Uses factbook.db, which is licensed under the CC0-1.0 (public domain).
169
     *
170
     * @see https://github.com/factbook/factbook.sql/releases
171
     * @see ../fixtures/factbook.db
172
     */
173
    public function testPaginateDbResults(): void
174
    {
175
        $paginator = new Paginator();
176
        $paginator
177
            ->setItemsPerPage(10)
178
            ->setPagesInRange(5);
179
180
        $paginator->setItemTotalCallback(static function (): int {
181
            /** @var PDOStatement $result */
182
            $result = self::$dbObj->query("SELECT COUNT(*) as totalCount FROM facts");
183
            /** @var string $row */
184
            $row    = $result->fetchColumn();
185
186
            return (int) $row;
187
        });
188
189
        // Pass our slice callback.
190
        $paginator->setSliceCallback(static function (int $offset, int $length): array {
191
            /** @var PDOStatement $result */
192
            $result     = self::$dbObj->query(sprintf('SELECT name, area FROM facts ORDER BY area DESC LIMIT %d, %d', $offset, $length), PDO::FETCH_ASSOC);
193
            $collection = [];
194
195
            foreach ($result as $row) {
196
                $collection[] = $row;
197
            }
198
199
            return $collection;
200
        });
201
202
        $pagination = $paginator->paginate();
203
204
        self::assertNotEmpty($pagination->getItems());
205
        self::assertSame(261, $pagination->getTotalNumberOfItems());
206
        self::assertSame([
207
            0 => [
208
                'name' => 'Russia',
209
                'area' => 17098242,
210
            ],
211
            1 => [
212
                'name' => 'Canada',
213
                'area' => 9984670,
214
            ],
215
            2 => [
216
                'name' => 'United States',
217
                'area' => 9826675,
218
            ],
219
            3 => [
220
                'name' => 'China',
221
                'area' => 9596960,
222
            ],
223
            4 => [
224
                'name' => 'Brazil',
225
                'area' => 8515770,
226
            ],
227
            5 => [
228
                'name' => 'Australia',
229
                'area' => 7741220,
230
            ],
231
            6 => [
232
                'name' => 'European Union',
233
                'area' => 4324782,
234
            ],
235
            7 => [
236
                'name' => 'India',
237
                'area' => 3287263,
238
            ],
239
            8 => [
240
                'name' => 'Argentina',
241
                'area' => 2780400,
242
            ],
243
            9 => [
244
                'name' => 'Kazakhstan',
245
                'area' => 2724900,
246
            ],
247
        ], $pagination->getItems());
248
249
        self::assertSame([
250
            0 => 1,
251
            1 => 2,
252
            2 => 3,
253
            3 => 4,
254
            4 => 5,
255
        ], $pagination->getPages());
256
257
        // Paginate the item collection, passing the current page number (e.g. from the current request).
258
        $pagination = $paginator->paginate(3);
259
260
        self::assertNotEmpty($pagination->getItems());
261
        self::assertSame([
262
            0 => [
263
                'name' => 'Peru',
264
                'area' => 1285216,
265
            ],
266
            1 => [
267
                'name' => 'Angola',
268
                'area' => 1246700,
269
            ],
270
            2 => [
271
                'name' => 'Mali',
272
                'area' => 1240192,
273
            ],
274
            3 => [
275
                'name' => 'South Africa',
276
                'area' => 1219090,
277
            ],
278
            4 => [
279
                'name' => 'Colombia',
280
                'area' => 1138910,
281
            ],
282
            5 => [
283
                'name' => 'Ethiopia',
284
                'area' => 1104300,
285
            ],
286
            6 => [
287
                'name' => 'Bolivia',
288
                'area' => 1098581,
289
            ],
290
            7 => [
291
                'name' => 'Mauritania',
292
                'area' => 1030700,
293
            ],
294
            8 => [
295
                'name' => 'Egypt',
296
                'area' => 1001450,
297
            ],
298
            9 => [
299
                'name' => 'Tanzania',
300
                'area' => 947300,
301
            ],
302
        ], $pagination->getItems());
303
304
        self::assertSame([
305
            0 => 1,
306
            1 => 2,
307
            2 => 3,
308
            3 => 4,
309
            4 => 5,
310
        ], $pagination->getPages());
311
312
        $pagination = $paginator->paginate(6);
313
314
        self::assertNotEmpty($pagination->getItems());
315
        self::assertSame([
316
            0 => [
317
                'name' => 'Spain',
318
                'area' => 505370,
319
            ],
320
            1 => [
321
                'name' => 'Turkmenistan',
322
                'area' => 488100,
323
            ],
324
            2 => [
325
                'name' => 'Cameroon',
326
                'area' => 475440,
327
            ],
328
            3 => [
329
                'name' => 'Papua New Guinea',
330
                'area' => 462840,
331
            ],
332
            4 => [
333
                'name' => 'Sweden',
334
                'area' => 450295,
335
            ],
336
            5 => [
337
                'name' => 'Uzbekistan',
338
                'area' => 447400,
339
            ],
340
            6 => [
341
                'name' => 'Morocco',
342
                'area' => 446550,
343
            ],
344
            7 => [
345
                'name' => 'Iraq',
346
                'area' => 438317,
347
            ],
348
            8 => [
349
                'name' => 'Paraguay',
350
                'area' => 406752,
351
            ],
352
            9 => [
353
                'name' => 'Zimbabwe',
354
                'area' => 390757,
355
            ],
356
        ], $pagination->getItems());
357
358
        self::assertSame([
359
            0 => 4,
360
            1 => 5,
361
            2 => 6,
362
            3 => 7,
363
            4 => 8,
364
        ], $pagination->getPages());
365
366
        $pagination = $paginator->paginate(50);
367
        self::assertCount(0, $pagination->getItems());
368
    }
369
370
    public function testPaginateFailZeroPageNumber(): void
371
    {
372
        $this->expectException(InvalidPageNumberException::class);
373
        $this->expectException(CallbackNotFoundException::class);
374
        $this->paginator->paginate(0);
375
    }
376
377
    public function testPaginateHighVolume(): void
378
    {
379
        $items = range(0, 293832);
380
381
        $this->paginator->setItemsPerPage(10)->setPagesInRange(5);
382
383
        $this->paginator->setItemTotalCallback(static function (Pagination $pagination) use ($items): int {
384
            $pagination->setMeta(['meta_3']);
385
386
            return \count($items);
387
        });
388
389
        $this->paginator->setSliceCallback(static function (int $offset, int $length, Pagination $pagination) use ($items): array {
390
            $pagination->setMeta(array_merge($pagination->getMeta(), ['meta_4']));
391
392
            return \array_slice($items, $offset, $length);
393
        });
394
395
        $pagination = $this->paginator->paginate();
396
397
        self::assertContains('meta_3', $pagination->getMeta());
398
        self::assertContains('meta_4', $pagination->getMeta());
399
400
        self::assertCount(10, $pagination->getItems());
401
        self::assertCount(5, $pagination->getPages());
402
403
        self::assertSame(29384, $pagination->getTotalNumberOfPages());
404
        self::assertSame(1, $pagination->getCurrentPageNumber());
405
        self::assertSame(1, $pagination->getFirstPageNumber());
406
        self::assertSame(29384, $pagination->getLastPageNumber());
407
408
        self::assertNull($pagination->getPreviousPageNumber());
409
410
        self::assertSame(2, $pagination->getNextPageNumber());
411
        self::assertSame(10, $pagination->getItemsPerPage());
412
        self::assertSame(293833, $pagination->getTotalNumberOfItems());
413
        self::assertSame(1, $pagination->getFirstPageNumberInRange());
414
        self::assertSame(5, $pagination->getLastPageNumberInRange());
415
416
        // Move to random page
417
        $pagination = $this->paginator->paginate(4573);
418
419
        self::assertCount(10, $pagination->getItems());
420
        self::assertCount(5, $pagination->getPages());
421
422
        self::assertSame(29384, $pagination->getTotalNumberOfPages());
423
        self::assertSame(4573, $pagination->getCurrentPageNumber());
424
        self::assertSame(1, $pagination->getFirstPageNumber());
425
        self::assertSame(29384, $pagination->getLastPageNumber());
426
        self::assertSame(4572, $pagination->getPreviousPageNumber());
427
        self::assertSame(4574, $pagination->getNextPageNumber());
428
        self::assertSame(10, $pagination->getItemsPerPage());
429
        self::assertSame(293833, $pagination->getTotalNumberOfItems());
430
        self::assertSame(4571, $pagination->getFirstPageNumberInRange());
431
        self::assertSame(4575, $pagination->getLastPageNumberInRange());
432
433
        // Move to last page
434
        $pagination = $this->paginator->paginate(29384);
435
436
        self::assertCount(3, $pagination->getItems());
437
        self::assertCount(5, $pagination->getPages());
438
439
        self::assertSame(29384, $pagination->getTotalNumberOfPages());
440
        self::assertSame(29384, $pagination->getCurrentPageNumber());
441
        self::assertSame(1, $pagination->getFirstPageNumber());
442
        self::assertSame(29384, $pagination->getLastPageNumber());
443
        self::assertSame(29383, $pagination->getPreviousPageNumber());
444
445
        self::assertNull($pagination->getNextPageNumber());
446
447
        self::assertSame(10, $pagination->getItemsPerPage());
448
        self::assertSame(293833, $pagination->getTotalNumberOfItems());
449
        self::assertSame(29380, $pagination->getFirstPageNumberInRange());
450
        self::assertSame(29384, $pagination->getLastPageNumberInRange());
451
452
        self::assertContains('meta_3', $pagination->getMeta());
453
        self::assertContains('meta_4', $pagination->getMeta());
454
    }
455
456
    public function testPaginateItemsPerPageNegativeOne(): void
457
    {
458
        $items = range(0, 1000);
459
460
        $this->paginator->setItemsPerPage(-1)->setPagesInRange(5);
461
462
        $this->paginator->setItemTotalCallback(static function (Pagination $pagination) use ($items): int {
463
            $pagination->setMeta(['meta_3']);
464
465
            return \count($items);
466
        });
467
468
        $this->paginator->setSliceCallback(static function (int $offset, int $length, Pagination $pagination) use ($items): array {
469
            $pagination->setMeta(array_merge($pagination->getMeta(), ['meta_4']));
470
471
            return \array_slice($items, $offset, $length);
472
        });
473
474
        $pagination = $this->paginator->paginate();
475
476
        self::assertContains('meta_3', $pagination->getMeta());
477
        self::assertContains('meta_4', $pagination->getMeta());
478
479
        self::assertCount(1001, $pagination->getItems());
480
        self::assertCount(1003, $pagination->getPages());
481
482
        self::assertSame(-1001, $pagination->getTotalNumberOfPages());
483
        self::assertSame(1, $pagination->getCurrentPageNumber());
484
        self::assertSame(1, $pagination->getFirstPageNumber());
485
        self::assertSame(-1001, $pagination->getLastPageNumber());
486
487
        self::assertNull($pagination->getPreviousPageNumber());
488
489
        self::assertNull($pagination->getNextPageNumber());
490
        self::assertSame(-1, $pagination->getItemsPerPage());
491
        self::assertSame(1001, $pagination->getTotalNumberOfItems());
492
        self::assertSame(-1001, $pagination->getFirstPageNumberInRange());
493
        self::assertSame(1, $pagination->getLastPageNumberInRange());
494
495
        // Move to random page
496
        $pagination = $this->paginator->paginate(567);
497
498
        self::assertCount(1001, $pagination->getItems());
499
        self::assertCount(1003, $pagination->getPages());
500
501
        self::assertSame(-1001, $pagination->getTotalNumberOfPages());
502
        self::assertSame(567, $pagination->getCurrentPageNumber());
503
        self::assertSame(1, $pagination->getFirstPageNumber());
504
        self::assertSame(-1001, $pagination->getLastPageNumber());
505
        self::assertSame(566, $pagination->getPreviousPageNumber());
506
        self::assertNull($pagination->getNextPageNumber());
507
        self::assertSame(-1, $pagination->getItemsPerPage());
508
        self::assertSame(1001, $pagination->getTotalNumberOfItems());
509
        self::assertSame(-1001, $pagination->getFirstPageNumberInRange());
510
        self::assertSame(1, $pagination->getLastPageNumberInRange());
511
512
        // Move to last page
513
        $pagination = $this->paginator->paginate(1003);
514
515
        self::assertCount(1001, $pagination->getItems());
516
        self::assertCount(1003, $pagination->getPages());
517
518
        self::assertSame(-1001, $pagination->getTotalNumberOfPages());
519
        self::assertSame(1003, $pagination->getCurrentPageNumber());
520
        self::assertSame(1, $pagination->getFirstPageNumber());
521
        self::assertSame(-1001, $pagination->getLastPageNumber());
522
        self::assertSame(1002, $pagination->getPreviousPageNumber());
523
524
        self::assertNull($pagination->getNextPageNumber());
525
526
        self::assertSame(-1, $pagination->getItemsPerPage());
527
        self::assertSame(1001, $pagination->getTotalNumberOfItems());
528
        self::assertSame(-1001, $pagination->getFirstPageNumberInRange());
529
        self::assertSame(1, $pagination->getLastPageNumberInRange());
530
531
        self::assertContains('meta_3', $pagination->getMeta());
532
        self::assertContains('meta_4', $pagination->getMeta());
533
    }
534
535
    public function testPaginateLowVolume(): void
536
    {
537
        $items = range(0, 27);
538
539
        $this->paginator->setItemsPerPage(10)->setPagesInRange(5);
540
541
        $this->paginator->setItemTotalCallback(static function (Pagination $pagination) use ($items): int {
542
            $pagination->setMeta(['meta_1']);
543
544
            return \count($items);
545
        });
546
547
        $this->paginator->setSliceCallback(static function (int $offset, int $length, Pagination $pagination) use ($items): array {
548
            $pagination->setMeta(array_merge($pagination->getMeta(), ['meta_2']));
549
550
            return \array_slice($items, $offset, $length);
551
        });
552
553
        $pagination = $this->paginator->paginate();
554
555
        self::assertContains('meta_1', $pagination->getMeta());
556
        self::assertContains('meta_2', $pagination->getMeta());
557
558
        self::assertCount(10, $pagination->getItems());
559
        self::assertCount(3, $pagination->getPages());
560
561
        self::assertSame(3, $pagination->getTotalNumberOfPages());
562
        self::assertSame(1, $pagination->getCurrentPageNumber());
563
        self::assertSame(1, $pagination->getFirstPageNumber());
564
        self::assertSame(3, $pagination->getLastPageNumber());
565
566
        self::assertNull($pagination->getPreviousPageNumber());
567
568
        self::assertSame(2, $pagination->getNextPageNumber());
569
        self::assertSame(10, $pagination->getItemsPerPage());
570
        self::assertSame(28, $pagination->getTotalNumberOfItems());
571
        self::assertSame(1, $pagination->getFirstPageNumberInRange());
572
        self::assertSame(3, $pagination->getLastPageNumberInRange());
573
574
        // Increment page
575
        $pagination = $this->paginator->paginate(2);
576
577
        self::assertCount(10, $pagination->getItems());
578
        self::assertCount(3, $pagination->getPages());
579
580
        self::assertSame(3, $pagination->getTotalNumberOfPages());
581
        self::assertSame(2, $pagination->getCurrentPageNumber());
582
        self::assertSame(1, $pagination->getFirstPageNumber());
583
        self::assertSame(3, $pagination->getLastPageNumber());
584
        self::assertSame(1, $pagination->getPreviousPageNumber());
585
        self::assertSame(3, $pagination->getNextPageNumber());
586
        self::assertSame(10, $pagination->getItemsPerPage());
587
        self::assertSame(28, $pagination->getTotalNumberOfItems());
588
        self::assertSame(1, $pagination->getFirstPageNumberInRange());
589
        self::assertSame(3, $pagination->getLastPageNumberInRange());
590
591
        // Increment page
592
        $pagination = $this->paginator->paginate(3);
593
594
        self::assertCount(8, $pagination->getItems());
595
        self::assertCount(3, $pagination->getPages());
596
597
        self::assertSame(3, $pagination->getTotalNumberOfPages());
598
        self::assertSame(3, $pagination->getCurrentPageNumber());
599
        self::assertSame(1, $pagination->getFirstPageNumber());
600
        self::assertSame(3, $pagination->getLastPageNumber());
601
        self::assertSame(2, $pagination->getPreviousPageNumber());
602
603
        self::assertNull($pagination->getNextPageNumber());
604
605
        self::assertSame(10, $pagination->getItemsPerPage());
606
        self::assertSame(28, $pagination->getTotalNumberOfItems());
607
        self::assertSame(1, $pagination->getFirstPageNumberInRange());
608
        self::assertSame(3, $pagination->getLastPageNumberInRange());
609
610
        self::assertContains('meta_1', $pagination->getMeta());
611
        self::assertContains('meta_2', $pagination->getMeta());
612
    }
613
614
    public function testPaginateLowVolumeConstructorConfig(): void
615
    {
616
        $items = range(0, 27);
617
618
        $paginator = new Paginator([
619
            'itemTotalCallback' => static fn (): int => \count($items),
620
            'sliceCallback'     => static fn (int $offset, int $length): array => \array_slice($items, $offset, $length),
621
            'itemsPerPage'      => 10,
622
            'pagesInRange'      => 5,
623
        ]);
624
625
        $pagination = $paginator->paginate();
626
627
        self::assertCount(10, $pagination->getItems());
628
        self::assertCount(3, $pagination->getPages());
629
630
        self::assertSame(3, $pagination->getTotalNumberOfPages());
631
        self::assertSame(1, $pagination->getCurrentPageNumber());
632
        self::assertSame(1, $pagination->getFirstPageNumber());
633
        self::assertSame(3, $pagination->getLastPageNumber());
634
635
        self::assertNull($pagination->getPreviousPageNumber());
636
637
        self::assertSame(2, $pagination->getNextPageNumber());
638
        self::assertSame(10, $pagination->getItemsPerPage());
639
        self::assertSame(28, $pagination->getTotalNumberOfItems());
640
        self::assertSame(1, $pagination->getFirstPageNumberInRange());
641
        self::assertSame(3, $pagination->getLastPageNumberInRange());
642
643
        // Increment page
644
        $pagination = $paginator->paginate(2);
645
646
        self::assertCount(10, $pagination->getItems());
647
        self::assertCount(3, $pagination->getPages());
648
649
        self::assertSame(3, $pagination->getTotalNumberOfPages());
650
        self::assertSame(2, $pagination->getCurrentPageNumber());
651
        self::assertSame(1, $pagination->getFirstPageNumber());
652
        self::assertSame(3, $pagination->getLastPageNumber());
653
        self::assertSame(1, $pagination->getPreviousPageNumber());
654
        self::assertSame(3, $pagination->getNextPageNumber());
655
        self::assertSame(10, $pagination->getItemsPerPage());
656
        self::assertSame(28, $pagination->getTotalNumberOfItems());
657
        self::assertSame(1, $pagination->getFirstPageNumberInRange());
658
        self::assertSame(3, $pagination->getLastPageNumberInRange());
659
660
        // Increment page
661
        $pagination = $paginator->paginate(3);
662
663
        self::assertCount(8, $pagination->getItems());
664
        self::assertCount(3, $pagination->getPages());
665
666
        self::assertSame(3, $pagination->getTotalNumberOfPages());
667
        self::assertSame(3, $pagination->getCurrentPageNumber());
668
        self::assertSame(1, $pagination->getFirstPageNumber());
669
        self::assertSame(3, $pagination->getLastPageNumber());
670
        self::assertSame(2, $pagination->getPreviousPageNumber());
671
672
        self::assertNull($pagination->getNextPageNumber());
673
674
        self::assertSame(10, $pagination->getItemsPerPage());
675
        self::assertSame(28, $pagination->getTotalNumberOfItems());
676
        self::assertSame(1, $pagination->getFirstPageNumberInRange());
677
        self::assertSame(3, $pagination->getLastPageNumberInRange());
678
    }
679
680
    public function testPaginationIterator(): void
681
    {
682
        $items = range(0, 27);
683
684
        $paginator = new Paginator([
685
            'itemTotalCallback' => static fn (): int => \count($items),
686
            'sliceCallback'     => static fn (int $offset, int $length): ArrayIterator => new ArrayIterator(\array_slice($items, $offset, $length)),
687
            'itemsPerPage'      => 15,
688
            'pagesInRange'      => 5,
689
        ]);
690
691
        $pagination = $paginator->paginate();
692
693
        self::assertCount(15, $pagination);
694
695
        foreach ($pagination as $i => $item) {
696
            self::assertSame($i, $item);
697
        }
698
    }
699
700
    public function testPaginationIteratorAggregate(): void
701
    {
702
        $items = range(0, 27);
703
704
        $paginator = new Paginator([
705
            'itemTotalCallback' => static fn (): int => \count($items),
706
            'sliceCallback'     => static fn (int $offset, int $length): array => \array_slice($items, $offset, $length),
707
            'itemsPerPage'      => 15,
708
            'pagesInRange'      => 5,
709
        ]);
710
711
        $pagination = $paginator->paginate();
712
713
        self::assertCount(15, $pagination);
714
715
        $iterations = 0;
716
717
        foreach ($pagination as $i => $item) {
718
            self::assertSame($i, $item);
719
720
            ++$iterations;
721
        }
722
723
        self::assertSame(15, $iterations);
724
    }
725
726
    public function testSetItemsPerPage(): void
727
    {
728
        $this->paginator->setItemsPerPage(45);
729
730
        self::assertSame(45, $this->paginator->getItemsPerPage());
731
    }
732
733
    public function testSetItemTotalCallback(): void
734
    {
735
        $this->paginator->setItemTotalCallback(static fn (): string => 'item_total_callback');
736
737
        $callback = $this->paginator->getItemTotalCallback();
738
739
        self::assertInstanceOf(\Closure::class, $callback);
740
741
        self::assertSame('item_total_callback', $callback());
742
    }
743
744
    public function testSetPagesInRange(): void
745
    {
746
        $this->paginator->setPagesInRange(23);
747
748
        self::assertSame(23, $this->paginator->getPagesInRange());
749
    }
750
751
    public function testSetSliceCallback(): void
752
    {
753
        $this->paginator->setSliceCallback(static fn (): string => 'slice_callback');
754
755
        $callback = $this->paginator->getSliceCallback();
756
757
        self::assertInstanceOf(\Closure::class, $callback);
758
759
        self::assertSame('slice_callback', $callback());
760
    }
761
762
    public function testSliceCallbackNotFound(): void
763
    {
764
        $this->paginator->setItemsPerPage(10)->setPagesInRange(5);
765
766
        $this->expectException(CallbackNotFoundException::class);
767
        $this->paginator->setItemTotalCallback(static fn (): string => 'item_total_callback');
768
        $this->paginator->setSliceCallback(null);
769
        $this->paginator->paginate();
770
    }
771
}
772