Added tests for new ShortUrlRepository::findOneMatching method

This commit is contained in:
Alejandro Celaya 2020-09-23 07:34:36 +02:00
parent 460ca032d2
commit 4e94f07050
2 changed files with 114 additions and 36 deletions

View file

@ -208,7 +208,8 @@ DQL;
->from(ShortUrl::class, 's') ->from(ShortUrl::class, 's')
->where($qb->expr()->eq('s.longUrl', ':longUrl')) ->where($qb->expr()->eq('s.longUrl', ':longUrl'))
->setParameter('longUrl', $url) ->setParameter('longUrl', $url)
->setMaxResults(1); ->setMaxResults(1)
->orderBy('s.id');
if ($meta->hasCustomSlug()) { if ($meta->hasCustomSlug()) {
$qb->andWhere($qb->expr()->eq('s.shortCode', ':slug')) $qb->andWhere($qb->expr()->eq('s.shortCode', ':slug'))
@ -246,14 +247,11 @@ DQL;
// If tags where provided, we need an extra join to see the amount of tags that every short URL has, so that we // If tags where provided, we need an extra join to see the amount of tags that every short URL has, so that we
// can discard those that also have more tags, making sure only those fully matching are included. // can discard those that also have more tags, making sure only those fully matching are included.
$qb->addSelect('COUNT(t.id) as tagsAmount') $qb->join('s.tags', 't')
->join('s.tags', 't')
->groupBy('s') ->groupBy('s')
->having($qb->expr()->eq('tagsAmount', ':tagsAmount')) ->having($qb->expr()->eq('COUNT(t.id)', ':tagsAmount'))
->setParameter('tagsAmount', $tagsAmount); ->setParameter('tagsAmount', $tagsAmount);
$result = $qb->getQuery()->getOneOrNullResult() ?? []; return $qb->getQuery()->getOneOrNullResult();
return $result[0] ?? null;
} }
} }

View file

@ -16,12 +16,15 @@ use Shlinkio\Shlink\Core\Model\ShortUrlMeta;
use Shlinkio\Shlink\Core\Model\ShortUrlsOrdering; use Shlinkio\Shlink\Core\Model\ShortUrlsOrdering;
use Shlinkio\Shlink\Core\Model\Visitor; use Shlinkio\Shlink\Core\Model\Visitor;
use Shlinkio\Shlink\Core\Repository\ShortUrlRepository; use Shlinkio\Shlink\Core\Repository\ShortUrlRepository;
use Shlinkio\Shlink\Core\Util\TagManagerTrait;
use Shlinkio\Shlink\TestUtils\DbTest\DatabaseTestCase; use Shlinkio\Shlink\TestUtils\DbTest\DatabaseTestCase;
use function count; use function count;
class ShortUrlRepositoryTest extends DatabaseTestCase class ShortUrlRepositoryTest extends DatabaseTestCase
{ {
use TagManagerTrait;
protected const ENTITIES_TO_EMPTY = [ protected const ENTITIES_TO_EMPTY = [
Tag::class, Tag::class,
Visit::class, Visit::class,
@ -211,33 +214,110 @@ class ShortUrlRepositoryTest extends DatabaseTestCase
$this->assertNotNull($this->repo->findOne('another-slug', 'doma.in')); $this->assertNotNull($this->repo->findOne('another-slug', 'doma.in'));
} }
// public function findOneMatchingAppliesProperConditions(): void /** @test */
// { public function findOneMatchingReturnsNullForNonExistingShortUrls(): void
// $matches = $this->provideCriteriaToMatch(); {
// } $this->assertNull($this->repo->findOneMatching('', [], ShortUrlMeta::createEmpty()));
// $this->assertNull($this->repo->findOneMatching('foobar', [], ShortUrlMeta::createEmpty()));
// private function provideCriteriaToMatch(): iterable $this->assertNull($this->repo->findOneMatching('foobar', ['foo', 'bar'], ShortUrlMeta::createEmpty()));
// { $this->assertNull($this->repo->findOneMatching('foobar', ['foo', 'bar'], ShortUrlMeta::fromRawData([
// $start = Chronos::parse('2020-03-05 20:18:30'); 'validSince' => Chronos::parse('2020-03-05 20:18:30'),
// $end = Chronos::parse('2021-03-05 20:18:30'); 'customSlug' => 'this_slug_does_not_exist',
// ])));
// yield [new ShortUrl('foo'), ShortUrlMeta::fromRawData(['validSince' => $start]), false]; }
// yield [new ShortUrl('foo'), ShortUrlMeta::fromRawData(['validUntil' => $end]), false];
// yield [new ShortUrl('foo'), ShortUrlMeta::fromRawData(['validSince' => $start, 'validUntil' => $end]), false]; /** @test */
// yield [ public function findOneMatchingAppliesProperConditions(): void
// new ShortUrl('foo', ShortUrlMeta::fromRawData(['validSince' => $start])), {
// ShortUrlMeta::fromRawData(['validSince' => $start]), $start = Chronos::parse('2020-03-05 20:18:30');
// true, $end = Chronos::parse('2021-03-05 20:18:30');
// ];
// yield [ $shortUrl = new ShortUrl('foo', ShortUrlMeta::fromRawData(['validSince' => $start]));
// new ShortUrl('foo', ShortUrlMeta::fromRawData(['validUntil' => $end])), $shortUrl->setTags($this->tagNamesToEntities($this->getEntityManager(), ['foo', 'bar']));
// ShortUrlMeta::fromRawData(['validUntil' => $end]), $this->getEntityManager()->persist($shortUrl);
// true,
// ]; $shortUrl2 = new ShortUrl('bar', ShortUrlMeta::fromRawData(['validUntil' => $end]));
// yield [ $this->getEntityManager()->persist($shortUrl2);
// new ShortUrl('foo', ShortUrlMeta::fromRawData(['validUntil' => $end, 'validSince' => $start])),
// ShortUrlMeta::fromRawData(['validUntil' => $end, 'validSince' => $start]), $shortUrl3 = new ShortUrl('baz', ShortUrlMeta::fromRawData(['validSince' => $start, 'validUntil' => $end]));
// true, $this->getEntityManager()->persist($shortUrl3);
// ];
// } $shortUrl4 = new ShortUrl('foo', ShortUrlMeta::fromRawData(['customSlug' => 'custom', 'validUntil' => $end]));
$this->getEntityManager()->persist($shortUrl4);
$shortUrl5 = new ShortUrl('foo', ShortUrlMeta::fromRawData(['maxVisits' => 3]));
$this->getEntityManager()->persist($shortUrl5);
$shortUrl6 = new ShortUrl('foo', ShortUrlMeta::fromRawData(['domain' => 'doma.in']));
$this->getEntityManager()->persist($shortUrl6);
$this->getEntityManager()->flush();
$this->assertSame(
$shortUrl,
$this->repo->findOneMatching('foo', ['foo', 'bar'], ShortUrlMeta::fromRawData(['validSince' => $start])),
);
$this->assertSame(
$shortUrl2,
$this->repo->findOneMatching('bar', [], ShortUrlMeta::fromRawData(['validUntil' => $end])),
);
$this->assertSame(
$shortUrl3,
$this->repo->findOneMatching('baz', [], ShortUrlMeta::fromRawData([
'validSince' => $start,
'validUntil' => $end,
])),
);
$this->assertSame(
$shortUrl4,
$this->repo->findOneMatching('foo', [], ShortUrlMeta::fromRawData([
'customSlug' => 'custom',
'validUntil' => $end,
])),
);
$this->assertSame(
$shortUrl5,
$this->repo->findOneMatching('foo', [], ShortUrlMeta::fromRawData(['maxVisits' => 3])),
);
$this->assertSame(
$shortUrl6,
$this->repo->findOneMatching('foo', [], ShortUrlMeta::fromRawData(['domain' => 'doma.in'])),
);
}
/** @test */
public function findOneMatchingReturnsOldestOneWhenThereAreMultipleMatches(): void
{
$start = Chronos::parse('2020-03-05 20:18:30');
$meta = ['validSince' => $start, 'maxVisits' => 50];
$tags = ['foo', 'bar'];
$tagEntities = $this->tagNamesToEntities($this->getEntityManager(), $tags);
$shortUrl1 = new ShortUrl('foo', ShortUrlMeta::fromRawData($meta));
$shortUrl1->setTags($tagEntities);
$this->getEntityManager()->persist($shortUrl1);
$shortUrl2 = new ShortUrl('foo', ShortUrlMeta::fromRawData($meta));
$shortUrl2->setTags($tagEntities);
$this->getEntityManager()->persist($shortUrl2);
$shortUrl3 = new ShortUrl('foo', ShortUrlMeta::fromRawData($meta));
$shortUrl3->setTags($tagEntities);
$this->getEntityManager()->persist($shortUrl3);
$this->getEntityManager()->flush();
$this->assertSame(
$shortUrl1,
$this->repo->findOneMatching('foo', $tags, ShortUrlMeta::fromRawData($meta)),
);
$this->assertNotSame(
$shortUrl2,
$this->repo->findOneMatching('foo', $tags, ShortUrlMeta::fromRawData($meta)),
);
$this->assertNotSame(
$shortUrl3,
$this->repo->findOneMatching('foo', $tags, ShortUrlMeta::fromRawData($meta)),
);
}
} }