mirror of
https://github.com/shlinkio/shlink.git
synced 2025-02-25 18:45:27 -06:00
Enhanced ExtraPathRedirectMiddleware so that it supports multi-segment slugs
This commit is contained in:
@@ -28,6 +28,8 @@ use Shlinkio\Shlink\Core\ShortUrl\Middleware\ExtraPathRedirectMiddleware;
|
||||
use Shlinkio\Shlink\Core\Util\RedirectResponseHelperInterface;
|
||||
use Shlinkio\Shlink\Core\Visit\RequestTrackerInterface;
|
||||
|
||||
use function str_starts_with;
|
||||
|
||||
class ExtraPathRedirectMiddlewareTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
@@ -74,6 +76,7 @@ class ExtraPathRedirectMiddlewareTest extends TestCase
|
||||
|
||||
$this->middleware->process($request, $this->handler->reveal());
|
||||
|
||||
$this->handler->handle($request)->shouldHaveBeenCalledOnce();
|
||||
$this->resolver->resolveEnabledShortUrl(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$this->requestTracker->trackIfApplicable(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$this->redirectionBuilder->buildShortUrlRedirect(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
@@ -112,49 +115,83 @@ class ExtraPathRedirectMiddlewareTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function handlerIsCalledWhenNoShortUrlIsFound(): void
|
||||
{
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider provideResolves
|
||||
*/
|
||||
public function handlerIsCalledWhenNoShortUrlIsFoundAfterExpectedAmountOfIterations(
|
||||
bool $multiSegmentEnabled,
|
||||
int $expectedResolveCalls,
|
||||
): void {
|
||||
$this->options->multiSegmentSlugsEnabled = $multiSegmentEnabled;
|
||||
|
||||
$type = $this->prophesize(NotFoundType::class);
|
||||
$type->isRegularNotFound()->willReturn(true);
|
||||
$type->isInvalidShortUrl()->willReturn(true);
|
||||
$request = ServerRequestFactory::fromGlobals()->withAttribute(NotFoundType::class, $type->reveal())
|
||||
->withUri(new Uri('/shortCode/bar/baz'));
|
||||
|
||||
$resolve = $this->resolver->resolveEnabledShortUrl(Argument::cetera())->willThrow(
|
||||
ShortUrlNotFoundException::class,
|
||||
);
|
||||
$resolve = $this->resolver->resolveEnabledShortUrl(
|
||||
Argument::that(fn (ShortUrlIdentifier $identifier) => str_starts_with($identifier->shortCode, 'shortCode')),
|
||||
)->willThrow(ShortUrlNotFoundException::class);
|
||||
|
||||
$this->middleware->process($request, $this->handler->reveal());
|
||||
|
||||
$resolve->shouldHaveBeenCalledOnce();
|
||||
$resolve->shouldHaveBeenCalledTimes($expectedResolveCalls);
|
||||
$this->requestTracker->trackIfApplicable(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$this->redirectionBuilder->buildShortUrlRedirect(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
$this->redirectResponseHelper->buildRedirectResponse(Argument::cetera())->shouldNotHaveBeenCalled();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function visitIsTrackedAndRedirectIsReturnedWhenShortUrlIsFound(): void
|
||||
{
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider provideResolves
|
||||
*/
|
||||
public function visitIsTrackedAndRedirectIsReturnedWhenShortUrlIsFoundAfterExpectedAmountOfIterations(
|
||||
bool $multiSegmentEnabled,
|
||||
int $expectedResolveCalls,
|
||||
?string $expectedExtraPath,
|
||||
): void {
|
||||
$this->options->multiSegmentSlugsEnabled = $multiSegmentEnabled;
|
||||
|
||||
$type = $this->prophesize(NotFoundType::class);
|
||||
$type->isRegularNotFound()->willReturn(true);
|
||||
$type->isInvalidShortUrl()->willReturn(true);
|
||||
$request = ServerRequestFactory::fromGlobals()->withAttribute(NotFoundType::class, $type->reveal())
|
||||
->withUri(new Uri('https://doma.in/shortCode/bar/baz'));
|
||||
$shortUrl = ShortUrl::withLongUrl('');
|
||||
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain('shortCode', 'doma.in');
|
||||
|
||||
$resolve = $this->resolver->resolveEnabledShortUrl($identifier)->willReturn($shortUrl);
|
||||
$buildLongUrl = $this->redirectionBuilder->buildShortUrlRedirect($shortUrl, [], '/bar/baz')->willReturn(
|
||||
'the_built_long_url',
|
||||
$identifier = Argument::that(
|
||||
fn (ShortUrlIdentifier $identifier) => str_starts_with($identifier->shortCode, 'shortCode'),
|
||||
);
|
||||
|
||||
$currentIteration = 1;
|
||||
$resolve = $this->resolver->resolveEnabledShortUrl($identifier)->will(
|
||||
function () use ($shortUrl, &$currentIteration, $expectedResolveCalls): ShortUrl {
|
||||
if ($expectedResolveCalls === $currentIteration) {
|
||||
return $shortUrl;
|
||||
}
|
||||
|
||||
$currentIteration++;
|
||||
throw ShortUrlNotFoundException::fromNotFound(ShortUrlIdentifier::fromShortUrl($shortUrl));
|
||||
},
|
||||
);
|
||||
$buildLongUrl = $this->redirectionBuilder->buildShortUrlRedirect($shortUrl, [], $expectedExtraPath)
|
||||
->willReturn('the_built_long_url');
|
||||
$buildResp = $this->redirectResponseHelper->buildRedirectResponse('the_built_long_url')->willReturn(
|
||||
new RedirectResponse(''),
|
||||
);
|
||||
|
||||
$this->middleware->process($request, $this->handler->reveal());
|
||||
|
||||
$resolve->shouldHaveBeenCalledOnce();
|
||||
$resolve->shouldHaveBeenCalledTimes($expectedResolveCalls);
|
||||
$buildLongUrl->shouldHaveBeenCalledOnce();
|
||||
$buildResp->shouldHaveBeenCalledOnce();
|
||||
$this->requestTracker->trackIfApplicable($shortUrl, $request)->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
|
||||
public function provideResolves(): iterable
|
||||
{
|
||||
yield [false, 1, '/bar/baz'];
|
||||
yield [true, 3, null];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user