RedirectActionTest.php 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. <?php
  2. declare(strict_types=1);
  3. namespace ShlinkioTest\Shlink\Core\Action;
  4. use Laminas\Diactoros\Response;
  5. use Laminas\Diactoros\ServerRequest;
  6. use PHPUnit\Framework\TestCase;
  7. use Prophecy\Argument;
  8. use Prophecy\Prophecy\ObjectProphecy;
  9. use Psr\Http\Server\RequestHandlerInterface;
  10. use Shlinkio\Shlink\Core\Action\RedirectAction;
  11. use Shlinkio\Shlink\Core\Entity\ShortUrl;
  12. use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
  13. use Shlinkio\Shlink\Core\Options;
  14. use Shlinkio\Shlink\Core\Service\UrlShortener;
  15. use Shlinkio\Shlink\Core\Service\VisitsTracker;
  16. use function array_key_exists;
  17. class RedirectActionTest extends TestCase
  18. {
  19. private RedirectAction $action;
  20. private ObjectProphecy $urlShortener;
  21. private ObjectProphecy $visitTracker;
  22. public function setUp(): void
  23. {
  24. $this->urlShortener = $this->prophesize(UrlShortener::class);
  25. $this->visitTracker = $this->prophesize(VisitsTracker::class);
  26. $this->action = new RedirectAction(
  27. $this->urlShortener->reveal(),
  28. $this->visitTracker->reveal(),
  29. new Options\AppOptions(['disableTrackParam' => 'foobar']),
  30. );
  31. }
  32. /**
  33. * @test
  34. * @dataProvider provideQueries
  35. */
  36. public function redirectionIsPerformedToLongUrl(string $expectedUrl, array $query): void
  37. {
  38. $shortCode = 'abc123';
  39. $shortUrl = new ShortUrl('http://domain.com/foo/bar?some=thing');
  40. $shortCodeToUrl = $this->urlShortener->shortCodeToUrl($shortCode, '')->willReturn($shortUrl);
  41. $track = $this->visitTracker->track(Argument::cetera())->will(function (): void {
  42. });
  43. $request = (new ServerRequest())->withAttribute('shortCode', $shortCode)->withQueryParams($query);
  44. $response = $this->action->process($request, $this->prophesize(RequestHandlerInterface::class)->reveal());
  45. $this->assertInstanceOf(Response\RedirectResponse::class, $response);
  46. $this->assertEquals(302, $response->getStatusCode());
  47. $this->assertTrue($response->hasHeader('Location'));
  48. $this->assertEquals($expectedUrl, $response->getHeaderLine('Location'));
  49. $shortCodeToUrl->shouldHaveBeenCalledOnce();
  50. $track->shouldHaveBeenCalledTimes(array_key_exists('foobar', $query) ? 0 : 1);
  51. }
  52. public function provideQueries(): iterable
  53. {
  54. yield ['http://domain.com/foo/bar?some=thing', []];
  55. yield ['http://domain.com/foo/bar?some=thing', ['foobar' => 'notrack']];
  56. yield ['http://domain.com/foo/bar?some=thing&foo=bar', ['foo' => 'bar']];
  57. yield ['http://domain.com/foo/bar?some=overwritten&foo=bar', ['foo' => 'bar', 'some' => 'overwritten']];
  58. yield ['http://domain.com/foo/bar?some=overwritten', ['foobar' => 'notrack', 'some' => 'overwritten']];
  59. }
  60. /** @test */
  61. public function nextMiddlewareIsInvokedIfLongUrlIsNotFound(): void
  62. {
  63. $shortCode = 'abc123';
  64. $this->urlShortener->shortCodeToUrl($shortCode, '')->willThrow(ShortUrlNotFoundException::class)
  65. ->shouldBeCalledOnce();
  66. $this->visitTracker->track(Argument::cetera())->shouldNotBeCalled();
  67. $handler = $this->prophesize(RequestHandlerInterface::class);
  68. $handle = $handler->handle(Argument::any())->willReturn(new Response());
  69. $request = (new ServerRequest())->withAttribute('shortCode', $shortCode);
  70. $this->action->process($request, $handler->reveal());
  71. $handle->shouldHaveBeenCalledOnce();
  72. }
  73. }