ListShortUrlsCommandTest.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. <?php
  2. declare(strict_types=1);
  3. namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl;
  4. use Cake\Chronos\Chronos;
  5. use Laminas\Paginator\Adapter\ArrayAdapter;
  6. use Laminas\Paginator\Paginator;
  7. use PHPUnit\Framework\TestCase;
  8. use Prophecy\Argument;
  9. use Prophecy\Prophecy\ObjectProphecy;
  10. use Shlinkio\Shlink\CLI\Command\ShortUrl\ListShortUrlsCommand;
  11. use Shlinkio\Shlink\Common\Util\DateRange;
  12. use Shlinkio\Shlink\Core\Entity\ShortUrl;
  13. use Shlinkio\Shlink\Core\Service\ShortUrlServiceInterface;
  14. use Symfony\Component\Console\Application;
  15. use Symfony\Component\Console\Tester\CommandTester;
  16. use function explode;
  17. class ListShortUrlsCommandTest extends TestCase
  18. {
  19. private CommandTester $commandTester;
  20. private ObjectProphecy $shortUrlService;
  21. public function setUp(): void
  22. {
  23. $this->shortUrlService = $this->prophesize(ShortUrlServiceInterface::class);
  24. $app = new Application();
  25. $command = new ListShortUrlsCommand($this->shortUrlService->reveal(), []);
  26. $app->add($command);
  27. $this->commandTester = new CommandTester($command);
  28. }
  29. /** @test */
  30. public function loadingMorePagesCallsListMoreTimes(): void
  31. {
  32. // The paginator will return more than one page
  33. $data = [];
  34. for ($i = 0; $i < 50; $i++) {
  35. $data[] = new ShortUrl('url_' . $i);
  36. }
  37. $this->shortUrlService->listShortUrls(Argument::cetera())
  38. ->will(fn () => new Paginator(new ArrayAdapter($data)))
  39. ->shouldBeCalledTimes(3);
  40. $this->commandTester->setInputs(['y', 'y', 'n']);
  41. $this->commandTester->execute([]);
  42. $output = $this->commandTester->getDisplay();
  43. $this->assertStringContainsString('Continue with page 2?', $output);
  44. $this->assertStringContainsString('Continue with page 3?', $output);
  45. $this->assertStringContainsString('Continue with page 4?', $output);
  46. }
  47. /** @test */
  48. public function havingMorePagesButAnsweringNoCallsListJustOnce(): void
  49. {
  50. // The paginator will return more than one page
  51. $data = [];
  52. for ($i = 0; $i < 30; $i++) {
  53. $data[] = new ShortUrl('url_' . $i);
  54. }
  55. $this->shortUrlService->listShortUrls(1, null, [], null, new DateRange())
  56. ->willReturn(new Paginator(new ArrayAdapter($data)))
  57. ->shouldBeCalledOnce();
  58. $this->commandTester->setInputs(['n']);
  59. $this->commandTester->execute([]);
  60. $output = $this->commandTester->getDisplay();
  61. $this->assertStringContainsString('url_1', $output);
  62. $this->assertStringContainsString('url_9', $output);
  63. $this->assertStringNotContainsString('url_10', $output);
  64. $this->assertStringNotContainsString('url_20', $output);
  65. $this->assertStringNotContainsString('url_30', $output);
  66. $this->assertStringContainsString('Continue with page 2?', $output);
  67. $this->assertStringNotContainsString('Continue with page 3?', $output);
  68. }
  69. /** @test */
  70. public function passingPageWillMakeListStartOnThatPage(): void
  71. {
  72. $page = 5;
  73. $this->shortUrlService->listShortUrls($page, null, [], null, new DateRange())
  74. ->willReturn(new Paginator(new ArrayAdapter()))
  75. ->shouldBeCalledOnce();
  76. $this->commandTester->setInputs(['y']);
  77. $this->commandTester->execute(['--page' => $page]);
  78. }
  79. /** @test */
  80. public function ifTagsFlagIsProvidedTagsColumnIsIncluded(): void
  81. {
  82. $this->shortUrlService->listShortUrls(1, null, [], null, new DateRange())
  83. ->willReturn(new Paginator(new ArrayAdapter()))
  84. ->shouldBeCalledOnce();
  85. $this->commandTester->setInputs(['y']);
  86. $this->commandTester->execute(['--showTags' => true]);
  87. $output = $this->commandTester->getDisplay();
  88. $this->assertStringContainsString('Tags', $output);
  89. }
  90. /**
  91. * @test
  92. * @dataProvider provideArgs
  93. */
  94. public function serviceIsInvokedWithProvidedArgs(
  95. array $commandArgs,
  96. ?int $page,
  97. ?string $searchTerm,
  98. array $tags,
  99. ?DateRange $dateRange
  100. ): void {
  101. $listShortUrls = $this->shortUrlService->listShortUrls($page, $searchTerm, $tags, null, $dateRange)
  102. ->willReturn(new Paginator(new ArrayAdapter()));
  103. $this->commandTester->setInputs(['n']);
  104. $this->commandTester->execute($commandArgs);
  105. $listShortUrls->shouldHaveBeenCalledOnce();
  106. }
  107. public function provideArgs(): iterable
  108. {
  109. yield [[], 1, null, [], new DateRange()];
  110. yield [['--page' => $page = 3], $page, null, [], new DateRange()];
  111. yield [['--searchTerm' => $searchTerm = 'search this'], 1, $searchTerm, [], new DateRange()];
  112. yield [
  113. ['--page' => $page = 3, '--searchTerm' => $searchTerm = 'search this', '--tags' => $tags = 'foo,bar'],
  114. $page,
  115. $searchTerm,
  116. explode(',', $tags),
  117. new DateRange(),
  118. ];
  119. yield [
  120. ['--startDate' => $startDate = '2019-01-01'],
  121. 1,
  122. null,
  123. [],
  124. new DateRange(Chronos::parse($startDate)),
  125. ];
  126. yield [
  127. ['--endDate' => $endDate = '2020-05-23'],
  128. 1,
  129. null,
  130. [],
  131. new DateRange(null, Chronos::parse($endDate)),
  132. ];
  133. yield [
  134. ['--startDate' => $startDate = '2019-01-01', '--endDate' => $endDate = '2020-05-23'],
  135. 1,
  136. null,
  137. [],
  138. new DateRange(Chronos::parse($startDate), Chronos::parse($endDate)),
  139. ];
  140. }
  141. /**
  142. * @param string|array|null $expectedOrderBy
  143. * @test
  144. * @dataProvider provideOrderBy
  145. */
  146. public function orderByIsProperlyComputed(array $commandArgs, $expectedOrderBy): void
  147. {
  148. $listShortUrls = $this->shortUrlService->listShortUrls(1, null, [], $expectedOrderBy, new DateRange())
  149. ->willReturn(new Paginator(new ArrayAdapter()));
  150. $this->commandTester->setInputs(['n']);
  151. $this->commandTester->execute($commandArgs);
  152. $listShortUrls->shouldHaveBeenCalledOnce();
  153. }
  154. public function provideOrderBy(): iterable
  155. {
  156. yield [[], null];
  157. yield [['--orderBy' => 'foo'], 'foo'];
  158. yield [['--orderBy' => 'foo,ASC'], ['foo' => 'ASC']];
  159. yield [['--orderBy' => 'bar,DESC'], ['bar' => 'DESC']];
  160. }
  161. }