mirror of
https://github.com/shlinkio/shlink.git
synced 2025-03-31 13:54:55 +03:00
Add E2E tests for dynamic rule-based redirects
This commit is contained in:
parent
07ae92943d
commit
df5ad554c1
5 changed files with 106 additions and 10 deletions
|
@ -71,7 +71,7 @@
|
||||||
"phpunit/phpunit": "^10.4",
|
"phpunit/phpunit": "^10.4",
|
||||||
"roave/security-advisories": "dev-master",
|
"roave/security-advisories": "dev-master",
|
||||||
"shlinkio/php-coding-standard": "~2.3.0",
|
"shlinkio/php-coding-standard": "~2.3.0",
|
||||||
"shlinkio/shlink-test-utils": "^4.0",
|
"shlinkio/shlink-test-utils": "^4.1",
|
||||||
"symfony/var-dumper": "^7.0",
|
"symfony/var-dumper": "^7.0",
|
||||||
"veewee/composer-run-parallel": "^1.3"
|
"veewee/composer-run-parallel": "^1.3"
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,8 +16,8 @@ class RedirectCondition extends AbstractEntity
|
||||||
private function __construct(
|
private function __construct(
|
||||||
public readonly string $name,
|
public readonly string $name,
|
||||||
private readonly RedirectConditionType $type,
|
private readonly RedirectConditionType $type,
|
||||||
public readonly string $matchValue,
|
private readonly string $matchValue,
|
||||||
public readonly ?string $matchKey = null,
|
private readonly ?string $matchKey = null,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ class ShortUrlRedirectRule extends AbstractEntity
|
||||||
private readonly ShortUrl $shortUrl, // No need to read this field. It's used by doctrine
|
private readonly ShortUrl $shortUrl, // No need to read this field. It's used by doctrine
|
||||||
private readonly int $priority,
|
private readonly int $priority,
|
||||||
public readonly string $longUrl,
|
public readonly string $longUrl,
|
||||||
public readonly Collection $conditions = new ArrayCollection(),
|
private Collection $conditions = new ArrayCollection(),
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace ShlinkioApiTest\Shlink\Core\Action;
|
namespace ShlinkioApiTest\Shlink\Core\Action;
|
||||||
|
|
||||||
|
use GuzzleHttp\RequestOptions;
|
||||||
use PHPUnit\Framework\Attributes\DataProvider;
|
use PHPUnit\Framework\Attributes\DataProvider;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
use PHPUnit\Framework\Attributes\Test;
|
||||||
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
||||||
|
@ -15,9 +16,9 @@ use const ShlinkioTest\Shlink\IOS_USER_AGENT;
|
||||||
class RedirectTest extends ApiTestCase
|
class RedirectTest extends ApiTestCase
|
||||||
{
|
{
|
||||||
#[Test, DataProvider('provideUserAgents')]
|
#[Test, DataProvider('provideUserAgents')]
|
||||||
public function properRedirectHappensBasedOnUserAgent(?string $userAgent, string $expectedRedirect): void
|
public function properRedirectHappensBasedOnUserAgent(array $options, string $expectedRedirect): void
|
||||||
{
|
{
|
||||||
$response = $this->callShortUrl('def456', $userAgent);
|
$response = $this->callShortUrl('def456', $options);
|
||||||
|
|
||||||
self::assertEquals(302, $response->getStatusCode());
|
self::assertEquals(302, $response->getStatusCode());
|
||||||
self::assertEquals($expectedRedirect, $response->getHeaderLine('Location'));
|
self::assertEquals($expectedRedirect, $response->getHeaderLine('Location'));
|
||||||
|
@ -25,15 +26,48 @@ class RedirectTest extends ApiTestCase
|
||||||
|
|
||||||
public static function provideUserAgents(): iterable
|
public static function provideUserAgents(): iterable
|
||||||
{
|
{
|
||||||
yield 'android' => [ANDROID_USER_AGENT, 'https://blog.alejandrocelaya.com/android'];
|
yield 'android' => [
|
||||||
yield 'ios' => [IOS_USER_AGENT, 'https://blog.alejandrocelaya.com/ios'];
|
[
|
||||||
|
RequestOptions::HEADERS => ['User-Agent' => ANDROID_USER_AGENT],
|
||||||
|
],
|
||||||
|
'https://blog.alejandrocelaya.com/android',
|
||||||
|
];
|
||||||
|
yield 'ios' => [
|
||||||
|
[
|
||||||
|
RequestOptions::HEADERS => ['User-Agent' => IOS_USER_AGENT],
|
||||||
|
],
|
||||||
|
'https://blog.alejandrocelaya.com/ios',
|
||||||
|
];
|
||||||
yield 'desktop' => [
|
yield 'desktop' => [
|
||||||
DESKTOP_USER_AGENT,
|
[
|
||||||
|
RequestOptions::HEADERS => ['User-Agent' => DESKTOP_USER_AGENT],
|
||||||
|
],
|
||||||
'https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/',
|
'https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/',
|
||||||
];
|
];
|
||||||
yield 'unknown' => [
|
yield 'unknown' => [
|
||||||
null,
|
[],
|
||||||
'https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/',
|
'https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/',
|
||||||
];
|
];
|
||||||
|
yield 'rule: english and foo' => [
|
||||||
|
[
|
||||||
|
RequestOptions::HEADERS => [
|
||||||
|
'Accept-Language' => 'en-UK',
|
||||||
|
],
|
||||||
|
RequestOptions::QUERY => ['foo' => 'bar'],
|
||||||
|
],
|
||||||
|
'https://example.com/english-and-foo-query?foo=bar',
|
||||||
|
];
|
||||||
|
yield 'rule: multiple query params' => [
|
||||||
|
[
|
||||||
|
RequestOptions::QUERY => ['foo' => 'bar', 'hello' => 'world'],
|
||||||
|
],
|
||||||
|
'https://example.com/multiple-query-params?foo=bar&hello=world',
|
||||||
|
];
|
||||||
|
yield 'rule: english' => [
|
||||||
|
[
|
||||||
|
RequestOptions::HEADERS => ['Accept-Language' => 'en-UK'],
|
||||||
|
],
|
||||||
|
'https://example.com/only-english',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace ShlinkioApiTest\Shlink\Rest\Fixtures;
|
||||||
|
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
use Doctrine\Common\DataFixtures\AbstractFixture;
|
||||||
|
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
|
||||||
|
use Doctrine\Persistence\ObjectManager;
|
||||||
|
use Shlinkio\Shlink\Core\RedirectRule\Entity\RedirectCondition;
|
||||||
|
use Shlinkio\Shlink\Core\RedirectRule\Entity\ShortUrlRedirectRule;
|
||||||
|
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
|
||||||
|
|
||||||
|
class ShortUrlRedirectRulesFixture extends AbstractFixture implements DependentFixtureInterface
|
||||||
|
{
|
||||||
|
public function getDependencies(): array
|
||||||
|
{
|
||||||
|
return [ShortUrlsFixture::class];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function load(ObjectManager $manager): void
|
||||||
|
{
|
||||||
|
/** @var ShortUrl $defShortUrl */
|
||||||
|
$defShortUrl = $this->getReference('def456_short_url');
|
||||||
|
|
||||||
|
$englishCondition = RedirectCondition::forLanguage('en-UK');
|
||||||
|
$manager->persist($englishCondition);
|
||||||
|
|
||||||
|
$fooQueryCondition = RedirectCondition::forQueryParam('foo', 'bar');
|
||||||
|
$manager->persist($fooQueryCondition);
|
||||||
|
|
||||||
|
$helloQueryCondition = RedirectCondition::forQueryParam('hello', 'world');
|
||||||
|
$manager->persist($helloQueryCondition);
|
||||||
|
|
||||||
|
$englishAndFooQueryRule = new ShortUrlRedirectRule(
|
||||||
|
$defShortUrl,
|
||||||
|
1,
|
||||||
|
'https://example.com/english-and-foo-query',
|
||||||
|
new ArrayCollection([$englishCondition, $fooQueryCondition]),
|
||||||
|
);
|
||||||
|
$manager->persist($englishAndFooQueryRule);
|
||||||
|
|
||||||
|
$multipleQueryParamsRule = new ShortUrlRedirectRule(
|
||||||
|
$defShortUrl,
|
||||||
|
2,
|
||||||
|
'https://example.com/multiple-query-params',
|
||||||
|
new ArrayCollection([$helloQueryCondition, $fooQueryCondition]),
|
||||||
|
);
|
||||||
|
$manager->persist($multipleQueryParamsRule);
|
||||||
|
|
||||||
|
$onlyEnglishRule = new ShortUrlRedirectRule(
|
||||||
|
$defShortUrl,
|
||||||
|
3,
|
||||||
|
'https://example.com/only-english',
|
||||||
|
new ArrayCollection([$englishCondition]),
|
||||||
|
);
|
||||||
|
$manager->persist($onlyEnglishRule);
|
||||||
|
|
||||||
|
$manager->flush();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue