Update to PHPUnit 10

This commit is contained in:
Alejandro Celaya
2023-02-09 09:32:38 +01:00
parent ad44a8441a
commit 650a286982
131 changed files with 335 additions and 315 deletions

View File

@@ -22,7 +22,7 @@ class RedirectTest extends ApiTestCase
self::assertEquals($expectedRedirect, $response->getHeaderLine('Location'));
}
public function provideUserAgents(): iterable
public static function provideUserAgents(): iterable
{
yield 'android' => [ANDROID_USER_AGENT, 'https://blog.alejandrocelaya.com/android'];
yield 'ios' => [IOS_USER_AGENT, 'https://blog.alejandrocelaya.com/ios'];

View File

@@ -52,7 +52,7 @@ class TagsPaginatorAdapterTest extends DatabaseTestCase
self::assertEquals($expectedTotalCount, $adapter->getNbResults());
}
public function provideFilters(): iterable
public static function provideFilters(): iterable
{
yield [null, null, 0, 10, ['another', 'bar', 'baz', 'foo'], 4];
yield [null, null, 2, 10, ['baz', 'foo'], 4];

View File

@@ -109,7 +109,7 @@ class TagRepositoryTest extends DatabaseTestCase
}
}
public function provideFilters(): iterable
public static function provideFilters(): iterable
{
$defaultList = [
['another', 0, 0, 0],

View File

@@ -56,7 +56,7 @@ class VisitLocationRepositoryTest extends DatabaseTestCase
self::assertCount(6, [...$all]);
}
public function provideBlockSize(): iterable
public static function provideBlockSize(): iterable
{
return map(range(1, 10), fn (int $value) => [$value]);
}

View File

@@ -87,7 +87,7 @@ class QrCodeActionTest extends TestCase
self::assertEquals($expectedContentType, $resp->getHeaderLine('Content-Type'));
}
public function provideQueries(): iterable
public static function provideQueries(): iterable
{
yield 'no format, png default' => ['png', [], 'image/png'];
yield 'no format, svg default' => ['svg', [], 'image/svg+xml'];
@@ -122,7 +122,7 @@ class QrCodeActionTest extends TestCase
self::assertEquals($expectedSize, $size);
}
public function provideRequestsWithSize(): iterable
public static function provideRequestsWithSize(): iterable
{
yield 'different margin and size defaults' => [
new QrCodeOptions(size: 660, margin: 40),
@@ -215,7 +215,7 @@ class QrCodeActionTest extends TestCase
self::assertEquals($color, $expectedColor);
}
public function provideRoundBlockSize(): iterable
public static function provideRoundBlockSize(): iterable
{
yield 'no round block param' => [new QrCodeOptions(), null, self::WHITE];
yield 'no round block param, but disabled by default' => [

View File

@@ -39,7 +39,7 @@ class RobotsActionTest extends TestCase
self::assertEquals('text/plain', $response->getHeaderLine('Content-Type'));
}
public function provideShortCodes(): iterable
public static function provideShortCodes(): iterable
{
yield 'three short codes' => [['foo', 'bar', 'baz'], <<<ROBOTS
# For more information about the robots.txt standard, see:

View File

@@ -32,7 +32,7 @@ class EnvVarsTest extends TestCase
self::assertEquals($exists, $envVar->existsInEnv());
}
public function provideExistingEnvVars(): iterable
public static function provideExistingEnvVars(): iterable
{
yield 'DB_NAME' => [EnvVars::DB_NAME, true];
yield 'BASE_PATH' => [EnvVars::BASE_PATH, true];
@@ -49,7 +49,7 @@ class EnvVarsTest extends TestCase
self::assertEquals($expected, $envVar->loadFromEnv($default));
}
public function provideEnvVarsValues(): iterable
public static function provideEnvVarsValues(): iterable
{
yield 'DB_NAME without default' => [EnvVars::DB_NAME, 'shlink', null];
yield 'DB_NAME with default' => [EnvVars::DB_NAME, 'shlink', 'foobar'];

View File

@@ -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,
),

View File

@@ -31,7 +31,7 @@ class BasePathPrefixerTest extends TestCase
self::assertEquals($expectedMiddlewares, $middlewares);
}
public function provideConfig(): iterable
public static function provideConfig(): iterable
{
yield 'with empty options' => [['routes' => []], [], []];
yield 'with non-empty options' => [

View File

@@ -25,7 +25,7 @@ class MultiSegmentSlugProcessorTest extends TestCase
self::assertEquals($expectedRoutes, ($this->processor)($config)['routes'] ?? []);
}
public function provideConfigs(): iterable
public static function provideConfigs(): iterable
{
yield [[], []];
yield [['url_shortener' => []], []];

View File

@@ -29,7 +29,7 @@ class ShortUrlMethodsProcessorTest extends TestCase
self::assertEquals($expectedRoutes, ($this->processor)($config)['routes'] ?? null);
}
public function provideConfigs(): iterable
public static function provideConfigs(): iterable
{
$buildConfigWithStatus = static fn (int $status, ?array $expectedAllowedMethods) => [[
'routes' => [

View File

@@ -44,7 +44,7 @@ class DomainServiceTest extends TestCase
self::assertEquals($expectedResult, $result);
}
public function provideExcludedDomains(): iterable
public static function provideExcludedDomains(): iterable
{
$default = DomainItem::forDefaultDomain('default.com', new EmptyNotFoundRedirectConfig());
$adminApiKey = ApiKey::create();
@@ -190,7 +190,7 @@ class DomainServiceTest extends TestCase
self::assertEquals('baz.com', $result->invalidShortUrlRedirect());
}
public function provideFoundDomains(): iterable
public static function provideFoundDomains(): iterable
{
$domain = Domain::withAuthority('');
$adminApiKey = ApiKey::create();

View File

@@ -6,6 +6,7 @@ namespace ShlinkioTest\Shlink\Core\ErrorHandler;
use Laminas\Diactoros\Response;
use Laminas\Diactoros\ServerRequestFactory;
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\ServerRequestInterface;
@@ -58,40 +59,39 @@ class NotFoundRedirectHandlerTest extends TestCase
self::assertSame($expectedResp, $result);
}
public function provideNonRedirectScenarios(): iterable
public static function provideNonRedirectScenarios(): iterable
{
yield 'no domain' => [function (
MockObject&DomainServiceInterface $domainService,
MockObject&NotFoundRedirectResolverInterface $resolver,
): void {
$domainService->expects($this->once())->method('findByAuthority')->withAnyParameters()->willReturn(
$domainService->expects(self::once())->method('findByAuthority')->withAnyParameters()->willReturn(
null,
);
$resolver->expects($this->once())->method('resolveRedirectResponse')->with(
$this->isInstanceOf(NotFoundType::class),
$this->isInstanceOf(NotFoundRedirectOptions::class),
$this->isInstanceOf(UriInterface::class),
$resolver->expects(self::once())->method('resolveRedirectResponse')->with(
self::isInstanceOf(NotFoundType::class),
self::isInstanceOf(NotFoundRedirectOptions::class),
self::isInstanceOf(UriInterface::class),
)->willReturn(null);
}];
yield 'non-redirecting domain' => [function (
MockObject&DomainServiceInterface $domainService,
MockObject&NotFoundRedirectResolverInterface $resolver,
): void {
$domainService->expects($this->once())->method('findByAuthority')->withAnyParameters()->willReturn(
$domainService->expects(self::once())->method('findByAuthority')->withAnyParameters()->willReturn(
Domain::withAuthority(''),
);
$resolver->expects($this->exactly(2))->method('resolveRedirectResponse')->withConsecutive(
[
$this->isInstanceOf(NotFoundType::class),
$this->isInstanceOf(Domain::class),
$this->isInstanceOf(UriInterface::class),
],
[
$this->isInstanceOf(NotFoundType::class),
$this->isInstanceOf(NotFoundRedirectOptions::class),
$this->isInstanceOf(UriInterface::class),
],
)->willReturn(null);
$callCount = 0;
$resolver->expects(self::exactly(2))->method('resolveRedirectResponse')->willReturnCallback(
function (mixed $arg1, mixed $arg2, mixed $arg3) use (&$callCount) {
Assert::assertInstanceOf(NotFoundType::class, $arg1);
Assert::assertInstanceOf($callCount === 0 ? Domain::class : NotFoundRedirectOptions::class, $arg2);
Assert::assertInstanceOf(UriInterface::class, $arg3);
$callCount++;
return null;
},
);
}];
}

View File

@@ -11,11 +11,12 @@ use Mezzio\Router\Route;
use Mezzio\Router\RouteResult;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Shlinkio\Shlink\Core\Action\RedirectAction;
use Shlinkio\Shlink\Core\ErrorHandler\Model\NotFoundType;
use Shlinkio\Shlink\Core\ErrorHandler\NotFoundTemplateHandler;
use function Laminas\Stratigility\middleware;
class NotFoundTemplateHandlerTest extends TestCase
{
private NotFoundTemplateHandler $handler;
@@ -44,19 +45,20 @@ class NotFoundTemplateHandlerTest extends TestCase
self::assertTrue($this->readFileCalled);
}
public function provideTemplates(): iterable
public static function provideTemplates(): iterable
{
$request = ServerRequestFactory::fromGlobals()->withUri(new Uri('/foo'));
yield 'base url' => [$this->withNotFoundType($request, '/foo'), NotFoundTemplateHandler::NOT_FOUND_TEMPLATE];
yield 'regular not found' => [$this->withNotFoundType($request), NotFoundTemplateHandler::NOT_FOUND_TEMPLATE];
yield 'base url' => [self::withNotFoundType($request, '/foo'), NotFoundTemplateHandler::NOT_FOUND_TEMPLATE];
yield 'regular not found' => [self::withNotFoundType($request), NotFoundTemplateHandler::NOT_FOUND_TEMPLATE];
yield 'invalid short code' => [
$this->withNotFoundType($request->withAttribute(
self::withNotFoundType($request->withAttribute(
RouteResult::class,
RouteResult::fromRoute(
new Route(
'foo',
$this->createMock(MiddlewareInterface::class),
middleware(function (): void {
}),
['GET'],
RedirectAction::class,
),
@@ -66,7 +68,7 @@ class NotFoundTemplateHandlerTest extends TestCase
];
}
private function withNotFoundType(ServerRequestInterface $req, string $baseUrl = ''): ServerRequestInterface
private static function withNotFoundType(ServerRequestInterface $req, string $baseUrl = ''): ServerRequestInterface
{
$type = NotFoundType::fromRequest($req, $baseUrl);
return $req->withAttribute(NotFoundType::class, $type);

View File

@@ -46,7 +46,7 @@ class CloseDbConnectionEventListenerTest extends TestCase
self::assertTrue($wrappedWasCalled);
}
public function provideWrapped(): iterable
public static function provideWrapped(): iterable
{
yield 'does not throw exception' => (static function (): array {
$wrappedWasCalled = false;

View File

@@ -146,7 +146,7 @@ class LocateVisitTest extends TestCase
self::assertEquals($visit->getVisitLocation(), VisitLocation::fromGeolocation(Location::emptyInstance()));
}
public function provideNonLocatableVisits(): iterable
public static function provideNonLocatableVisits(): iterable
{
$shortUrl = ShortUrl::createFake();
@@ -180,7 +180,7 @@ class LocateVisitTest extends TestCase
self::assertEquals($visit->getVisitLocation(), VisitLocation::fromGeolocation($location));
}
public function provideIpAddresses(): iterable
public static function provideIpAddresses(): iterable
{
yield 'no original IP address' => [
Visit::forValidShortUrl(ShortUrl::createFake(), new Visitor('', '', '1.2.3.4', '')),

View File

@@ -121,7 +121,7 @@ class NotifyVisitToMercureTest extends TestCase
($this->listener)(new VisitLocated($visitId));
}
public function provideOrphanVisits(): iterable
public static function provideOrphanVisits(): iterable
{
$visitor = Visitor::emptyInstance();

View File

@@ -120,13 +120,13 @@ class NotifyVisitToWebHooksTest extends TestCase
$this->createListener($webhooks)(new VisitLocated('1'));
}
public function provideVisits(): iterable
public static function provideVisits(): iterable
{
yield 'regular visit' => [
Visit::forValidShortUrl(ShortUrl::createFake(), Visitor::emptyInstance()),
['shortUrl', 'visit'],
];
yield 'orphan visit' => [Visit::forBasePath(Visitor::emptyInstance()), ['visit'],];
yield 'orphan visit' => [Visit::forBasePath(Visitor::emptyInstance()), ['visit']];
}
private function createListener(array $webhooks, bool $notifyOrphanVisits = true): NotifyVisitToWebHooks

View File

@@ -77,7 +77,7 @@ class PublishingUpdatesGeneratorTest extends TestCase
], $update->payload);
}
public function provideMethod(): iterable
public static function provideMethod(): iterable
{
yield 'newVisitUpdate' => ['newVisitUpdate', 'https://shlink.io/new-visit', 'the cool title'];
yield 'newShortUrlVisitUpdate' => ['newShortUrlVisitUpdate', 'https://shlink.io/new-visit/foo', null];
@@ -105,7 +105,7 @@ class PublishingUpdatesGeneratorTest extends TestCase
], $update->payload);
}
public function provideOrphanVisits(): iterable
public static function provideOrphanVisits(): iterable
{
$visitor = Visitor::emptyInstance();

View File

@@ -102,7 +102,7 @@ class NotifyNewShortUrlToRabbitMqTest extends TestCase
($this->listener())(new ShortUrlCreated($shortUrlId));
}
public function provideExceptions(): iterable
public static function provideExceptions(): iterable
{
yield [new RuntimeException('RuntimeException Error')];
yield [new Exception('Exception Error')];

View File

@@ -91,7 +91,7 @@ class NotifyVisitToRabbitMqTest extends TestCase
($this->listener())(new VisitLocated($visitId));
}
public function provideVisits(): iterable
public static function provideVisits(): iterable
{
$visitor = Visitor::emptyInstance();
@@ -130,7 +130,7 @@ class NotifyVisitToRabbitMqTest extends TestCase
($this->listener())(new VisitLocated($visitId));
}
public function provideExceptions(): iterable
public static function provideExceptions(): iterable
{
yield [new RuntimeException('RuntimeException Error')];
yield [new Exception('Exception Error')];
@@ -155,14 +155,14 @@ class NotifyVisitToRabbitMqTest extends TestCase
($this->listener(new RabbitMqOptions(true, $legacy)))(new VisitLocated($visitId));
}
public function provideLegacyPayloads(): iterable
public static function provideLegacyPayloads(): iterable
{
yield 'legacy non-orphan visit' => [
true,
$visit = Visit::forValidShortUrl(ShortUrl::withLongUrl('longUrl'), Visitor::emptyInstance()),
noop(...),
function (MockObject & PublishingHelperInterface $helper) use ($visit): void {
$helper->method('publishUpdate')->with($this->callback(function (Update $update) use ($visit): bool {
$helper->method('publishUpdate')->with(self::callback(function (Update $update) use ($visit): bool {
$payload = $update->payload;
Assert::assertEquals($payload, $visit->jsonSerialize());
Assert::assertArrayNotHasKey('visitedUrl', $payload);
@@ -179,7 +179,7 @@ class NotifyVisitToRabbitMqTest extends TestCase
Visit::forBasePath(Visitor::emptyInstance()),
noop(...),
function (MockObject & PublishingHelperInterface $helper): void {
$helper->method('publishUpdate')->with($this->callback(function (Update $update): bool {
$helper->method('publishUpdate')->with(self::callback(function (Update $update): bool {
$payload = $update->payload;
Assert::assertArrayHasKey('visitedUrl', $payload);
Assert::assertArrayHasKey('type', $payload);
@@ -193,14 +193,14 @@ class NotifyVisitToRabbitMqTest extends TestCase
Visit::forValidShortUrl(ShortUrl::withLongUrl('longUrl'), Visitor::emptyInstance()),
function (MockObject & PublishingUpdatesGeneratorInterface $updatesGenerator): void {
$update = Update::forTopicAndPayload('', []);
$updatesGenerator->expects($this->never())->method('newOrphanVisitUpdate');
$updatesGenerator->expects($this->once())->method('newVisitUpdate')->withAnyParameters()->willReturn(
$updatesGenerator->expects(self::never())->method('newOrphanVisitUpdate');
$updatesGenerator->expects(self::once())->method('newVisitUpdate')->withAnyParameters()->willReturn(
$update,
);
$updatesGenerator->expects($this->once())->method('newShortUrlVisitUpdate')->willReturn($update);
$updatesGenerator->expects(self::once())->method('newShortUrlVisitUpdate')->willReturn($update);
},
function (MockObject & PublishingHelperInterface $helper): void {
$helper->expects($this->exactly(2))->method('publishUpdate')->with($this->isInstanceOf(Update::class));
$helper->expects(self::exactly(2))->method('publishUpdate')->with(self::isInstanceOf(Update::class));
},
];
yield 'non-legacy orphan visit' => [
@@ -208,12 +208,12 @@ class NotifyVisitToRabbitMqTest extends TestCase
Visit::forBasePath(Visitor::emptyInstance()),
function (MockObject & PublishingUpdatesGeneratorInterface $updatesGenerator): void {
$update = Update::forTopicAndPayload('', []);
$updatesGenerator->expects($this->once())->method('newOrphanVisitUpdate')->willReturn($update);
$updatesGenerator->expects($this->never())->method('newVisitUpdate');
$updatesGenerator->expects($this->never())->method('newShortUrlVisitUpdate');
$updatesGenerator->expects(self::once())->method('newOrphanVisitUpdate')->willReturn($update);
$updatesGenerator->expects(self::never())->method('newVisitUpdate');
$updatesGenerator->expects(self::never())->method('newShortUrlVisitUpdate');
},
function (MockObject & PublishingHelperInterface $helper): void {
$helper->expects($this->once())->method('publishUpdate')->with($this->isInstanceOf(Update::class));
$helper->expects(self::once())->method('publishUpdate')->with(self::isInstanceOf(Update::class));
},
];
}

View File

@@ -69,7 +69,7 @@ class NotifyNewShortUrlToRedisTest extends TestCase
$this->createListener()(new ShortUrlCreated($shortUrlId));
}
public function provideExceptions(): iterable
public static function provideExceptions(): iterable
{
yield [new RuntimeException('RuntimeException Error')];
yield [new Exception('Exception Error')];

View File

@@ -68,7 +68,7 @@ class NotifyVisitToRedisTest extends TestCase
$this->createListener()(new VisitLocated($visitId));
}
public function provideExceptions(): iterable
public static function provideExceptions(): iterable
{
yield [new RuntimeException('RuntimeException Error')];
yield [new Exception('Exception Error')];

View File

@@ -67,7 +67,7 @@ class UpdateGeoLiteDbTest extends TestCase
($this->listener)();
}
public function provideFlags(): iterable
public static function provideFlags(): iterable
{
yield 'existing old db' => [true, 'Updating GeoLite2 db file...'];
yield 'not existing old db' => [false, 'Downloading GeoLite2 db file...'];
@@ -101,7 +101,7 @@ class UpdateGeoLiteDbTest extends TestCase
($this->listener)();
}
public function provideDownloaded(): iterable
public static function provideDownloaded(): iterable
{
yield [100, 0, true, null];
yield [100, 0, false, null];
@@ -129,7 +129,7 @@ class UpdateGeoLiteDbTest extends TestCase
($this->listener)();
}
public function provideGeolocationResults(): iterable
public static function provideGeolocationResults(): iterable
{
return map(GeolocationResult::cases(), static fn (GeolocationResult $value) => [
$value,

View File

@@ -41,7 +41,7 @@ class DeleteShortUrlExceptionTest extends TestCase
self::assertEquals(422, $e->getStatus());
}
public function provideThresholds(): array
public static function provideThresholds(): array
{
return map(range(5, 50, 5), function (int $number) {
return [$number, $shortCode = generateRandomShortCode(6), sprintf(

View File

@@ -29,7 +29,7 @@ class ForbiddenTagOperationExceptionTest extends TestCase
self::assertEquals(403, $e->getStatus());
}
public function provideExceptions(): iterable
public static function provideExceptions(): iterable
{
yield 'deletion' => [ForbiddenTagOperationException::forDeletion(), 'You are not allowed to delete tags'];
yield 'renaming' => [ForbiddenTagOperationException::forRenaming(), 'You are not allowed to rename tags'];

View File

@@ -34,7 +34,7 @@ class InvalidUrlExceptionTest extends TestCase
self::assertEquals($prev, $e->getPrevious());
}
public function providePrevious(): iterable
public static function providePrevious(): iterable
{
yield 'null previous' => [null];
yield 'instance previous' => [new Exception('Previous error', 10)];

View File

@@ -53,7 +53,7 @@ class IpCannotBeLocatedExceptionTest extends TestCase
self::assertEquals(UnlocatableIpType::ERROR, $e->type);
}
public function provideErrors(): iterable
public static function provideErrors(): iterable
{
yield 'Simple exception with positive code' => [new Exception('Some message', 100)];
yield 'Runtime exception with negative code' => [new RuntimeException('Something went wrong', -50)];

View File

@@ -30,7 +30,7 @@ class NonUniqueSlugExceptionTest extends TestCase
self::assertEquals($expectedAdditional, $e->getAdditionalData());
}
public function provideMessages(): iterable
public static function provideMessages(): iterable
{
yield 'without domain' => [
'Provided slug "foo" is already in use.',

View File

@@ -34,7 +34,7 @@ class ShortUrlNotFoundExceptionTest extends TestCase
self::assertEquals($expectedAdditional, $e->getAdditionalData());
}
public function provideMessages(): iterable
public static function provideMessages(): iterable
{
yield 'without domain' => [
'No URL found with short code "abc123"',

View File

@@ -46,7 +46,7 @@ class ValidationExceptionTest extends TestCase
self::assertStringContainsString($expectedStringRepresentation, (string) $e);
}
public function provideExceptions(): iterable
public static function provideExceptions(): iterable
{
return [[null], [new RuntimeException()], [new LogicException()]];
}

View File

@@ -26,7 +26,7 @@ class FunctionsTest extends TestCase
self::assertEquals($expectedValues, enumValues($enum));
}
public function provideEnums(): iterable
public static function provideEnums(): iterable
{
yield EnvVars::class => [EnvVars::class, map(EnvVars::cases(), static fn (EnvVars $envVar) => $envVar->value)];
yield VisitType::class => [

View File

@@ -188,7 +188,7 @@ class ImportedLinksProcessorTest extends TestCase
$this->processor->process($this->io, ImportResult::withShortUrls([$importedUrl]), $this->buildParams());
}
public function provideUrlsWithVisits(): iterable
public static function provideUrlsWithVisits(): iterable
{
$now = Chronos::now();
$createImportedUrl = static fn (array $visits) =>
@@ -262,7 +262,7 @@ class ImportedLinksProcessorTest extends TestCase
);
}
public function provideOrphanVisits(): iterable
public static function provideOrphanVisits(): iterable
{
yield 'import orphan disable without visits' => [false, [], null, 0];
yield 'import orphan enabled without visits' => [true, [], null, 0];

View File

@@ -41,7 +41,7 @@ class ShortUrlTest extends TestCase
$shortUrl->regenerateShortCode(ShortUrlMode::STRICT);
}
public function provideInvalidShortUrls(): iterable
public static function provideInvalidShortUrls(): iterable
{
yield 'with custom slug' => [
ShortUrl::create(ShortUrlCreation::fromRawData(['customSlug' => 'custom-slug', 'longUrl' => 'longUrl'])),
@@ -68,7 +68,7 @@ class ShortUrlTest extends TestCase
self::assertNotEquals($firstShortCode, $secondShortCode);
}
public function provideValidShortUrls(): iterable
public static function provideValidShortUrls(): iterable
{
yield 'no custom slug' => [ShortUrl::createFake()];
yield 'imported with custom slug' => [ShortUrl::fromImport(
@@ -90,7 +90,7 @@ class ShortUrlTest extends TestCase
self::assertEquals($expectedLength, strlen($shortUrl->getShortCode()));
}
public function provideLengths(): iterable
public static function provideLengths(): iterable
{
yield [null, DEFAULT_SHORT_CODES_LENGTH];
yield from map(range(4, 10), fn (int $value) => [$value, $value]);

View File

@@ -55,7 +55,7 @@ class ShortCodeUniquenessHelperTest extends TestCase
self::assertTrue($result);
}
public function provideDomains(): iterable
public static function provideDomains(): iterable
{
yield 'no domain' => [null, null];
yield 'domain' => [Domain::withAuthority($authority = 's.test'), $authority];

View File

@@ -50,7 +50,7 @@ class ShortUrlRedirectionBuilderTest extends TestCase
self::assertEquals($expectedUrl, $result);
}
public function provideData(): iterable
public static function provideData(): iterable
{
$request = static fn (array $query = []) => ServerRequestFactory::fromGlobals()->withQueryParams($query);

View File

@@ -26,7 +26,7 @@ class ShortUrlStringifierTest extends TestCase
self::assertEquals($expected, $stringifier->stringify($shortUrl));
}
public function provideConfigAndShortUrls(): iterable
public static function provideConfigAndShortUrls(): iterable
{
$shortUrlWithShortCode = fn (string $shortCode, ?string $domain = null) => ShortUrl::create(
ShortUrlCreation::fromRawData([

View File

@@ -42,7 +42,7 @@ class ShortUrlTitleResolutionHelperTest extends TestCase
);
}
public function provideTitles(): iterable
public static function provideTitles(): iterable
{
yield 'no title' => [null, 1, 0];
yield 'title' => ['link title', 0, 1];

View File

@@ -12,7 +12,6 @@ use Mezzio\Router\RouteResult;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Shlinkio\Shlink\Core\Action\RedirectAction;
use Shlinkio\Shlink\Core\ErrorHandler\Model\NotFoundType;
@@ -26,6 +25,7 @@ use Shlinkio\Shlink\Core\ShortUrl\ShortUrlResolverInterface;
use Shlinkio\Shlink\Core\Util\RedirectResponseHelperInterface;
use Shlinkio\Shlink\Core\Visit\RequestTrackerInterface;
use function Laminas\Stratigility\middleware;
use function str_starts_with;
class ExtraPathRedirectMiddlewareTest extends TestCase
@@ -68,7 +68,7 @@ class ExtraPathRedirectMiddlewareTest extends TestCase
$this->middleware($options)->process($request, $this->handler);
}
public function provideNonRedirectingRequests(): iterable
public static function provideNonRedirectingRequests(): iterable
{
$baseReq = ServerRequestFactory::fromGlobals();
$buildReq = static fn (?NotFoundType $type): ServerRequestInterface =>
@@ -84,7 +84,8 @@ class ExtraPathRedirectMiddlewareTest extends TestCase
RouteResult::class,
RouteResult::fromRoute(new Route(
'/foo',
$this->createMock(MiddlewareInterface::class),
middleware(function (): void {
}),
['GET'],
RedirectAction::class,
)),
@@ -170,7 +171,7 @@ class ExtraPathRedirectMiddlewareTest extends TestCase
$this->middleware($options)->process($request, $this->handler);
}
public function provideResolves(): iterable
public static function provideResolves(): iterable
{
yield [false, 1, '/bar/baz'];
yield [true, 3, null];

View File

@@ -43,7 +43,7 @@ class TrimTrailingSlashMiddlewareTest extends TestCase
$this->middleware($trailingSlashEnabled)->process($inputRequest, $this->requestHandler);
}
public function provideRequests(): iterable
public static function provideRequests(): iterable
{
yield 'trailing slash disabled' => [
false,

View File

@@ -31,7 +31,7 @@ class ShortUrlCreationTest extends TestCase
ShortUrlCreation::fromRawData($data);
}
public function provideInvalidData(): iterable
public static function provideInvalidData(): iterable
{
yield [[]];
yield [[
@@ -136,7 +136,7 @@ class ShortUrlCreationTest extends TestCase
self::assertNull($creation->maxVisits);
}
public function provideCustomSlugs(): iterable
public static function provideCustomSlugs(): iterable
{
yield ['🔥', '🔥'];
yield ['🦣 🍅', '🦣-🍅'];
@@ -175,7 +175,7 @@ class ShortUrlCreationTest extends TestCase
self::assertEquals($expectedTitle, $creation->title);
}
public function provideTitles(): iterable
public static function provideTitles(): iterable
{
yield [null, null];
yield ['foo', 'foo'];
@@ -201,7 +201,7 @@ class ShortUrlCreationTest extends TestCase
self::assertSame($expectedDomain, $creation->domain);
}
public function provideDomains(): iterable
public static function provideDomains(): iterable
{
yield 'null domain' => [null, null];
yield 'empty domain' => ['', null];

View File

@@ -27,7 +27,7 @@ class ShortUrlEditionTest extends TestCase
self::assertEquals($expectedDevicesToRemove, $edition->devicesToRemove);
}
public function provideDeviceLongUrls(): iterable
public static function provideDeviceLongUrls(): iterable
{
yield 'null' => [null, [], []];
yield 'empty' => [[], [], []];

View File

@@ -18,7 +18,7 @@ class ShortUrlModeTest extends TestCase
self::assertSame($expected, ShortUrlMode::tryDeprecated($mode));
}
public function provideModes(): iterable
public static function provideModes(): iterable
{
yield 'invalid' => ['invalid', null];
yield 'foo' => ['foo', null];

View File

@@ -29,7 +29,7 @@ class DeviceLongUrlsValidatorTest extends TestCase
self::assertEquals(['NOT_ARRAY' => 'Provided value is not an array.'], $this->validator->getMessages());
}
public function provideNonArrayValues(): iterable
public static function provideNonArrayValues(): iterable
{
yield 'int' => [0];
yield 'float' => [100.45];

View File

@@ -79,7 +79,7 @@ class ShortUrlRepositoryAdapterTest extends TestCase
$adapter->getNbResults();
}
public function provideFilteringArgs(): iterable
public static function provideFilteringArgs(): iterable
{
yield [];
yield ['search'];

View File

@@ -55,7 +55,7 @@ class PersistenceShortUrlRelationResolverTest extends TestCase
self::assertEquals($authority, $result->authority);
}
public function provideFoundDomains(): iterable
public static function provideFoundDomains(): iterable
{
$authority = 's.test';
@@ -89,7 +89,7 @@ class PersistenceShortUrlRelationResolverTest extends TestCase
self::assertEquals($expectedTags, $result->toArray());
}
public function provideTags(): iterable
public static function provideTags(): iterable
{
yield 'no duplicated tags' => [['foo', 'bar', 'baz'], [new Tag('foo'), new Tag('bar'), new Tag('baz')]];
yield 'duplicated tags' => [['foo', 'bar', 'bar'], [new Tag('foo'), new Tag('bar')]];

View File

@@ -34,7 +34,7 @@ class SimpleShortUrlRelationResolverTest extends TestCase
}
}
public function provideDomains(): iterable
public static function provideDomains(): iterable
{
yield 'empty domain' => [null];
yield 'non-empty domain' => ['domain.com'];

View File

@@ -113,7 +113,7 @@ class ShortUrlResolverTest extends TestCase
$this->urlResolver->resolveEnabledShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode));
}
public function provideDisabledShortUrls(): iterable
public static function provideDisabledShortUrls(): iterable
{
$now = Chronos::now();

View File

@@ -8,6 +8,7 @@ use Cake\Chronos\Chronos;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
use PHPUnit\Framework\MockObject\Rule\InvokedCount;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\Core\Model\DeviceType;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
@@ -93,23 +94,23 @@ class ShortUrlServiceTest extends TestCase
self::assertEquals($resolveDeviceLongUrls(), $shortUrl->deviceLongUrls());
}
public function provideShortUrlEdits(): iterable
public static function provideShortUrlEdits(): iterable
{
yield 'no long URL' => [$this->never(), ShortUrlEdition::fromRawData([
yield 'no long URL' => [new InvokedCount(0), ShortUrlEdition::fromRawData([
'validSince' => Chronos::parse('2017-01-01 00:00:00')->toAtomString(),
'validUntil' => Chronos::parse('2017-01-05 00:00:00')->toAtomString(),
'maxVisits' => 5,
]), null];
yield 'long URL and API key' => [$this->once(), ShortUrlEdition::fromRawData([
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',
]), ApiKey::create()];
yield 'long URL with validation' => [$this->once(), ShortUrlEdition::fromRawData([
yield 'long URL with validation' => [new InvokedCount(1), ShortUrlEdition::fromRawData([
'longUrl' => 'modifiedLongUrl',
'validateUrl' => true,
]), null];
yield 'device redirects' => [$this->never(), ShortUrlEdition::fromRawData([
yield 'device redirects' => [new InvokedCount(0), ShortUrlEdition::fromRawData([
'deviceLongUrls' => [
DeviceType::IOS->value => 'iosLongUrl',
DeviceType::ANDROID->value => 'androidLongUrl',

View File

@@ -33,7 +33,7 @@ class ShortUrlDataTransformerTest extends TestCase
self::assertEquals($expectedMeta, $meta);
}
public function provideShortUrls(): iterable
public static function provideShortUrls(): iterable
{
$maxVisits = random_int(1, 1000);
$now = Chronos::now();

View File

@@ -95,7 +95,7 @@ class UrlShortenerTest extends TestCase
self::assertSame($expected, $result);
}
public function provideExistingShortUrls(): iterable
public static function provideExistingShortUrls(): iterable
{
$url = 'http://foo.com';

View File

@@ -74,7 +74,7 @@ class TagServiceTest extends TestCase
self::assertEquals($expected, $result->getCurrentPageResults());
}
public function provideApiKeysAndSearchTerm(): iterable
public static function provideApiKeysAndSearchTerm(): iterable
{
yield 'no API key, no filter' => [
null,
@@ -156,7 +156,7 @@ class TagServiceTest extends TestCase
self::assertEquals($newName, (string) $tag);
}
public function provideValidRenames(): iterable
public static function provideValidRenames(): iterable
{
yield 'same names' => ['foo', 'foo', 1];
yield 'different names names' => ['foo', 'bar', 0];

View File

@@ -8,7 +8,7 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey;
trait ApiKeyHelpersTrait
{
public function provideAdminApiKeys(): iterable
public static function provideAdminApiKeys(): iterable
{
yield 'no API key' => [null];
yield 'admin API key' => [ApiKey::create()];

View File

@@ -43,7 +43,7 @@ class DoctrineBatchHelperTest extends TestCase
}
}
public function provideIterables(): iterable
public static function provideIterables(): iterable
{
yield [[], 100, 1];
yield [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3, 4];

View File

@@ -33,7 +33,7 @@ class RedirectResponseHelperTest extends TestCase
self::assertEquals($expectedCacheControl ?? '', $response->getHeaderLine('Cache-Control'));
}
public function provideRedirectConfigs(): iterable
public static function provideRedirectConfigs(): iterable
{
yield 'status 302' => [302, 20, 302, null];
yield 'status 307' => [307, 20, 307, null];

View File

@@ -22,7 +22,7 @@ class VisitLocationTest extends TestCase
self::assertEquals($isEmpty, $location->isEmpty());
}
public function provideArgs(): iterable
public static function provideArgs(): iterable
{
yield [['', '', '', '', 0.0, 0.0, ''], true];
yield [['', '', '', '', 0.0, 0.0, 'dd'], false];

View File

@@ -29,7 +29,7 @@ class VisitTest extends TestCase
], $visit->jsonSerialize());
}
public function provideUserAgents(): iterable
public static function provideUserAgents(): iterable
{
yield 'Chrome' => [
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36',
@@ -56,7 +56,7 @@ class VisitTest extends TestCase
self::assertEquals($expectedAddress, $visit->getRemoteAddr());
}
public function provideAddresses(): iterable
public static function provideAddresses(): iterable
{
yield 'anonymized null address' => [true, null, null];
yield 'non-anonymized null address' => [false, null, null];

View File

@@ -72,7 +72,7 @@ class VisitLocatorTest extends TestCase
});
}
public function provideMethodNames(): iterable
public static function provideMethodNames(): iterable
{
yield 'locateUnlocatedVisits' => ['locateUnlocatedVisits', 'findUnlocatedVisits'];
yield 'locateVisitsWithEmptyLocation' => ['locateVisitsWithEmptyLocation', 'findVisitsWithEmptyLocation'];
@@ -120,7 +120,7 @@ class VisitLocatorTest extends TestCase
);
}
public function provideIsNonLocatableAddress(): iterable
public static function provideIsNonLocatableAddress(): iterable
{
yield 'locateUnlocatedVisits - locatable address' => ['locateUnlocatedVisits', 'findUnlocatedVisits', false];
yield 'locateUnlocatedVisits - non-locatable address' => ['locateUnlocatedVisits', 'findUnlocatedVisits', true];

View File

@@ -39,7 +39,7 @@ class VisitToLocationHelperTest extends TestCase
$this->helper->resolveVisitLocation($visit);
}
public function provideNonLocatableVisits(): iterable
public static function provideNonLocatableVisits(): iterable
{
yield [Visit::forBasePath(Visitor::emptyInstance()), IpCannotBeLocatedException::forEmptyAddress()];
yield [

View File

@@ -29,7 +29,7 @@ class VisitorTest extends TestCase
self::assertEquals($remoteAddress, $visitor->remoteAddress);
}
public function provideParams(): iterable
public static function provideParams(): iterable
{
yield 'all values are bigger' => [
[str_repeat('a', 1000), str_repeat('b', 2000), str_repeat('c', 500), ''],
@@ -49,8 +49,8 @@ class VisitorTest extends TestCase
];
yield 'random strings' => [
[
$userAgent = $this->generateRandomString(2000),
$referer = $this->generateRandomString(50),
$userAgent = self::generateRandomString(2000),
$referer = self::generateRandomString(50),
null,
'',
],
@@ -62,7 +62,7 @@ class VisitorTest extends TestCase
];
}
private function generateRandomString(int $length): string
private static function generateRandomString(int $length): string
{
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
@@ -77,10 +77,10 @@ class VisitorTest extends TestCase
public function newNormalizedInstanceIsCreatedFromTrackingOptions(): void
{
$visitor = new Visitor(
$this->generateRandomString(2000),
$this->generateRandomString(2000),
$this->generateRandomString(2000),
$this->generateRandomString(2000),
self::generateRandomString(2000),
self::generateRandomString(2000),
self::generateRandomString(2000),
self::generateRandomString(2000),
);
$normalizedVisitor = $visitor->normalizeForTrackingOptions(new TrackingOptions(
disableIpTracking: true,

View File

@@ -67,7 +67,7 @@ class NonOrphanVisitsPaginatorAdapterTest extends TestCase
self::assertEquals($list, $result);
}
public function provideLimitAndOffset(): iterable
public static function provideLimitAndOffset(): iterable
{
yield [1, 5];
yield [10, 4];

View File

@@ -59,7 +59,7 @@ class OrphanVisitsPaginatorAdapterTest extends TestCase
self::assertEquals($list, $result);
}
public function provideLimitAndOffset(): iterable
public static function provideLimitAndOffset(): iterable
{
yield [1, 5];
yield [10, 4];

View File

@@ -57,7 +57,7 @@ class RequestTrackerTest extends TestCase
$this->requestTracker->trackIfApplicable($shortUrl, $request);
}
public function provideNonTrackingRequests(): iterable
public static function provideNonTrackingRequests(): iterable
{
yield 'forwarded from head' => [ServerRequestFactory::fromGlobals()->withAttribute(
ImplicitHeadMiddleware::FORWARDED_HTTP_METHOD_ATTRIBUTE,

View File

@@ -34,7 +34,7 @@ class OrphanVisitDataTransformerTest extends TestCase
self::assertEquals($expectedResult, $result);
}
public function provideVisits(): iterable
public static function provideVisits(): iterable
{
yield 'base path visit' => [
$visit = Visit::forBasePath(Visitor::emptyInstance()),

View File

@@ -6,6 +6,7 @@ namespace ShlinkioTest\Shlink\Core\Visit;
use Doctrine\ORM\EntityManagerInterface;
use Laminas\Stdlib\ArrayUtils;
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\Core\Domain\Entity\Domain;
@@ -53,13 +54,17 @@ class VisitsStatsHelperTest extends TestCase
public function returnsExpectedVisitsStats(int $expectedCount): void
{
$repo = $this->createMock(VisitRepository::class);
$repo->expects($this->exactly(2))->method('countNonOrphanVisits')->withConsecutive(
[new VisitsCountFiltering()],
[new VisitsCountFiltering(excludeBots: true)],
)->willReturn($expectedCount * 3);
$repo->expects($this->exactly(2))->method('countOrphanVisits')->withConsecutive(
[$this->isInstanceOf(VisitsCountFiltering::class)],
[$this->isInstanceOf(VisitsCountFiltering::class)],
$callCount = 0;
$repo->expects($this->exactly(2))->method('countNonOrphanVisits')->willReturnCallback(
function (VisitsCountFiltering $options) use ($expectedCount, &$callCount) {
Assert::assertEquals($callCount !== 0, $options->excludeBots);
$callCount++;
return $expectedCount * 3;
},
);
$repo->expects($this->exactly(2))->method('countOrphanVisits')->with(
$this->isInstanceOf(VisitsCountFiltering::class),
)->willReturn($expectedCount);
$this->em->expects($this->once())->method('getRepository')->with(Visit::class)->willReturn($repo);
@@ -68,7 +73,7 @@ class VisitsStatsHelperTest extends TestCase
self::assertEquals(new VisitsStats($expectedCount * 3, $expectedCount), $stats);
}
public function provideCounts(): iterable
public static function provideCounts(): iterable
{
return map(range(0, 50, 5), fn (int $value) => [$value]);
}

View File

@@ -56,7 +56,7 @@ class VisitsTrackerTest extends TestCase
$this->visitsTracker(new TrackingOptions(disableTracking: true))->{$method}(...$args);
}
public function provideTrackingMethodNames(): iterable
public static function provideTrackingMethodNames(): iterable
{
yield 'track' => ['track', [ShortUrl::createFake(), Visitor::emptyInstance()]];
yield 'trackInvalidShortUrlVisit' => ['trackInvalidShortUrlVisit', [Visitor::emptyInstance()]];
@@ -77,7 +77,7 @@ class VisitsTrackerTest extends TestCase
$this->visitsTracker(new TrackingOptions(trackOrphanVisits: false))->{$method}(Visitor::emptyInstance());
}
public function provideOrphanTrackingMethodNames(): iterable
public static function provideOrphanTrackingMethodNames(): iterable
{
yield 'trackInvalidShortUrlVisit' => ['trackInvalidShortUrlVisit'];
yield 'trackBaseUrlVisit' => ['trackBaseUrlVisit'];