mirror of
https://github.com/shlinkio/shlink.git
synced 2026-03-11 01:33:11 +08:00
Enforce a schema to be provided when short URLs are created
This commit is contained in:
@@ -58,7 +58,7 @@ class NotifyNewShortUrlToMercureTest extends TestCase
|
||||
#[Test]
|
||||
public function expectedNotificationIsPublished(): void
|
||||
{
|
||||
$shortUrl = ShortUrl::withLongUrl('longUrl');
|
||||
$shortUrl = ShortUrl::withLongUrl('https://longUrl');
|
||||
$update = Update::forTopicAndPayload('', []);
|
||||
|
||||
$this->em->expects($this->once())->method('find')->with(ShortUrl::class, '123')->willReturn($shortUrl);
|
||||
@@ -75,7 +75,7 @@ class NotifyNewShortUrlToMercureTest extends TestCase
|
||||
#[Test]
|
||||
public function messageIsPrintedIfPublishingFails(): void
|
||||
{
|
||||
$shortUrl = ShortUrl::withLongUrl('longUrl');
|
||||
$shortUrl = ShortUrl::withLongUrl('https://longUrl');
|
||||
$update = Update::forTopicAndPayload('', []);
|
||||
$e = new Exception('Error');
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ class PublishingUpdatesGeneratorTest extends TestCase
|
||||
{
|
||||
$shortUrl = ShortUrl::create(ShortUrlCreation::fromRawData([
|
||||
'customSlug' => 'foo',
|
||||
'longUrl' => 'longUrl',
|
||||
'longUrl' => 'https://longUrl',
|
||||
'title' => $title,
|
||||
]));
|
||||
$visit = Visit::forValidShortUrl($shortUrl, Visitor::emptyInstance());
|
||||
@@ -50,7 +50,7 @@ class PublishingUpdatesGeneratorTest extends TestCase
|
||||
'shortUrl' => [
|
||||
'shortCode' => $shortUrl->getShortCode(),
|
||||
'shortUrl' => 'http:/' . $shortUrl->getShortCode(),
|
||||
'longUrl' => 'longUrl',
|
||||
'longUrl' => 'https://longUrl',
|
||||
'deviceLongUrls' => $shortUrl->deviceLongUrls(),
|
||||
'dateCreated' => $shortUrl->getDateCreated()->toAtomString(),
|
||||
'visitsCount' => 0,
|
||||
@@ -115,7 +115,7 @@ class PublishingUpdatesGeneratorTest extends TestCase
|
||||
{
|
||||
$shortUrl = ShortUrl::create(ShortUrlCreation::fromRawData([
|
||||
'customSlug' => 'foo',
|
||||
'longUrl' => 'longUrl',
|
||||
'longUrl' => 'https://longUrl',
|
||||
'title' => 'The title',
|
||||
]));
|
||||
|
||||
@@ -125,7 +125,7 @@ class PublishingUpdatesGeneratorTest extends TestCase
|
||||
self::assertEquals(['shortUrl' => [
|
||||
'shortCode' => $shortUrl->getShortCode(),
|
||||
'shortUrl' => 'http:/' . $shortUrl->getShortCode(),
|
||||
'longUrl' => 'longUrl',
|
||||
'longUrl' => 'https://longUrl',
|
||||
'deviceLongUrls' => $shortUrl->deviceLongUrls(),
|
||||
'dateCreated' => $shortUrl->getDateCreated()->toAtomString(),
|
||||
'visitsCount' => 0,
|
||||
|
||||
@@ -70,7 +70,7 @@ class NotifyNewShortUrlToRabbitMqTest extends TestCase
|
||||
$shortUrlId = '123';
|
||||
$update = Update::forTopicAndPayload(Topic::NEW_SHORT_URL->value, []);
|
||||
$this->em->expects($this->once())->method('find')->with(ShortUrl::class, $shortUrlId)->willReturn(
|
||||
ShortUrl::withLongUrl('longUrl'),
|
||||
ShortUrl::withLongUrl('https://longUrl'),
|
||||
);
|
||||
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with(
|
||||
$this->isInstanceOf(ShortUrl::class),
|
||||
@@ -87,7 +87,7 @@ class NotifyNewShortUrlToRabbitMqTest extends TestCase
|
||||
$shortUrlId = '123';
|
||||
$update = Update::forTopicAndPayload(Topic::NEW_SHORT_URL->value, []);
|
||||
$this->em->expects($this->once())->method('find')->with(ShortUrl::class, $shortUrlId)->willReturn(
|
||||
ShortUrl::withLongUrl('longUrl'),
|
||||
ShortUrl::withLongUrl('https://longUrl'),
|
||||
);
|
||||
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with(
|
||||
$this->isInstanceOf(ShortUrl::class),
|
||||
|
||||
@@ -98,7 +98,7 @@ class NotifyVisitToRabbitMqTest extends TestCase
|
||||
yield 'non-orphan visit' => [
|
||||
Visit::forValidShortUrl(
|
||||
ShortUrl::create(ShortUrlCreation::fromRawData([
|
||||
'longUrl' => 'foo',
|
||||
'longUrl' => 'https://foo',
|
||||
'customSlug' => 'bar',
|
||||
])),
|
||||
$visitor,
|
||||
@@ -152,7 +152,7 @@ class NotifyVisitToRabbitMqTest extends TestCase
|
||||
{
|
||||
yield 'legacy non-orphan visit' => [
|
||||
true,
|
||||
$visit = Visit::forValidShortUrl(ShortUrl::withLongUrl('longUrl'), Visitor::emptyInstance()),
|
||||
$visit = Visit::forValidShortUrl(ShortUrl::withLongUrl('https://longUrl'), Visitor::emptyInstance()),
|
||||
noop(...),
|
||||
function (MockObject & PublishingHelperInterface $helper) use ($visit): void {
|
||||
$helper->method('publishUpdate')->with(self::callback(function (Update $update) use ($visit): bool {
|
||||
@@ -183,7 +183,7 @@ class NotifyVisitToRabbitMqTest extends TestCase
|
||||
];
|
||||
yield 'non-legacy non-orphan visit' => [
|
||||
false,
|
||||
Visit::forValidShortUrl(ShortUrl::withLongUrl('longUrl'), Visitor::emptyInstance()),
|
||||
Visit::forValidShortUrl(ShortUrl::withLongUrl('https://longUrl'), Visitor::emptyInstance()),
|
||||
function (MockObject & PublishingUpdatesGeneratorInterface $updatesGenerator): void {
|
||||
$update = Update::forTopicAndPayload('', []);
|
||||
$updatesGenerator->expects(self::never())->method('newOrphanVisitUpdate');
|
||||
|
||||
@@ -54,7 +54,7 @@ class NotifyNewShortUrlToRedisTest extends TestCase
|
||||
$shortUrlId = '123';
|
||||
$update = Update::forTopicAndPayload(Topic::NEW_SHORT_URL->value, []);
|
||||
$this->em->expects($this->once())->method('find')->with(ShortUrl::class, $shortUrlId)->willReturn(
|
||||
ShortUrl::withLongUrl('longUrl'),
|
||||
ShortUrl::withLongUrl('https://longUrl'),
|
||||
);
|
||||
$this->updatesGenerator->expects($this->once())->method('newShortUrlUpdate')->with(
|
||||
$this->isInstanceOf(ShortUrl::class),
|
||||
|
||||
@@ -117,11 +117,11 @@ class ImportedLinksProcessorTest extends TestCase
|
||||
public function alreadyImportedUrlsAreSkipped(): void
|
||||
{
|
||||
$urls = [
|
||||
new ImportedShlinkUrl(ImportSource::BITLY, 'foo', [], Chronos::now(), null, 'foo', null),
|
||||
new ImportedShlinkUrl(ImportSource::BITLY, 'bar', [], Chronos::now(), null, 'bar', null),
|
||||
new ImportedShlinkUrl(ImportSource::BITLY, 'baz', [], Chronos::now(), null, 'baz', null),
|
||||
new ImportedShlinkUrl(ImportSource::BITLY, 'baz2', [], Chronos::now(), null, 'baz2', null),
|
||||
new ImportedShlinkUrl(ImportSource::BITLY, 'baz3', [], Chronos::now(), null, 'baz3', null),
|
||||
new ImportedShlinkUrl(ImportSource::BITLY, 'https://foo', [], Chronos::now(), null, 'foo', null),
|
||||
new ImportedShlinkUrl(ImportSource::BITLY, 'https://bar', [], Chronos::now(), null, 'bar', null),
|
||||
new ImportedShlinkUrl(ImportSource::BITLY, 'https://baz', [], Chronos::now(), null, 'baz', null),
|
||||
new ImportedShlinkUrl(ImportSource::BITLY, 'https://baz2', [], Chronos::now(), null, 'baz2', null),
|
||||
new ImportedShlinkUrl(ImportSource::BITLY, 'https://baz3', [], Chronos::now(), null, 'baz3', null),
|
||||
];
|
||||
|
||||
$this->em->method('getRepository')->with(ShortUrl::class)->willReturn($this->repo);
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -47,8 +47,10 @@ class VisitLocatorTest extends TestCase
|
||||
): void {
|
||||
$unlocatedVisits = map(
|
||||
range(1, 200),
|
||||
fn (int $i) =>
|
||||
Visit::forValidShortUrl(ShortUrl::withLongUrl(sprintf('short_code_%s', $i)), Visitor::emptyInstance()),
|
||||
fn (int $i) => Visit::forValidShortUrl(
|
||||
ShortUrl::withLongUrl(sprintf('https://short_code_%s', $i)),
|
||||
Visitor::emptyInstance(),
|
||||
),
|
||||
);
|
||||
|
||||
$this->repo->expects($this->once())->method($expectedRepoMethodName)->willReturn($unlocatedVisits);
|
||||
@@ -85,7 +87,7 @@ class VisitLocatorTest extends TestCase
|
||||
bool $isNonLocatableAddress,
|
||||
): void {
|
||||
$unlocatedVisits = [
|
||||
Visit::forValidShortUrl(ShortUrl::withLongUrl('foo'), Visitor::emptyInstance()),
|
||||
Visit::forValidShortUrl(ShortUrl::withLongUrl('https://foo'), Visitor::emptyInstance()),
|
||||
];
|
||||
|
||||
$this->repo->expects($this->once())->method($expectedRepoMethodName)->willReturn($unlocatedVisits);
|
||||
|
||||
Reference in New Issue
Block a user