mirror of
https://github.com/shlinkio/shlink.git
synced 2025-02-25 18:45:27 -06:00
Enforce a schema to be provided when short URLs are created
This commit is contained in:
@@ -43,7 +43,9 @@ class ShortUrlTest extends TestCase
|
||||
public static function provideInvalidShortUrls(): iterable
|
||||
{
|
||||
yield 'with custom slug' => [
|
||||
ShortUrl::create(ShortUrlCreation::fromRawData(['customSlug' => 'custom-slug', 'longUrl' => 'longUrl'])),
|
||||
ShortUrl::create(
|
||||
ShortUrlCreation::fromRawData(['customSlug' => 'custom-slug', 'longUrl' => 'https://longUrl']),
|
||||
),
|
||||
'The short code cannot be regenerated on ShortUrls where a custom slug was provided.',
|
||||
];
|
||||
yield 'already persisted' => [
|
||||
@@ -68,7 +70,7 @@ class ShortUrlTest extends TestCase
|
||||
{
|
||||
yield 'no custom slug' => [ShortUrl::createFake()];
|
||||
yield 'imported with custom slug' => [ShortUrl::fromImport(
|
||||
new ImportedShlinkUrl(ImportSource::BITLY, 'longUrl', [], Chronos::now(), null, 'custom-slug', null),
|
||||
new ImportedShlinkUrl(ImportSource::BITLY, 'https://url', [], Chronos::now(), null, 'custom-slug', null),
|
||||
true,
|
||||
)];
|
||||
}
|
||||
@@ -77,7 +79,7 @@ class ShortUrlTest extends TestCase
|
||||
public function shortCodesHaveExpectedLength(?int $length, int $expectedLength): void
|
||||
{
|
||||
$shortUrl = ShortUrl::create(ShortUrlCreation::fromRawData(
|
||||
[ShortUrlInputFilter::SHORT_CODE_LENGTH => $length, 'longUrl' => 'longUrl'],
|
||||
[ShortUrlInputFilter::SHORT_CODE_LENGTH => $length, 'longUrl' => 'https://longUrl'],
|
||||
));
|
||||
|
||||
self::assertEquals($expectedLength, strlen($shortUrl->getShortCode()));
|
||||
@@ -92,7 +94,7 @@ class ShortUrlTest extends TestCase
|
||||
#[Test]
|
||||
public function deviceLongUrlsAreUpdated(): void
|
||||
{
|
||||
$shortUrl = ShortUrl::withLongUrl('foo');
|
||||
$shortUrl = ShortUrl::withLongUrl('https://foo');
|
||||
|
||||
$shortUrl->update(ShortUrlEdition::fromRawData([
|
||||
ShortUrlInputFilter::DEVICE_LONG_URLS => [
|
||||
|
||||
@@ -29,7 +29,7 @@ class ShortUrlStringifierTest extends TestCase
|
||||
{
|
||||
$shortUrlWithShortCode = fn (string $shortCode, ?string $domain = null) => ShortUrl::create(
|
||||
ShortUrlCreation::fromRawData([
|
||||
'longUrl' => 'longUrl',
|
||||
'longUrl' => 'https://longUrl',
|
||||
'customSlug' => $shortCode,
|
||||
'domain' => $domain,
|
||||
]),
|
||||
|
||||
@@ -136,7 +136,7 @@ class ExtraPathRedirectMiddlewareTest extends TestCase
|
||||
$type->method('isInvalidShortUrl')->willReturn(true);
|
||||
$request = ServerRequestFactory::fromGlobals()->withAttribute(NotFoundType::class, $type)
|
||||
->withUri(new Uri('https://s.test/shortCode/bar/baz'));
|
||||
$shortUrl = ShortUrl::withLongUrl('longUrl');
|
||||
$shortUrl = ShortUrl::withLongUrl('https://longUrl');
|
||||
|
||||
$currentIteration = 1;
|
||||
$this->resolver->expects($this->exactly($expectedResolveCalls))->method('resolveEnabledShortUrl')->with(
|
||||
|
||||
@@ -115,7 +115,7 @@ class ShortUrlCreationTest extends TestCase
|
||||
$creation = ShortUrlCreation::fromRawData([
|
||||
'validSince' => Chronos::parse('2015-01-01')->toAtomString(),
|
||||
'customSlug' => $customSlug,
|
||||
'longUrl' => 'longUrl',
|
||||
'longUrl' => 'https://longUrl',
|
||||
], new UrlShortenerOptions(multiSegmentSlugsEnabled: $multiSegmentEnabled, mode: $shortUrlMode));
|
||||
|
||||
self::assertTrue($creation->hasValidSince());
|
||||
@@ -161,7 +161,7 @@ class ShortUrlCreationTest extends TestCase
|
||||
{
|
||||
$creation = ShortUrlCreation::fromRawData([
|
||||
'title' => $title,
|
||||
'longUrl' => 'longUrl',
|
||||
'longUrl' => 'https://longUrl',
|
||||
]);
|
||||
|
||||
self::assertEquals($expectedTitle, $creation->title);
|
||||
@@ -184,7 +184,7 @@ class ShortUrlCreationTest extends TestCase
|
||||
{
|
||||
$creation = ShortUrlCreation::fromRawData([
|
||||
'domain' => $domain,
|
||||
'longUrl' => 'longUrl',
|
||||
'longUrl' => 'https://longUrl',
|
||||
]);
|
||||
|
||||
self::assertSame($expectedDomain, $creation->domain);
|
||||
|
||||
@@ -31,23 +31,29 @@ class ShortUrlEditionTest extends TestCase
|
||||
yield 'null' => [null, [], []];
|
||||
yield 'empty' => [[], [], []];
|
||||
yield 'only new urls' => [[
|
||||
DeviceType::DESKTOP->value => 'foo',
|
||||
DeviceType::IOS->value => 'bar',
|
||||
DeviceType::DESKTOP->value => 'https://foo',
|
||||
DeviceType::IOS->value => 'https://bar',
|
||||
], [
|
||||
DeviceType::DESKTOP->value => DeviceLongUrlPair::fromRawTypeAndLongUrl(DeviceType::DESKTOP->value, 'foo'),
|
||||
DeviceType::IOS->value => DeviceLongUrlPair::fromRawTypeAndLongUrl(DeviceType::IOS->value, 'bar'),
|
||||
DeviceType::DESKTOP->value => DeviceLongUrlPair::fromRawTypeAndLongUrl(
|
||||
DeviceType::DESKTOP->value,
|
||||
'https://foo',
|
||||
),
|
||||
DeviceType::IOS->value => DeviceLongUrlPair::fromRawTypeAndLongUrl(DeviceType::IOS->value, 'https://bar'),
|
||||
], []];
|
||||
yield 'only urls to remove' => [[
|
||||
DeviceType::ANDROID->value => null,
|
||||
DeviceType::IOS->value => null,
|
||||
], [], [DeviceType::ANDROID, DeviceType::IOS]];
|
||||
yield 'both' => [[
|
||||
DeviceType::DESKTOP->value => 'bar',
|
||||
DeviceType::IOS->value => 'foo',
|
||||
DeviceType::DESKTOP->value => 'https://bar',
|
||||
DeviceType::IOS->value => 'https://foo',
|
||||
DeviceType::ANDROID->value => null,
|
||||
], [
|
||||
DeviceType::DESKTOP->value => DeviceLongUrlPair::fromRawTypeAndLongUrl(DeviceType::DESKTOP->value, 'bar'),
|
||||
DeviceType::IOS->value => DeviceLongUrlPair::fromRawTypeAndLongUrl(DeviceType::IOS->value, 'foo'),
|
||||
DeviceType::DESKTOP->value => DeviceLongUrlPair::fromRawTypeAndLongUrl(
|
||||
DeviceType::DESKTOP->value,
|
||||
'https://bar',
|
||||
),
|
||||
DeviceType::IOS->value => DeviceLongUrlPair::fromRawTypeAndLongUrl(DeviceType::IOS->value, 'https://foo'),
|
||||
], [DeviceType::ANDROID]];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ class ShortUrlResolverTest extends TestCase
|
||||
#[Test, DataProvider('provideAdminApiKeys')]
|
||||
public function shortCodeIsProperlyParsed(?ApiKey $apiKey): void
|
||||
{
|
||||
$shortUrl = ShortUrl::withLongUrl('expected_url');
|
||||
$shortUrl = ShortUrl::withLongUrl('https://expected_url');
|
||||
$shortCode = $shortUrl->getShortCode();
|
||||
$identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode);
|
||||
|
||||
@@ -76,7 +76,7 @@ class ShortUrlResolverTest extends TestCase
|
||||
#[Test]
|
||||
public function shortCodeToEnabledShortUrlProperlyParsesShortCode(): void
|
||||
{
|
||||
$shortUrl = ShortUrl::withLongUrl('expected_url');
|
||||
$shortUrl = ShortUrl::withLongUrl('https://expected_url');
|
||||
$shortCode = $shortUrl->getShortCode();
|
||||
|
||||
$this->repo->expects($this->once())->method('findOneWithDomainFallback')->with(
|
||||
@@ -111,7 +111,9 @@ class ShortUrlResolverTest extends TestCase
|
||||
$now = Chronos::now();
|
||||
|
||||
yield 'maxVisits reached' => [(function () {
|
||||
$shortUrl = ShortUrl::create(ShortUrlCreation::fromRawData(['maxVisits' => 3, 'longUrl' => 'longUrl']));
|
||||
$shortUrl = ShortUrl::create(
|
||||
ShortUrlCreation::fromRawData(['maxVisits' => 3, 'longUrl' => 'https://longUrl']),
|
||||
);
|
||||
$shortUrl->setVisits(new ArrayCollection(map(
|
||||
range(0, 4),
|
||||
fn () => Visit::forValidShortUrl($shortUrl, Visitor::emptyInstance()),
|
||||
@@ -120,16 +122,16 @@ class ShortUrlResolverTest extends TestCase
|
||||
return $shortUrl;
|
||||
})()];
|
||||
yield 'future validSince' => [ShortUrl::create(ShortUrlCreation::fromRawData(
|
||||
['validSince' => $now->addMonth()->toAtomString(), 'longUrl' => 'longUrl'],
|
||||
['validSince' => $now->addMonth()->toAtomString(), 'longUrl' => 'https://longUrl'],
|
||||
))];
|
||||
yield 'past validUntil' => [ShortUrl::create(ShortUrlCreation::fromRawData(
|
||||
['validUntil' => $now->subMonth()->toAtomString(), 'longUrl' => 'longUrl'],
|
||||
['validUntil' => $now->subMonth()->toAtomString(), 'longUrl' => 'https://longUrl'],
|
||||
))];
|
||||
yield 'mixed' => [(function () use ($now) {
|
||||
$shortUrl = ShortUrl::create(ShortUrlCreation::fromRawData([
|
||||
'maxVisits' => 3,
|
||||
'validUntil' => $now->subMonth()->toAtomString(),
|
||||
'longUrl' => 'longUrl',
|
||||
'longUrl' => 'https://longUrl',
|
||||
]));
|
||||
$shortUrl->setVisits(new ArrayCollection(map(
|
||||
range(0, 4),
|
||||
|
||||
@@ -57,7 +57,7 @@ class ShortUrlServiceTest extends TestCase
|
||||
ShortUrlEdition $shortUrlEdit,
|
||||
?ApiKey $apiKey,
|
||||
): void {
|
||||
$originalLongUrl = 'originalLongUrl';
|
||||
$originalLongUrl = 'https://originalLongUrl';
|
||||
$shortUrl = ShortUrl::withLongUrl($originalLongUrl);
|
||||
|
||||
$this->urlResolver->expects($this->once())->method('resolveShortUrl')->with(
|
||||
@@ -103,16 +103,16 @@ class ShortUrlServiceTest extends TestCase
|
||||
yield 'long URL and API key' => [new InvokedCount(1), ShortUrlEdition::fromRawData([
|
||||
'validSince' => Chronos::parse('2017-01-01 00:00:00')->toAtomString(),
|
||||
'maxVisits' => 10,
|
||||
'longUrl' => 'modifiedLongUrl',
|
||||
'longUrl' => 'https://modifiedLongUrl',
|
||||
]), ApiKey::create()];
|
||||
yield 'long URL with validation' => [new InvokedCount(1), ShortUrlEdition::fromRawData([
|
||||
'longUrl' => 'modifiedLongUrl',
|
||||
'longUrl' => 'https://modifiedLongUrl',
|
||||
'validateUrl' => true,
|
||||
]), null];
|
||||
yield 'device redirects' => [new InvokedCount(0), ShortUrlEdition::fromRawData([
|
||||
'deviceLongUrls' => [
|
||||
DeviceType::IOS->value => 'iosLongUrl',
|
||||
DeviceType::ANDROID->value => 'androidLongUrl',
|
||||
DeviceType::IOS->value => 'https://iosLongUrl',
|
||||
DeviceType::ANDROID->value => 'https://androidLongUrl',
|
||||
],
|
||||
]), null];
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ class ShortUrlDataTransformerTest extends TestCase
|
||||
]];
|
||||
yield 'max visits only' => [ShortUrl::create(ShortUrlCreation::fromRawData([
|
||||
'maxVisits' => $maxVisits,
|
||||
'longUrl' => 'longUrl',
|
||||
'longUrl' => 'https://longUrl',
|
||||
])), [
|
||||
'validSince' => null,
|
||||
'validUntil' => null,
|
||||
@@ -52,7 +52,7 @@ class ShortUrlDataTransformerTest extends TestCase
|
||||
]];
|
||||
yield 'max visits and valid since' => [
|
||||
ShortUrl::create(ShortUrlCreation::fromRawData(
|
||||
['validSince' => $now, 'maxVisits' => $maxVisits, 'longUrl' => 'longUrl'],
|
||||
['validSince' => $now, 'maxVisits' => $maxVisits, 'longUrl' => 'https://longUrl'],
|
||||
)),
|
||||
[
|
||||
'validSince' => $now->toAtomString(),
|
||||
@@ -62,7 +62,7 @@ class ShortUrlDataTransformerTest extends TestCase
|
||||
];
|
||||
yield 'both dates' => [
|
||||
ShortUrl::create(ShortUrlCreation::fromRawData(
|
||||
['validSince' => $now, 'validUntil' => $now->subDays(10), 'longUrl' => 'longUrl'],
|
||||
['validSince' => $now, 'validUntil' => $now->subDays(10), 'longUrl' => 'https://longUrl'],
|
||||
)),
|
||||
[
|
||||
'validSince' => $now->toAtomString(),
|
||||
@@ -75,7 +75,7 @@ class ShortUrlDataTransformerTest extends TestCase
|
||||
'validSince' => $now,
|
||||
'validUntil' => $now->subDays(5),
|
||||
'maxVisits' => $maxVisits,
|
||||
'longUrl' => 'longUrl',
|
||||
'longUrl' => 'https://longUrl',
|
||||
])),
|
||||
[
|
||||
'validSince' => $now->toAtomString(),
|
||||
|
||||
Reference in New Issue
Block a user