ShortUrlServiceTest.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. <?php
  2. declare(strict_types=1);
  3. namespace ShlinkioTest\Shlink\Core\Service;
  4. use Cake\Chronos\Chronos;
  5. use Doctrine\ORM\EntityManagerInterface;
  6. use Doctrine\ORM\EntityRepository;
  7. use PHPUnit\Framework\TestCase;
  8. use Prophecy\Argument;
  9. use Prophecy\PhpUnit\ProphecyTrait;
  10. use Prophecy\Prophecy\ObjectProphecy;
  11. use Shlinkio\Shlink\Core\Entity\ShortUrl;
  12. use Shlinkio\Shlink\Core\Entity\Tag;
  13. use Shlinkio\Shlink\Core\Model\ShortUrlEdit;
  14. use Shlinkio\Shlink\Core\Model\ShortUrlIdentifier;
  15. use Shlinkio\Shlink\Core\Model\ShortUrlsParams;
  16. use Shlinkio\Shlink\Core\Repository\ShortUrlRepository;
  17. use Shlinkio\Shlink\Core\Service\ShortUrl\ShortUrlResolverInterface;
  18. use Shlinkio\Shlink\Core\Service\ShortUrlService;
  19. use Shlinkio\Shlink\Core\Util\UrlValidatorInterface;
  20. use Shlinkio\Shlink\Rest\Entity\ApiKey;
  21. use function count;
  22. class ShortUrlServiceTest extends TestCase
  23. {
  24. use ProphecyTrait;
  25. private ShortUrlService $service;
  26. private ObjectProphecy $em;
  27. private ObjectProphecy $urlResolver;
  28. private ObjectProphecy $urlValidator;
  29. public function setUp(): void
  30. {
  31. $this->em = $this->prophesize(EntityManagerInterface::class);
  32. $this->em->persist(Argument::any())->willReturn(null);
  33. $this->em->flush()->willReturn(null);
  34. $this->urlResolver = $this->prophesize(ShortUrlResolverInterface::class);
  35. $this->urlValidator = $this->prophesize(UrlValidatorInterface::class);
  36. $this->service = new ShortUrlService(
  37. $this->em->reveal(),
  38. $this->urlResolver->reveal(),
  39. $this->urlValidator->reveal(),
  40. );
  41. }
  42. /** @test */
  43. public function listedUrlsAreReturnedFromEntityManager(): void
  44. {
  45. $list = [
  46. new ShortUrl(''),
  47. new ShortUrl(''),
  48. new ShortUrl(''),
  49. new ShortUrl(''),
  50. ];
  51. $repo = $this->prophesize(ShortUrlRepository::class);
  52. $repo->findList(Argument::cetera())->willReturn($list)->shouldBeCalledOnce();
  53. $repo->countList(Argument::cetera())->willReturn(count($list))->shouldBeCalledOnce();
  54. $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal());
  55. $list = $this->service->listShortUrls(ShortUrlsParams::emptyInstance());
  56. self::assertEquals(4, $list->getCurrentItemCount());
  57. }
  58. /** @test */
  59. public function providedTagsAreGetFromRepoAndSetToTheShortUrl(): void
  60. {
  61. $shortUrl = $this->prophesize(ShortUrl::class);
  62. $shortUrl->setTags(Argument::any())->shouldBeCalledOnce();
  63. $shortCode = 'abc123';
  64. $this->urlResolver->resolveShortUrl(new ShortUrlIdentifier($shortCode))->willReturn($shortUrl->reveal())
  65. ->shouldBeCalledOnce();
  66. $tagRepo = $this->prophesize(EntityRepository::class);
  67. $tagRepo->findOneBy(['name' => 'foo'])->willReturn(new Tag('foo'))->shouldBeCalledOnce();
  68. $tagRepo->findOneBy(['name' => 'bar'])->willReturn(null)->shouldBeCalledOnce();
  69. $this->em->getRepository(Tag::class)->willReturn($tagRepo->reveal());
  70. $this->service->setTagsByShortCode(new ShortUrlIdentifier($shortCode), ['foo', 'bar']);
  71. }
  72. /**
  73. * @test
  74. * @dataProvider provideShortUrlEdits
  75. */
  76. public function updateMetadataByShortCodeUpdatesProvidedData(
  77. int $expectedValidateCalls,
  78. ShortUrlEdit $shortUrlEdit,
  79. ?ApiKey $apiKey
  80. ): void {
  81. $originalLongUrl = 'originalLongUrl';
  82. $shortUrl = new ShortUrl($originalLongUrl);
  83. $findShortUrl = $this->urlResolver->resolveShortUrl(
  84. new ShortUrlIdentifier('abc123'),
  85. $apiKey,
  86. )->willReturn($shortUrl);
  87. $flush = $this->em->flush()->willReturn(null);
  88. $result = $this->service->updateMetadataByShortCode(new ShortUrlIdentifier('abc123'), $shortUrlEdit, $apiKey);
  89. self::assertSame($shortUrl, $result);
  90. self::assertEquals($shortUrlEdit->validSince(), $shortUrl->getValidSince());
  91. self::assertEquals($shortUrlEdit->validUntil(), $shortUrl->getValidUntil());
  92. self::assertEquals($shortUrlEdit->maxVisits(), $shortUrl->getMaxVisits());
  93. self::assertEquals($shortUrlEdit->longUrl() ?? $originalLongUrl, $shortUrl->getLongUrl());
  94. $findShortUrl->shouldHaveBeenCalled();
  95. $flush->shouldHaveBeenCalled();
  96. $this->urlValidator->validateUrl(
  97. $shortUrlEdit->longUrl(),
  98. $shortUrlEdit->doValidateUrl(),
  99. )->shouldHaveBeenCalledTimes($expectedValidateCalls);
  100. }
  101. public function provideShortUrlEdits(): iterable
  102. {
  103. yield 'no long URL' => [0, ShortUrlEdit::fromRawData(
  104. [
  105. 'validSince' => Chronos::parse('2017-01-01 00:00:00')->toAtomString(),
  106. 'validUntil' => Chronos::parse('2017-01-05 00:00:00')->toAtomString(),
  107. 'maxVisits' => 5,
  108. ],
  109. ), null];
  110. yield 'long URL' => [1, ShortUrlEdit::fromRawData(
  111. [
  112. 'validSince' => Chronos::parse('2017-01-01 00:00:00')->toAtomString(),
  113. 'maxVisits' => 10,
  114. 'longUrl' => 'modifiedLongUrl',
  115. ],
  116. ), new ApiKey()];
  117. yield 'long URL with validation' => [1, ShortUrlEdit::fromRawData(
  118. [
  119. 'longUrl' => 'modifiedLongUrl',
  120. 'validateUrl' => true,
  121. ],
  122. ), null];
  123. }
  124. }