mirror of
https://github.com/shlinkio/shlink.git
synced 2024-11-28 00:38:46 +03:00
Created paginator adapter tests
This commit is contained in:
parent
3218f8c283
commit
e1e3c7f061
5 changed files with 144 additions and 32 deletions
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Core\Paginator\Adapter;
|
||||
|
||||
use Laminas\Paginator\Adapter\AdapterInterface;
|
||||
|
||||
abstract class AbstractCacheableCountPaginatorAdapter implements AdapterInterface
|
||||
{
|
||||
private ?int $count = null;
|
||||
|
||||
final public function count(): int
|
||||
{
|
||||
// Since a new adapter instance is created every time visits are fetched, it is reasonably safe to internally
|
||||
// cache the count value.
|
||||
// The reason it is cached is because the Paginator is actually calling the method twice.
|
||||
// An inconsistent value could be returned if between the first call and the second one, a new visit is created.
|
||||
// However, it's almost instant, and then the adapter instance is discarded immediately after.
|
||||
|
||||
if ($this->count !== null) {
|
||||
return $this->count;
|
||||
}
|
||||
|
||||
return $this->count = $this->doCount();
|
||||
}
|
||||
|
||||
abstract protected function doCount(): int;
|
||||
}
|
|
@ -4,18 +4,15 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shlinkio\Shlink\Core\Paginator\Adapter;
|
||||
|
||||
use Laminas\Paginator\Adapter\AdapterInterface;
|
||||
use Shlinkio\Shlink\Core\Model\VisitsParams;
|
||||
use Shlinkio\Shlink\Core\Repository\VisitRepositoryInterface;
|
||||
|
||||
class VisitsForTagPaginatorAdapter implements AdapterInterface
|
||||
class VisitsForTagPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
|
||||
{
|
||||
private VisitRepositoryInterface $visitRepository;
|
||||
private string $tag;
|
||||
private VisitsParams $params;
|
||||
|
||||
private ?int $count = null;
|
||||
|
||||
public function __construct(VisitRepositoryInterface $visitRepository, string $tag, VisitsParams $params)
|
||||
{
|
||||
$this->visitRepository = $visitRepository;
|
||||
|
@ -33,18 +30,8 @@ class VisitsForTagPaginatorAdapter implements AdapterInterface
|
|||
);
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
protected function doCount(): int
|
||||
{
|
||||
// Since a new adapter instance is created every time visits are fetched, it is reasonably safe to internally
|
||||
// cache the count value.
|
||||
// The reason it is cached is because the Paginator is actually calling the method twice.
|
||||
// An inconsistent value could be returned if between the first call and the second one, a new visit is created.
|
||||
// However, it's almost instant, and then the adapter instance is discarded immediately after.
|
||||
|
||||
if ($this->count !== null) {
|
||||
return $this->count;
|
||||
}
|
||||
|
||||
return $this->count = $this->visitRepository->countVisitsByTag($this->tag, $this->params->getDateRange());
|
||||
return $this->visitRepository->countVisitsByTag($this->tag, $this->params->getDateRange());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,19 +4,16 @@ declare(strict_types=1);
|
|||
|
||||
namespace Shlinkio\Shlink\Core\Paginator\Adapter;
|
||||
|
||||
use Laminas\Paginator\Adapter\AdapterInterface;
|
||||
use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier;
|
||||
use Shlinkio\Shlink\Core\Model\VisitsParams;
|
||||
use Shlinkio\Shlink\Core\Repository\VisitRepositoryInterface;
|
||||
|
||||
class VisitsPaginatorAdapter implements AdapterInterface
|
||||
class VisitsPaginatorAdapter extends AbstractCacheableCountPaginatorAdapter
|
||||
{
|
||||
private VisitRepositoryInterface $visitRepository;
|
||||
private ShortUrlIdentifier $identifier;
|
||||
private VisitsParams $params;
|
||||
|
||||
private ?int $count = null;
|
||||
|
||||
public function __construct(
|
||||
VisitRepositoryInterface $visitRepository,
|
||||
ShortUrlIdentifier $identifier,
|
||||
|
@ -38,19 +35,9 @@ class VisitsPaginatorAdapter implements AdapterInterface
|
|||
);
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
protected function doCount(): int
|
||||
{
|
||||
// Since a new adapter instance is created every time visits are fetched, it is reasonably safe to internally
|
||||
// cache the count value.
|
||||
// The reason it is cached is because the Paginator is actually calling the method twice.
|
||||
// An inconsistent value could be returned if between the first call and the second one, a new visit is created.
|
||||
// However, it's almost instant, and then the adapter instance is discarded immediately after.
|
||||
|
||||
if ($this->count !== null) {
|
||||
return $this->count;
|
||||
}
|
||||
|
||||
return $this->count = $this->visitRepository->countVisitsByShortCode(
|
||||
return $this->visitRepository->countVisitsByShortCode(
|
||||
$this->identifier->shortCode(),
|
||||
$this->identifier->domain(),
|
||||
$this->params->getDateRange(),
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ShlinkioTest\Shlink\Core\Paginator\Adapter;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Common\Util\DateRange;
|
||||
use Shlinkio\Shlink\Core\Model\VisitsParams;
|
||||
use Shlinkio\Shlink\Core\Paginator\Adapter\VisitsForTagPaginatorAdapter;
|
||||
use Shlinkio\Shlink\Core\Repository\VisitRepositoryInterface;
|
||||
|
||||
class VisitsForTagPaginatorAdapterTest extends TestCase
|
||||
{
|
||||
private VisitsForTagPaginatorAdapter $adapter;
|
||||
private ObjectProphecy $repo;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->repo = $this->prophesize(VisitRepositoryInterface::class);
|
||||
$this->adapter = new VisitsForTagPaginatorAdapter($this->repo->reveal(), 'foo', VisitsParams::fromRawData([]));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function repoIsCalledEveryTimeItemsAreFetched(): void
|
||||
{
|
||||
$count = 3;
|
||||
$limit = 1;
|
||||
$offset = 5;
|
||||
$findVisits = $this->repo->findVisitsByTag('foo', new DateRange(), $limit, $offset)->willReturn([]);
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$this->adapter->getItems($offset, $limit);
|
||||
}
|
||||
|
||||
$findVisits->shouldHaveBeenCalledTimes($count);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function repoIsCalledOnlyOnceForCount(): void
|
||||
{
|
||||
$count = 3;
|
||||
$countVisits = $this->repo->countVisitsByTag('foo', new DateRange())->willReturn(3);
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$this->adapter->count();
|
||||
}
|
||||
|
||||
$countVisits->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ShlinkioTest\Shlink\Core\Paginator\Adapter;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Common\Util\DateRange;
|
||||
use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier;
|
||||
use Shlinkio\Shlink\Core\Model\VisitsParams;
|
||||
use Shlinkio\Shlink\Core\Paginator\Adapter\VisitsPaginatorAdapter;
|
||||
use Shlinkio\Shlink\Core\Repository\VisitRepositoryInterface;
|
||||
|
||||
class VisitsPaginatorAdapterTest extends TestCase
|
||||
{
|
||||
private VisitsPaginatorAdapter $adapter;
|
||||
private ObjectProphecy $repo;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->repo = $this->prophesize(VisitRepositoryInterface::class);
|
||||
$this->adapter = new VisitsPaginatorAdapter(
|
||||
$this->repo->reveal(),
|
||||
new ShortUrlIdentifier(''),
|
||||
VisitsParams::fromRawData([]),
|
||||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function repoIsCalledEveryTimeItemsAreFetched(): void
|
||||
{
|
||||
$count = 3;
|
||||
$limit = 1;
|
||||
$offset = 5;
|
||||
$findVisits = $this->repo->findVisitsByShortCode('', null, new DateRange(), $limit, $offset)->willReturn([]);
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$this->adapter->getItems($offset, $limit);
|
||||
}
|
||||
|
||||
$findVisits->shouldHaveBeenCalledTimes($count);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function repoIsCalledOnlyOnceForCount(): void
|
||||
{
|
||||
$count = 3;
|
||||
$countVisits = $this->repo->countVisitsByShortCode('', null, new DateRange())->willReturn(3);
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$this->adapter->count();
|
||||
}
|
||||
|
||||
$countVisits->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue