|
|
|
|
@@ -13,7 +13,6 @@ use PHPUnit\Framework\MockObject\MockObject;
|
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
|
use Psr\Http\Message\ServerRequestInterface;
|
|
|
|
|
use Psr\Http\Message\UriInterface;
|
|
|
|
|
use Psr\Http\Server\MiddlewareInterface;
|
|
|
|
|
use Psr\Log\NullLogger;
|
|
|
|
|
use Shlinkio\Shlink\Core\Action\RedirectAction;
|
|
|
|
|
use Shlinkio\Shlink\Core\Config\NotFoundRedirectResolver;
|
|
|
|
|
@@ -21,6 +20,8 @@ use Shlinkio\Shlink\Core\ErrorHandler\Model\NotFoundType;
|
|
|
|
|
use Shlinkio\Shlink\Core\Options\NotFoundRedirectOptions;
|
|
|
|
|
use Shlinkio\Shlink\Core\Util\RedirectResponseHelperInterface;
|
|
|
|
|
|
|
|
|
|
use function Laminas\Stratigility\middleware;
|
|
|
|
|
|
|
|
|
|
class NotFoundRedirectResolverTest extends TestCase
|
|
|
|
|
{
|
|
|
|
|
private NotFoundRedirectResolver $resolver;
|
|
|
|
|
@@ -52,47 +53,47 @@ class NotFoundRedirectResolverTest extends TestCase
|
|
|
|
|
self::assertSame($expectedResp, $resp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function provideRedirects(): iterable
|
|
|
|
|
public static function provideRedirects(): iterable
|
|
|
|
|
{
|
|
|
|
|
yield 'base URL with trailing slash' => [
|
|
|
|
|
$uri = new Uri('/'),
|
|
|
|
|
$this->notFoundType(ServerRequestFactory::fromGlobals()->withUri($uri)),
|
|
|
|
|
self::notFoundType(ServerRequestFactory::fromGlobals()->withUri($uri)),
|
|
|
|
|
new NotFoundRedirectOptions(baseUrl: 'baseUrl'),
|
|
|
|
|
'baseUrl',
|
|
|
|
|
];
|
|
|
|
|
yield 'base URL with domain placeholder' => [
|
|
|
|
|
$uri = new Uri('https://s.test'),
|
|
|
|
|
$this->notFoundType(ServerRequestFactory::fromGlobals()->withUri($uri)),
|
|
|
|
|
self::notFoundType(ServerRequestFactory::fromGlobals()->withUri($uri)),
|
|
|
|
|
new NotFoundRedirectOptions(baseUrl: 'https://redirect-here.com/{DOMAIN}'),
|
|
|
|
|
'https://redirect-here.com/s.test',
|
|
|
|
|
];
|
|
|
|
|
yield 'base URL with domain placeholder in query' => [
|
|
|
|
|
$uri = new Uri('https://s.test'),
|
|
|
|
|
$this->notFoundType(ServerRequestFactory::fromGlobals()->withUri($uri)),
|
|
|
|
|
self::notFoundType(ServerRequestFactory::fromGlobals()->withUri($uri)),
|
|
|
|
|
new NotFoundRedirectOptions(baseUrl: 'https://redirect-here.com/?domain={DOMAIN}'),
|
|
|
|
|
'https://redirect-here.com/?domain=s.test',
|
|
|
|
|
];
|
|
|
|
|
yield 'base URL without trailing slash' => [
|
|
|
|
|
$uri = new Uri(''),
|
|
|
|
|
$this->notFoundType(ServerRequestFactory::fromGlobals()->withUri($uri)),
|
|
|
|
|
self::notFoundType(ServerRequestFactory::fromGlobals()->withUri($uri)),
|
|
|
|
|
new NotFoundRedirectOptions(baseUrl: 'baseUrl'),
|
|
|
|
|
'baseUrl',
|
|
|
|
|
];
|
|
|
|
|
yield 'regular 404' => [
|
|
|
|
|
$uri = new Uri('/foo/bar'),
|
|
|
|
|
$this->notFoundType(ServerRequestFactory::fromGlobals()->withUri($uri)),
|
|
|
|
|
self::notFoundType(ServerRequestFactory::fromGlobals()->withUri($uri)),
|
|
|
|
|
new NotFoundRedirectOptions(regular404: 'regular404'),
|
|
|
|
|
'regular404',
|
|
|
|
|
];
|
|
|
|
|
yield 'regular 404 with path placeholder in query' => [
|
|
|
|
|
$uri = new Uri('/foo/bar'),
|
|
|
|
|
$this->notFoundType(ServerRequestFactory::fromGlobals()->withUri($uri)),
|
|
|
|
|
self::notFoundType(ServerRequestFactory::fromGlobals()->withUri($uri)),
|
|
|
|
|
new NotFoundRedirectOptions(regular404: 'https://redirect-here.com/?path={ORIGINAL_PATH}'),
|
|
|
|
|
'https://redirect-here.com/?path=%2Ffoo%2Fbar',
|
|
|
|
|
];
|
|
|
|
|
yield 'regular 404 with multiple placeholders' => [
|
|
|
|
|
$uri = new Uri('https://s.test/foo/bar'),
|
|
|
|
|
$this->notFoundType(ServerRequestFactory::fromGlobals()->withUri($uri)),
|
|
|
|
|
self::notFoundType(ServerRequestFactory::fromGlobals()->withUri($uri)),
|
|
|
|
|
new NotFoundRedirectOptions(
|
|
|
|
|
regular404: 'https://redirect-here.com/{ORIGINAL_PATH}/{DOMAIN}/?d={DOMAIN}&p={ORIGINAL_PATH}',
|
|
|
|
|
),
|
|
|
|
|
@@ -100,13 +101,13 @@ class NotFoundRedirectResolverTest extends TestCase
|
|
|
|
|
];
|
|
|
|
|
yield 'invalid short URL' => [
|
|
|
|
|
new Uri('/foo'),
|
|
|
|
|
$this->notFoundType($this->requestForRoute(RedirectAction::class)),
|
|
|
|
|
self::notFoundType(self::requestForRoute(RedirectAction::class)),
|
|
|
|
|
new NotFoundRedirectOptions(invalidShortUrl: 'invalidShortUrl'),
|
|
|
|
|
'invalidShortUrl',
|
|
|
|
|
];
|
|
|
|
|
yield 'invalid short URL with path placeholder' => [
|
|
|
|
|
new Uri('/foo'),
|
|
|
|
|
$this->notFoundType($this->requestForRoute(RedirectAction::class)),
|
|
|
|
|
self::notFoundType(self::requestForRoute(RedirectAction::class)),
|
|
|
|
|
new NotFoundRedirectOptions(invalidShortUrl: 'https://redirect-here.com/{ORIGINAL_PATH}'),
|
|
|
|
|
'https://redirect-here.com/foo',
|
|
|
|
|
];
|
|
|
|
|
@@ -115,7 +116,7 @@ class NotFoundRedirectResolverTest extends TestCase
|
|
|
|
|
/** @test */
|
|
|
|
|
public function noResponseIsReturnedIfNoConditionsMatch(): void
|
|
|
|
|
{
|
|
|
|
|
$notFoundType = $this->notFoundType($this->requestForRoute('foo'));
|
|
|
|
|
$notFoundType = self::notFoundType(self::requestForRoute('foo'));
|
|
|
|
|
$this->helper->expects($this->never())->method('buildRedirectResponse');
|
|
|
|
|
|
|
|
|
|
$result = $this->resolver->resolveRedirectResponse($notFoundType, new NotFoundRedirectOptions(), new Uri());
|
|
|
|
|
@@ -123,12 +124,12 @@ class NotFoundRedirectResolverTest extends TestCase
|
|
|
|
|
self::assertNull($result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function notFoundType(ServerRequestInterface $req): NotFoundType
|
|
|
|
|
private static function notFoundType(ServerRequestInterface $req): NotFoundType
|
|
|
|
|
{
|
|
|
|
|
return NotFoundType::fromRequest($req, '');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function requestForRoute(string $routeName): ServerRequestInterface
|
|
|
|
|
private static function requestForRoute(string $routeName): ServerRequestInterface
|
|
|
|
|
{
|
|
|
|
|
return ServerRequestFactory::fromGlobals()
|
|
|
|
|
->withAttribute(
|
|
|
|
|
@@ -136,7 +137,8 @@ class NotFoundRedirectResolverTest extends TestCase
|
|
|
|
|
RouteResult::fromRoute(
|
|
|
|
|
new Route(
|
|
|
|
|
'foo',
|
|
|
|
|
$this->createMock(MiddlewareInterface::class),
|
|
|
|
|
middleware(function (): void {
|
|
|
|
|
}),
|
|
|
|
|
['GET'],
|
|
|
|
|
$routeName,
|
|
|
|
|
),
|
|
|
|
|
|