Skip to content

Commit

Permalink
fix(Pager): fix offset pagination bug where the last page points to…
Browse files Browse the repository at this point in the history
… the first page. (#64)
  • Loading branch information
priyadi authored Jun 8, 2024
1 parent f0a70a5 commit a31c5f9
Show file tree
Hide file tree
Showing 3 changed files with 384 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
* build: limit `zenstruck/foundry` to 1.37.* for now
* fix(`PagerFactory`): pager should not be lazy, so that if the page does not
exist, it will throw an exception immediately, not inside template.
* feat(`PagerFactory`): wrap `OutOfBoundsException` and add the pager and
options to the exception class.
* fix(`Pager`): fix offset pagination bug where the last page points to the
first page.

# 0.9.1

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public function __construct(
$this->firstPage = $this->decorate($this->pageable->getFirstPage());

if ($lastPage = $this->pageable->getLastPage()) {
$this->lastPage = $this->decorate($lastPage->withPageNumber(null));
$this->lastPage = $this->decorate($lastPage);
}

// preps
Expand Down
379 changes: 379 additions & 0 deletions tests/src/IntegrationTests/Pager/OffsetPagerWithCountTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,379 @@
<?php

declare(strict_types=1);

/*
* This file is part of rekalogika/rekapager package.
*
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev>
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/

namespace Rekalogika\Rekapager\Tests\IntegrationTests\Pager;

use PHPUnit\Framework\Attributes\DataProviderExternal;
use Rekalogika\Rekapager\Tests\IntegrationTests\DataProvider\PageableGeneratorProvider;

class OffsetPagerWithCountTest extends PagerTestCase
{
protected function getPagerCount(): bool|int
{
return true;
}

#[DataProviderExternal(PageableGeneratorProvider::class, 'offset')]
public function testFirstPage(string $pageableGeneratorClass): void
{
$pageable = $this->createPageableFromGenerator($pageableGeneratorClass);
$pager = $this->createPagerFromPageable($pageable);

$this->assertPager(
$pager,
proximity: 2,
hasPrevious: false,
hasNext: true,
hasFirst: false,
hasLast: true,
hasGapToFirstPage: false,
hasGapToLastPage: true,
numOfPreviousNeighboringPages: 0,
numOfNextNeighboringPages: 4,
firstPageNumber: null,
lastPageNumber: 21,
currentPageNumber: 1,
previousPageNumbers: [],
nextPageNumbers: [2, 3, 4, 5],
currentCount: 5,
);
}

#[DataProviderExternal(PageableGeneratorProvider::class, 'offset')]
public function testSecondPage(string $pageableGeneratorClass): void
{
$pageable = $this->createPageableFromGenerator($pageableGeneratorClass);
$page = $this->getNthPageFromBeginning($pageable, 2);
$pager = $this->createPagerFromPage($page);

$this->assertPager(
$pager,
proximity: 2,
hasPrevious: true,
hasNext: true,
hasFirst: true,
hasLast: true,
hasGapToFirstPage: false,
hasGapToLastPage: true,
numOfPreviousNeighboringPages: 0,
numOfNextNeighboringPages: 3,
firstPageNumber: 1,
lastPageNumber: 21,
currentPageNumber: 2,
previousPageNumbers: [],
nextPageNumbers: [3, 4, 5],
currentCount: 5,
);
}

#[DataProviderExternal(PageableGeneratorProvider::class, 'offset')]
public function testThirdPage(string $pageableGeneratorClass): void
{
$pageable = $this->createPageableFromGenerator($pageableGeneratorClass);
$page = $this->getNthPageFromBeginning($pageable, 3);
$pager = $this->createPagerFromPage($page);

$this->assertPager(
$pager,
proximity: 2,
hasPrevious: true,
hasNext: true,
hasFirst: true,
hasLast: true,
hasGapToFirstPage: false,
hasGapToLastPage: true,
numOfPreviousNeighboringPages: 1,
numOfNextNeighboringPages: 2,
firstPageNumber: 1,
lastPageNumber: 21,
currentPageNumber: 3,
previousPageNumbers: [2],
nextPageNumbers: [4, 5],
currentCount: 5,
);
}

#[DataProviderExternal(PageableGeneratorProvider::class, 'offset')]
public function testFourthPage(string $pageableGeneratorClass): void
{
$pageable = $this->createPageableFromGenerator($pageableGeneratorClass);
$page = $this->getNthPageFromBeginning($pageable, 4);
$pager = $this->createPagerFromPage($page);

$this->assertPager(
$pager,
proximity: 2,
hasPrevious: true,
hasNext: true,
hasFirst: true,
hasLast: true,
hasGapToFirstPage: false,
hasGapToLastPage: true,
numOfPreviousNeighboringPages: 2,
numOfNextNeighboringPages: 2,
firstPageNumber: 1,
lastPageNumber: 21,
currentPageNumber: 4,
previousPageNumbers: [2, 3],
nextPageNumbers: [5, 6],
currentCount: 5,
);
}

#[DataProviderExternal(PageableGeneratorProvider::class, 'offset')]
public function testFifthPage(string $pageableGeneratorClass): void
{
$pageable = $this->createPageableFromGenerator($pageableGeneratorClass);
$page = $this->getNthPageFromBeginning($pageable, 5);
$pager = $this->createPagerFromPage($page);

$this->assertPager(
$pager,
proximity: 2,
hasPrevious: true,
hasNext: true,
hasFirst: true,
hasLast: true,
hasGapToFirstPage: false,
hasGapToLastPage: true,
numOfPreviousNeighboringPages: 3,
numOfNextNeighboringPages: 2,
firstPageNumber: 1,
lastPageNumber: 21,
currentPageNumber: 5,
previousPageNumbers: [2, 3, 4],
nextPageNumbers: [6, 7],
currentCount: 5,
);
}

#[DataProviderExternal(PageableGeneratorProvider::class, 'offset')]
public function testSixthPage(string $pageableGeneratorClass): void
{
$pageable = $this->createPageableFromGenerator($pageableGeneratorClass);
$page = $this->getNthPageFromBeginning($pageable, 6);
$pager = $this->createPagerFromPage($page);

$this->assertPager(
$pager,
proximity: 2,
hasPrevious: true,
hasNext: true,
hasFirst: true,
hasLast: true,
hasGapToFirstPage: true,
hasGapToLastPage: true,
numOfPreviousNeighboringPages: 2,
numOfNextNeighboringPages: 2,
firstPageNumber: 1,
lastPageNumber: 21,
currentPageNumber: 6,
previousPageNumbers: [4, 5],
nextPageNumbers: [7, 8],
currentCount: 5,
);
}

#[DataProviderExternal(PageableGeneratorProvider::class, 'offset')]
public function testLastPage(string $pageableGeneratorClass): void
{
$pageable = $this->createPageableFromGenerator($pageableGeneratorClass);
$page = $this->getLastPageByIteration($pageable);
$pager = $this->createPagerFromPage($page);

$this->assertPager(
$pager,
proximity: 2,
hasPrevious: true,
hasNext: false,
hasFirst: true,
hasLast: false,
hasGapToFirstPage: true,
hasGapToLastPage: false,
numOfPreviousNeighboringPages: 4,
numOfNextNeighboringPages: 0,
firstPageNumber: 1,
lastPageNumber: null,
currentPageNumber: 21,
previousPageNumbers: [17, 18, 19, 20],
nextPageNumbers: [],
currentCount: 3,
);
}

#[DataProviderExternal(PageableGeneratorProvider::class, 'offset')]
public function testSecondLastPage(string $pageableGeneratorClass): void
{
$pageable = $this->createPageableFromGenerator($pageableGeneratorClass);
$page = $this->getNthPageFromEndByIteration($pageable, 2);
$pager = $this->createPagerFromPage($page);

$this->assertPager(
$pager,
proximity: 2,
hasPrevious: true,
hasNext: true,
hasFirst: true,
hasLast: true,
hasGapToFirstPage: true,
hasGapToLastPage: false,
numOfPreviousNeighboringPages: 3,
numOfNextNeighboringPages: 0,
firstPageNumber: 1,
lastPageNumber: 21,
currentPageNumber: 20,
previousPageNumbers: [17, 18, 19],
nextPageNumbers: [],
currentCount: 5,
);
}

#[DataProviderExternal(PageableGeneratorProvider::class, 'offset')]
public function testThirdLastPage(string $pageableGeneratorClass): void
{
$pageable = $this->createPageableFromGenerator($pageableGeneratorClass);
$page = $this->getNthPageFromEndByIteration($pageable, 3);
$pager = $this->createPagerFromPage($page);

$this->assertPager(
$pager,
proximity: 2,
hasPrevious: true,
hasNext: true,
hasFirst: true,
hasLast: true,
hasGapToFirstPage: true,
hasGapToLastPage: false,
numOfPreviousNeighboringPages: 2,
numOfNextNeighboringPages: 1,
firstPageNumber: 1,
lastPageNumber: 21,
currentPageNumber: 19,
previousPageNumbers: [17, 18],
nextPageNumbers: [20],
currentCount: 5,
);
}

#[DataProviderExternal(PageableGeneratorProvider::class, 'offset')]
public function testFourthLastPage(string $pageableGeneratorClass): void
{
$pageable = $this->createPageableFromGenerator($pageableGeneratorClass);
$page = $this->getNthPageFromEndByIteration($pageable, 4);
$pager = $this->createPagerFromPage($page);

$this->assertPager(
$pager,
proximity: 2,
hasPrevious: true,
hasNext: true,
hasFirst: true,
hasLast: true,
hasGapToFirstPage: true,
hasGapToLastPage: false,
numOfPreviousNeighboringPages: 2,
numOfNextNeighboringPages: 2,
firstPageNumber: 1,
lastPageNumber: 21,
currentPageNumber: 18,
previousPageNumbers: [16, 17],
nextPageNumbers: [19, 20],
currentCount: 5,
);
}

#[DataProviderExternal(PageableGeneratorProvider::class, 'offset')]
public function testFifthLastPage(string $pageableGeneratorClass): void
{
$pageable = $this->createPageableFromGenerator($pageableGeneratorClass);
$page = $this->getNthPageFromEndByIteration($pageable, 5);
$pager = $this->createPagerFromPage($page);

$this->assertPager(
$pager,
proximity: 2,
hasPrevious: true,
hasNext: true,
hasFirst: true,
hasLast: true,
hasGapToFirstPage: true,
hasGapToLastPage: false,
numOfPreviousNeighboringPages: 2,
numOfNextNeighboringPages: 3,
firstPageNumber: 1,
lastPageNumber: 21,
currentPageNumber: 17,
previousPageNumbers: [15, 16],
nextPageNumbers: [18, 19, 20],
currentCount: 5,
);
}

#[DataProviderExternal(PageableGeneratorProvider::class, 'offset')]
public function testThirdPageByIterationAndJump(string $pageableGeneratorClass): void
{
$pageable = $this->createPageableFromGenerator($pageableGeneratorClass);
$pageByIteration = $this->getNthPageFromBeginning($pageable, 3);
$pagerByIteration = $this->createPagerFromPage($pageByIteration);

$this->assertPager(
$pagerByIteration,
proximity: 2,
hasPrevious: true,
hasNext: true,
hasFirst: true,
hasLast: true,
hasGapToFirstPage: false,
hasGapToLastPage: true,
numOfPreviousNeighboringPages: 1,
numOfNextNeighboringPages: 2,
firstPageNumber: 1,
lastPageNumber: 21,
currentPageNumber: 3,
previousPageNumbers: [2],
nextPageNumbers: [4, 5],
currentCount: 5,
);

$firstPage = $pageable->getFirstPage();
$nextPages = $firstPage->getNextPages(2);
$pageByJump = $nextPages[1] ?? null;
static::assertNotNull($pageByJump);

$pagerByJump = $this->createPagerFromPage($pageByJump);

$this->assertPager(
$pagerByJump,
proximity: 2,
hasPrevious: true,
hasNext: true,
hasFirst: true,
hasLast: true,
hasGapToFirstPage: false,
hasGapToLastPage: true,
numOfPreviousNeighboringPages: 1,
numOfNextNeighboringPages: 2,
firstPageNumber: 1,
lastPageNumber: 21,
currentPageNumber: 3,
previousPageNumbers: [2],
nextPageNumbers: [4, 5],
currentCount: 5,
);

self::assertEquals(
iterator_to_array($pagerByIteration->getCurrentPage()),
iterator_to_array($pagerByJump->getCurrentPage())
);
}
}

0 comments on commit a31c5f9

Please sign in to comment.