From dd4b4277c92f07651b666e91b084236bf4236bb7 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 8 May 2020 20:11:37 +0200 Subject: [PATCH] Added test for VisitRepository tag methods --- .../Core/src/Repository/VisitRepository.php | 5 +- .../Repository/VisitRepositoryTest.php | 99 +++++++++++++++---- 2 files changed, 85 insertions(+), 19 deletions(-) diff --git a/module/Core/src/Repository/VisitRepository.php b/module/Core/src/Repository/VisitRepository.php index e779a8bb..b3761c9f 100644 --- a/module/Core/src/Repository/VisitRepository.php +++ b/module/Core/src/Repository/VisitRepository.php @@ -149,11 +149,14 @@ class VisitRepository extends EntityRepository implements VisitRepositoryInterfa ->where($qb->expr()->eq('t.name', ':tag')) ->setParameter('tag', $tag); + $shortUrlIds = array_column($qb->getQuery()->getArrayResult(), 'id'); + $shortUrlIds[] = '-1'; // Add an invalid ID, in case the list is empty + // Parameters in this query need to be part of the query itself, as we need to use it a sub-query later // Since they are not strictly provided by the caller, it's reasonably safe $qb2 = $this->getEntityManager()->createQueryBuilder(); $qb2->from(Visit::class, 'v') - ->where($qb2->expr()->in('v.shortUrl', array_column($qb->getQuery()->getArrayResult(), 'id'))); + ->where($qb2->expr()->in('v.shortUrl', $shortUrlIds)); // Apply date range filtering $this->applyDatesInline($qb2, $dateRange); diff --git a/module/Core/test-db/Repository/VisitRepositoryTest.php b/module/Core/test-db/Repository/VisitRepositoryTest.php index 13fc8581..529a5ae0 100644 --- a/module/Core/test-db/Repository/VisitRepositoryTest.php +++ b/module/Core/test-db/Repository/VisitRepositoryTest.php @@ -5,9 +5,11 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Repository; use Cake\Chronos\Chronos; +use Doctrine\Common\Collections\ArrayCollection; use Shlinkio\Shlink\Common\Util\DateRange; use Shlinkio\Shlink\Core\Entity\Domain; use Shlinkio\Shlink\Core\Entity\ShortUrl; +use Shlinkio\Shlink\Core\Entity\Tag; use Shlinkio\Shlink\Core\Entity\Visit; use Shlinkio\Shlink\Core\Entity\VisitLocation; use Shlinkio\Shlink\Core\Model\ShortUrlMeta; @@ -27,6 +29,7 @@ class VisitRepositoryTest extends DatabaseTestCase Visit::class, ShortUrl::class, Domain::class, + Tag::class, ]; private VisitRepository $repo; @@ -125,18 +128,69 @@ class VisitRepositoryTest extends DatabaseTestCase ))); } - private function createShortUrlsAndVisits(): array + /** @test */ + public function findVisitsByTagReturnsProperData(): void + { + $foo = new Tag('foo'); + $this->getEntityManager()->persist($foo); + + /** @var ShortUrl $shortUrl */ + [,, $shortUrl] = $this->createShortUrlsAndVisits(false); + /** @var ShortUrl $shortUrl2 */ + [,, $shortUrl2] = $this->createShortUrlsAndVisits(false); + /** @var ShortUrl $shortUrl3 */ + [,, $shortUrl3] = $this->createShortUrlsAndVisits(false); + + $shortUrl->setTags(new ArrayCollection([$foo])); + $shortUrl2->setTags(new ArrayCollection([$foo])); + $shortUrl3->setTags(new ArrayCollection([$foo])); + + $this->getEntityManager()->flush(); + + $this->assertCount(0, $this->repo->findVisitsByTag('invalid')); + $this->assertCount(18, $this->repo->findVisitsByTag((string) $foo)); + $this->assertCount(6, $this->repo->findVisitsByTag((string) $foo, new DateRange( + Chronos::parse('2016-01-02'), + Chronos::parse('2016-01-03'), + ))); + $this->assertCount(12, $this->repo->findVisitsByTag((string) $foo, new DateRange( + Chronos::parse('2016-01-03'), + ))); + } + + /** @test */ + public function countVisitsByTagReturnsProperData(): void + { + $foo = new Tag('foo'); + $this->getEntityManager()->persist($foo); + + /** @var ShortUrl $shortUrl */ + [,, $shortUrl] = $this->createShortUrlsAndVisits(false); + /** @var ShortUrl $shortUrl2 */ + [,, $shortUrl2] = $this->createShortUrlsAndVisits(false); + + $shortUrl->setTags(new ArrayCollection([$foo])); + $shortUrl2->setTags(new ArrayCollection([$foo])); + + $this->getEntityManager()->flush(); + + $this->assertEquals(0, $this->repo->countVisitsByTag('invalid')); + $this->assertEquals(12, $this->repo->countVisitsByTag((string) $foo)); + $this->assertEquals(4, $this->repo->countVisitsByTag((string) $foo, new DateRange( + Chronos::parse('2016-01-02'), + Chronos::parse('2016-01-03'), + ))); + $this->assertEquals(8, $this->repo->countVisitsByTag((string) $foo, new DateRange( + Chronos::parse('2016-01-03'), + ))); + } + + private function createShortUrlsAndVisits(bool $withDomain = true): array { $shortUrl = new ShortUrl(''); $domain = 'example.com'; $shortCode = $shortUrl->getShortCode(); - $shortUrlWithDomain = new ShortUrl('', ShortUrlMeta::fromRawData([ - 'customSlug' => $shortCode, - 'domain' => $domain, - ])); - $this->getEntityManager()->persist($shortUrl); - $this->getEntityManager()->persist($shortUrlWithDomain); for ($i = 0; $i < 6; $i++) { $visit = new Visit( @@ -147,17 +201,26 @@ class VisitRepositoryTest extends DatabaseTestCase ); $this->getEntityManager()->persist($visit); } - for ($i = 0; $i < 3; $i++) { - $visit = new Visit( - $shortUrlWithDomain, - Visitor::emptyInstance(), - true, - Chronos::parse(sprintf('2016-01-0%s', $i + 1)), - ); - $this->getEntityManager()->persist($visit); - } - $this->getEntityManager()->flush(); - return [$shortCode, $domain]; + if ($withDomain) { + $shortUrlWithDomain = new ShortUrl('', ShortUrlMeta::fromRawData([ + 'customSlug' => $shortCode, + 'domain' => $domain, + ])); + $this->getEntityManager()->persist($shortUrlWithDomain); + + for ($i = 0; $i < 3; $i++) { + $visit = new Visit( + $shortUrlWithDomain, + Visitor::emptyInstance(), + true, + Chronos::parse(sprintf('2016-01-0%s', $i + 1)), + ); + $this->getEntityManager()->persist($visit); + } + $this->getEntityManager()->flush(); + } + + return [$shortCode, $domain, $shortUrl]; } }