diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c5749074..b4335cb2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -152,8 +152,8 @@ jobs: - run: mv build/coverage-db/coverage-db.cov build/coverage-db.cov - run: mv build/coverage-api/coverage-api.cov build/coverage-api.cov - run: mv build/coverage-cli/coverage-cli.cov build/coverage-cli.cov - - run: wget https://phar.phpunit.de/phpcov-8.2.1.phar - - run: php phpcov-8.2.1.phar merge build --clover build/clover.xml + - run: wget https://phar.phpunit.de/phpcov-9.0.0.phar + - run: php phpcov-9.0.0.phar merge build --clover build/clover.xml - name: Publish coverage uses: codecov/codecov-action@v1 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 01c481b9..538f3c30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this * *Nothing* ### Changed -* *Nothing* +* [#1696](https://github.com/shlinkio/shlink/issues/1696) Migrated to PHPUnit 10. ### Deprecated * *Nothing* diff --git a/composer.json b/composer.json index 228a2c5f..202ed25e 100644 --- a/composer.json +++ b/composer.json @@ -20,63 +20,62 @@ "akrabat/ip-address-middleware": "^2.1", "cakephp/chronos": "^2.3", "doctrine/migrations": "^3.5", - "doctrine/orm": "^2.13.3", - "endroid/qr-code": "^4.6", + "doctrine/orm": "^2.14", + "endroid/qr-code": "^4.7", "geoip2/geoip2": "^2.13", "guzzlehttp/guzzle": "^7.5", "happyr/doctrine-specification": "^2.0", "jaybizzle/crawler-detect": "^1.2.112", - "laminas/laminas-config": "^3.7", - "laminas/laminas-config-aggregator": "^1.11", - "laminas/laminas-diactoros": "^2.19", - "laminas/laminas-inputfilter": "^2.22", - "laminas/laminas-servicemanager": "^3.19", - "laminas/laminas-stdlib": "^3.15", - "lcobucci/jwt": "^4.2", + "laminas/laminas-config": "^3.8", + "laminas/laminas-config-aggregator": "^1.13", + "laminas/laminas-diactoros": "^2.24", + "laminas/laminas-inputfilter": "^2.24", + "laminas/laminas-servicemanager": "^3.20", + "laminas/laminas-stdlib": "^3.16", + "lcobucci/jwt": "^4.3", "league/uri": "^6.8", "lstrojny/functional-php": "^1.17", - "mezzio/mezzio": "^3.13", - "mezzio/mezzio-fastroute": "^3.7", - "mezzio/mezzio-problem-details": "^1.7", - "mezzio/mezzio-swoole": "^4.5", + "mezzio/mezzio": "^3.15", + "mezzio/mezzio-fastroute": "^3.8", + "mezzio/mezzio-problem-details": "^1.11", + "mezzio/mezzio-swoole": "^4.6", "mlocati/ip-lib": "^1.18", "mobiledetect/mobiledetectlib": "^3.74", "ocramius/proxy-manager": "^2.14", - "pagerfanta/core": "^3.6", + "pagerfanta/core": "^3.7", "php-middleware/request-id": "^4.1", "pugx/shortid-php": "^1.1", - "ramsey/uuid": "^4.5", + "ramsey/uuid": "^4.7", "shlinkio/shlink-common": "^5.3.1", "shlinkio/shlink-config": "^2.4", "shlinkio/shlink-event-dispatcher": "^2.6", "shlinkio/shlink-importer": "^5.0", "shlinkio/shlink-installer": "^8.3", "shlinkio/shlink-ip-geolocation": "^3.2", - "spiral/roadrunner": "^2.11", - "spiral/roadrunner-jobs": "^2.5", - "symfony/console": "^6.1", - "symfony/filesystem": "^6.1", - "symfony/lock": "^6.1", - "symfony/process": "^6.1", - "symfony/string": "^6.1" + "spiral/roadrunner": "^2.12", + "spiral/roadrunner-jobs": "^2.7", + "symfony/console": "^6.2", + "symfony/filesystem": "^6.2", + "symfony/lock": "^6.2", + "symfony/process": "^6.2", + "symfony/string": "^6.2" }, "require-dev": { "cebe/php-openapi": "^1.7", "devster/ubench": "^2.1", - "dms/phpunit-arraysubset-asserts": "^0.4.0", - "infection/infection": "^0.26.15", + "infection/infection": "^0.26.19", "openswoole/ide-helper": "~4.11.5", - "phpstan/phpstan": "^1.8", + "phpstan/phpstan": "^1.9", "phpstan/phpstan-doctrine": "^1.3", - "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", "phpstan/phpstan-symfony": "^1.2", - "phpunit/php-code-coverage": "^9.2", - "phpunit/phpunit": "^9.5", + "phpunit/php-code-coverage": "^10.0", + "phpunit/phpunit": "^10.0", "roave/security-advisories": "dev-master", "shlinkio/php-coding-standard": "~2.3.0", - "shlinkio/shlink-test-utils": "^3.4", - "symfony/var-dumper": "^6.1", - "veewee/composer-run-parallel": "^1.1" + "shlinkio/shlink-test-utils": "^3.5", + "symfony/var-dumper": "^6.2", + "veewee/composer-run-parallel": "^1.2" }, "autoload": { "psr-4": { @@ -133,7 +132,7 @@ "test:cli": "APP_ENV=test DB_DRIVER=maria TEST_ENV=cli php vendor/bin/phpunit --order-by=random --colors=always --testdox -c phpunit-cli.xml --log-junit=build/coverage-cli/junit.xml", "test:cli:ci": "GENERATE_COVERAGE=yes composer test:cli", "test:cli:pretty": "GENERATE_COVERAGE=pretty composer test:cli", - "infect:ci:base": "infection --threads=max --only-covered --only-covering-test-cases --skip-initial-tests", + "infect:ci:base": "infection --threads=max --only-covered --skip-initial-tests", "infect:ci:unit": "@infect:ci:base --coverage=build/coverage-unit --min-msi=80", "infect:ci:db": "@infect:ci:base --coverage=build/coverage-db --min-msi=95 --configuration=infection-db.json5", "infect:ci:api": "@infect:ci:base --coverage=build/coverage-api --min-msi=80 --configuration=infection-api.json5", diff --git a/module/CLI/test-cli/Command/GenerateApiKeyTest.php b/module/CLI/test-cli/Command/GenerateApiKeyTest.php index b14462c0..c98dc237 100644 --- a/module/CLI/test-cli/Command/GenerateApiKeyTest.php +++ b/module/CLI/test-cli/Command/GenerateApiKeyTest.php @@ -4,13 +4,14 @@ declare(strict_types=1); namespace ShlinkioCliTest\Shlink\CLI\Command; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\CLI\Command\Api\GenerateKeyCommand; use Shlinkio\Shlink\CLI\Util\ExitCodes; use Shlinkio\Shlink\TestUtils\CliTest\CliTestCase; class GenerateApiKeyTest extends CliTestCase { - /** @test */ + #[Test] public function outputIsCorrect(): void { [$output, $exitCode] = $this->exec([GenerateKeyCommand::NAME]); diff --git a/module/CLI/test-cli/Command/ListApiKeysTest.php b/module/CLI/test-cli/Command/ListApiKeysTest.php index 96b60e92..80a1134d 100644 --- a/module/CLI/test-cli/Command/ListApiKeysTest.php +++ b/module/CLI/test-cli/Command/ListApiKeysTest.php @@ -5,16 +5,15 @@ declare(strict_types=1); namespace ShlinkioCliTest\Shlink\CLI\Command; use Cake\Chronos\Chronos; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\CLI\Command\Api\ListKeysCommand; use Shlinkio\Shlink\CLI\Util\ExitCodes; use Shlinkio\Shlink\TestUtils\CliTest\CliTestCase; class ListApiKeysTest extends CliTestCase { - /** - * @test - * @dataProvider provideFlags - */ + #[Test, DataProvider('provideFlags')] public function generatesExpectedOutput(array $flags, string $expectedOutput): void { [$output, $exitCode] = $this->exec([ListKeysCommand::NAME, ...$flags]); @@ -23,7 +22,7 @@ class ListApiKeysTest extends CliTestCase self::assertEquals(ExitCodes::EXIT_SUCCESS, $exitCode); } - public function provideFlags(): iterable + public static function provideFlags(): iterable { $expiredApiKeyDate = Chronos::now()->subDay()->startOfDay()->toAtomString(); $enabledOnlyOutput = <<exec([ListShortUrlsCommand::NAME, ...$flags], ['no']); self::assertStringContainsString($expectedOutput, $output); } - public function provideFlagsAndOutput(): iterable + public static function provideFlagsAndOutput(): iterable { // phpcs:disable Generic.Files.LineLength yield 'no flags' => [[], <<resolver = new RoleResolver($this->domainService, 'default.com'); } - /** - * @test - * @dataProvider provideRoles - */ + #[Test, DataProvider('provideRoles')] public function properRolesAreResolvedBasedOnInput( - InputInterface $input, + callable $createInput, array $expectedRoles, int $expectedDomainCalls, ): void { + $input = $createInput($this); $this->domainService->expects($this->exactly($expectedDomainCalls))->method('getOrCreate')->with( 'example.com', - )->willReturn($this->domainWithId(Domain::withAuthority('example.com'))); + )->willReturn(self::domainWithId(Domain::withAuthority('example.com'))); $result = $this->resolver->determineRoles($input); self::assertEquals($expectedRoles, $result); } - public function provideRoles(): iterable + public static function provideRoles(): iterable { - $domain = $this->domainWithId(Domain::withAuthority('example.com')); - $buildInput = function (array $definition): InputInterface { - $input = $this->createStub(InputInterface::class); + $domain = self::domainWithId(Domain::withAuthority('example.com')); + $buildInput = static fn (array $definition) => function (TestCase $test) use ($definition): InputInterface { + $input = $test->createStub(InputInterface::class); $input->method('getOption')->willReturnMap( map($definition, static fn (mixed $returnValue, string $param) => [$param, $returnValue]), ); @@ -98,7 +98,7 @@ class RoleResolverTest extends TestCase ]; } - /** @test */ + #[Test] public function exceptionIsThrownWhenTryingToAddDomainOnlyLinkedToDefaultDomain(): void { $input = $this->createStub(InputInterface::class); @@ -114,7 +114,7 @@ class RoleResolverTest extends TestCase $this->resolver->determineRoles($input); } - private function domainWithId(Domain $domain): Domain + private static function domainWithId(Domain $domain): Domain { $domain->setId('1'); return $domain; diff --git a/module/CLI/test/Command/Api/DisableKeyCommandTest.php b/module/CLI/test/Command/Api/DisableKeyCommandTest.php index 3a3c2def..8a1c64e8 100644 --- a/module/CLI/test/Command/Api/DisableKeyCommandTest.php +++ b/module/CLI/test/Command/Api/DisableKeyCommandTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Command\Api; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\Api\DisableKeyCommand; @@ -25,7 +26,7 @@ class DisableKeyCommandTest extends TestCase $this->commandTester = $this->testerForCommand(new DisableKeyCommand($this->apiKeyService)); } - /** @test */ + #[Test] public function providedApiKeyIsDisabled(): void { $apiKey = 'abcd1234'; @@ -39,7 +40,7 @@ class DisableKeyCommandTest extends TestCase self::assertStringContainsString('API key "abcd1234" properly disabled', $output); } - /** @test */ + #[Test] public function errorIsReturnedIfServiceThrowsException(): void { $apiKey = 'abcd1234'; diff --git a/module/CLI/test/Command/Api/GenerateKeyCommandTest.php b/module/CLI/test/Command/Api/GenerateKeyCommandTest.php index 631a01c8..b5dbe513 100644 --- a/module/CLI/test/Command/Api/GenerateKeyCommandTest.php +++ b/module/CLI/test/Command/Api/GenerateKeyCommandTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Command\Api; use Cake\Chronos\Chronos; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\ApiKey\RoleResolverInterface; @@ -32,7 +33,7 @@ class GenerateKeyCommandTest extends TestCase $this->commandTester = $this->testerForCommand($command); } - /** @test */ + #[Test] public function noExpirationDateIsDefinedIfNotProvided(): void { $this->apiKeyService->expects($this->once())->method('create')->with( @@ -46,7 +47,7 @@ class GenerateKeyCommandTest extends TestCase self::assertStringContainsString('Generated API key: ', $output); } - /** @test */ + #[Test] public function expirationDateIsDefinedIfProvided(): void { $this->apiKeyService->expects($this->once())->method('create')->with( @@ -59,7 +60,7 @@ class GenerateKeyCommandTest extends TestCase ]); } - /** @test */ + #[Test] public function nameIsDefinedIfProvided(): void { $this->apiKeyService->expects($this->once())->method('create')->with( diff --git a/module/CLI/test/Command/Api/ListKeysCommandTest.php b/module/CLI/test/Command/Api/ListKeysCommandTest.php index f4101ec6..e4cdb438 100644 --- a/module/CLI/test/Command/Api/ListKeysCommandTest.php +++ b/module/CLI/test/Command/Api/ListKeysCommandTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Command\Api; use Cake\Chronos\Chronos; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\Api\ListKeysCommand; @@ -29,10 +31,7 @@ class ListKeysCommandTest extends TestCase $this->commandTester = $this->testerForCommand(new ListKeysCommand($this->apiKeyService)); } - /** - * @test - * @dataProvider provideKeysAndOutputs - */ + #[Test, DataProvider('provideKeysAndOutputs')] public function returnsExpectedOutput(array $keys, bool $enabledOnly, string $expected): void { $this->apiKeyService->expects($this->once())->method('listKeys')->with($enabledOnly)->willReturn($keys); @@ -43,7 +42,7 @@ class ListKeysCommandTest extends TestCase self::assertEquals($expected, $output); } - public function provideKeysAndOutputs(): iterable + public static function provideKeysAndOutputs(): iterable { $dateInThePast = Chronos::createFromFormat('Y-m-d H:i:s', '2020-01-01 00:00:00'); @@ -84,14 +83,14 @@ class ListKeysCommandTest extends TestCase yield 'with roles' => [ [ $apiKey1 = ApiKey::create(), - $apiKey2 = $this->apiKeyWithRoles([RoleDefinition::forAuthoredShortUrls()]), - $apiKey3 = $this->apiKeyWithRoles( - [RoleDefinition::forDomain($this->domainWithId(Domain::withAuthority('example.com')))], + $apiKey2 = self::apiKeyWithRoles([RoleDefinition::forAuthoredShortUrls()]), + $apiKey3 = self::apiKeyWithRoles( + [RoleDefinition::forDomain(self::domainWithId(Domain::withAuthority('example.com')))], ), $apiKey4 = ApiKey::create(), - $apiKey5 = $this->apiKeyWithRoles([ + $apiKey5 = self::apiKeyWithRoles([ RoleDefinition::forAuthoredShortUrls(), - RoleDefinition::forDomain($this->domainWithId(Domain::withAuthority('example.com'))), + RoleDefinition::forDomain(self::domainWithId(Domain::withAuthority('example.com'))), ]), $apiKey6 = ApiKey::create(), ], @@ -141,7 +140,7 @@ class ListKeysCommandTest extends TestCase ]; } - private function apiKeyWithRoles(array $roles): ApiKey + private static function apiKeyWithRoles(array $roles): ApiKey { $apiKey = ApiKey::create(); foreach ($roles as $role) { @@ -151,7 +150,7 @@ class ListKeysCommandTest extends TestCase return $apiKey; } - private function domainWithId(Domain $domain): Domain + private static function domainWithId(Domain $domain): Domain { $domain->setId('1'); return $domain; diff --git a/module/CLI/test/Command/Db/CreateDatabaseCommandTest.php b/module/CLI/test/Command/Db/CreateDatabaseCommandTest.php index bf1eac98..9358184b 100644 --- a/module/CLI/test/Command/Db/CreateDatabaseCommandTest.php +++ b/module/CLI/test/Command/Db/CreateDatabaseCommandTest.php @@ -9,6 +9,8 @@ use Doctrine\DBAL\Driver; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\SqlitePlatform; use Doctrine\DBAL\Schema\AbstractSchemaManager; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\Db\CreateDatabaseCommand; @@ -63,7 +65,7 @@ class CreateDatabaseCommandTest extends TestCase $this->commandTester = $this->testerForCommand($command); } - /** @test */ + #[Test] public function successMessageIsPrintedIfDatabaseAlreadyExists(): void { $shlinkDatabase = 'shlink_database'; @@ -81,7 +83,7 @@ class CreateDatabaseCommandTest extends TestCase self::assertStringContainsString('Database already exists. Run "db:migrate" command', $output); } - /** @test */ + #[Test] public function databaseIsCreatedIfItDoesNotExist(): void { $shlinkDatabase = 'shlink_database'; @@ -96,10 +98,7 @@ class CreateDatabaseCommandTest extends TestCase $this->commandTester->execute([]); } - /** - * @test - * @dataProvider provideEmptyDatabase - */ + #[Test, DataProvider('provideEmptyDatabase')] public function tablesAreCreatedIfDatabaseIsEmpty(array $tables): void { $shlinkDatabase = 'shlink_database'; @@ -124,13 +123,13 @@ class CreateDatabaseCommandTest extends TestCase self::assertStringContainsString('Database properly created!', $output); } - public function provideEmptyDatabase(): iterable + public static function provideEmptyDatabase(): iterable { yield 'no tables' => [[]]; yield 'migrations table' => [[MIGRATIONS_TABLE]]; } - /** @test */ + #[Test] public function databaseCheckIsSkippedForSqlite(): void { $this->driver->method('getDatabasePlatform')->willReturn($this->createMock(SqlitePlatform::class)); diff --git a/module/CLI/test/Command/Db/MigrateDatabaseCommandTest.php b/module/CLI/test/Command/Db/MigrateDatabaseCommandTest.php index 7027ca21..7bdbfca0 100644 --- a/module/CLI/test/Command/Db/MigrateDatabaseCommandTest.php +++ b/module/CLI/test/Command/Db/MigrateDatabaseCommandTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Command\Db; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\Db\MigrateDatabaseCommand; @@ -38,7 +39,7 @@ class MigrateDatabaseCommandTest extends TestCase $this->commandTester = $this->testerForCommand($command); } - /** @test */ + #[Test] public function migrationsCommandIsRunWithProperVerbosity(): void { $this->processHelper->expects($this->once())->method('run')->with($this->isInstanceOf(OutputInterface::class), [ diff --git a/module/CLI/test/Command/Domain/DomainRedirectsCommandTest.php b/module/CLI/test/Command/Domain/DomainRedirectsCommandTest.php index 1bf5cec3..48125d91 100644 --- a/module/CLI/test/Command/Domain/DomainRedirectsCommandTest.php +++ b/module/CLI/test/Command/Domain/DomainRedirectsCommandTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Command\Domain; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\Domain\DomainRedirectsCommand; @@ -30,10 +32,7 @@ class DomainRedirectsCommandTest extends TestCase $this->commandTester = $this->testerForCommand(new DomainRedirectsCommand($this->domainService)); } - /** - * @test - * @dataProvider provideDomains - */ + #[Test, DataProvider('provideDomains')] public function onlyPlainQuestionsAreAskedForNewDomainsAndDomainsWithNoRedirects(?Domain $domain): void { $domainAuthority = 'my-domain.com'; @@ -60,13 +59,13 @@ class DomainRedirectsCommandTest extends TestCase self::assertEquals(3, substr_count($output, '(Leave empty for no redirect)')); } - public function provideDomains(): iterable + public static function provideDomains(): iterable { yield 'no domain' => [null]; yield 'domain without redirects' => [Domain::withAuthority('')]; } - /** @test */ + #[Test] public function offersNewOptionsForDomainsWithExistingRedirects(): void { $domainAuthority = 'example.com'; @@ -95,7 +94,7 @@ class DomainRedirectsCommandTest extends TestCase self::assertEquals(3, substr_count($output, 'Remove redirect')); } - /** @test */ + #[Test] public function authorityIsRequestedWhenNotProvidedAndNoOtherDomainsExist(): void { $domainAuthority = 'example.com'; @@ -117,7 +116,7 @@ class DomainRedirectsCommandTest extends TestCase self::assertStringContainsString('Domain authority for which you want to set specific redirects', $output); } - /** @test */ + #[Test] public function oneOfTheExistingDomainsCanBeSelected(): void { $domainAuthority = 'existing-two.com'; @@ -146,7 +145,7 @@ class DomainRedirectsCommandTest extends TestCase self::assertStringContainsString($domainAuthority, $output); } - /** @test */ + #[Test] public function aNewDomainCanBeCreatedEvenIfOthersAlreadyExist(): void { $domainAuthority = 'new-domain.com'; diff --git a/module/CLI/test/Command/Domain/GetDomainVisitsCommandTest.php b/module/CLI/test/Command/Domain/GetDomainVisitsCommandTest.php index 5cda6dc3..bdee0ed4 100644 --- a/module/CLI/test/Command/Domain/GetDomainVisitsCommandTest.php +++ b/module/CLI/test/Command/Domain/GetDomainVisitsCommandTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Command\Domain; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\Domain\GetDomainVisitsCommand; @@ -37,7 +38,7 @@ class GetDomainVisitsCommandTest extends TestCase ); } - /** @test */ + #[Test] public function outputIsProperlyGenerated(): void { $shortUrl = ShortUrl::createFake(); diff --git a/module/CLI/test/Command/Domain/ListDomainsCommandTest.php b/module/CLI/test/Command/Domain/ListDomainsCommandTest.php index 0275ba87..ad31d86d 100644 --- a/module/CLI/test/Command/Domain/ListDomainsCommandTest.php +++ b/module/CLI/test/Command/Domain/ListDomainsCommandTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Command\Domain; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\Domain\ListDomainsCommand; @@ -29,10 +31,7 @@ class ListDomainsCommandTest extends TestCase $this->commandTester = $this->testerForCommand(new ListDomainsCommand($this->domainService)); } - /** - * @test - * @dataProvider provideInputsAndOutputs - */ + #[Test, DataProvider('provideInputsAndOutputs')] public function allDomainsAreProperlyPrinted(array $input, string $expectedOutput): void { $bazDomain = Domain::withAuthority('baz.com'); @@ -57,7 +56,7 @@ class ListDomainsCommandTest extends TestCase self::assertEquals(ExitCodes::EXIT_SUCCESS, $this->commandTester->getStatusCode()); } - public function provideInputsAndOutputs(): iterable + public static function provideInputsAndOutputs(): iterable { $withoutRedirectsOutput = <<commandTester = $this->testerForCommand($command); } - /** @test */ + #[Test] public function properShortCodeIsCreatedIfLongUrlIsCorrect(): void { $shortUrl = ShortUrl::createFake(); @@ -64,7 +66,7 @@ class CreateShortUrlCommandTest extends TestCase self::assertStringContainsString('stringified_short_url', $output); } - /** @test */ + #[Test] public function exceptionWhileParsingLongUrlOutputsError(): void { $url = 'http://domain.com/invalid'; @@ -80,7 +82,7 @@ class CreateShortUrlCommandTest extends TestCase self::assertStringContainsString('Provided URL http://domain.com/invalid is invalid.', $output); } - /** @test */ + #[Test] public function providingNonUniqueSlugOutputsError(): void { $this->urlShortener->expects($this->once())->method('shorten')->withAnyParameters()->willThrowException( @@ -95,7 +97,7 @@ class CreateShortUrlCommandTest extends TestCase self::assertStringContainsString('Provided slug "my-slug" is already in use', $output); } - /** @test */ + #[Test] public function properlyProcessesProvidedTags(): void { $shortUrl = ShortUrl::createFake(); @@ -119,10 +121,7 @@ class CreateShortUrlCommandTest extends TestCase self::assertStringContainsString('stringified_short_url', $output); } - /** - * @test - * @dataProvider provideDomains - */ + #[Test, DataProvider('provideDomains')] public function properlyProcessesProvidedDomain(array $input, ?string $expectedDomain): void { $this->urlShortener->expects($this->once())->method('shorten')->with( @@ -139,7 +138,7 @@ class CreateShortUrlCommandTest extends TestCase self::assertEquals(ExitCodes::EXIT_SUCCESS, $this->commandTester->getStatusCode()); } - public function provideDomains(): iterable + public static function provideDomains(): iterable { yield 'no domain' => [[], null]; yield 'non-default domain foo' => [['--domain' => 'foo.com'], 'foo.com']; @@ -147,10 +146,7 @@ class CreateShortUrlCommandTest extends TestCase yield 'default domain' => [['--domain' => self::DEFAULT_DOMAIN], null]; } - /** - * @test - * @dataProvider provideFlags - */ + #[Test, DataProvider('provideFlags')] public function urlValidationHasExpectedValueBasedOnProvidedFlags(array $options, ?bool $expectedValidateUrl): void { $shortUrl = ShortUrl::createFake(); @@ -166,7 +162,7 @@ class CreateShortUrlCommandTest extends TestCase $this->commandTester->execute($options); } - public function provideFlags(): iterable + public static function provideFlags(): iterable { yield 'no flags' => [[], null]; yield 'validate-url' => [['--validate-url' => true], true]; diff --git a/module/CLI/test/Command/ShortUrl/DeleteShortUrlCommandTest.php b/module/CLI/test/Command/ShortUrl/DeleteShortUrlCommandTest.php index 09d48d12..06081983 100644 --- a/module/CLI/test/Command/ShortUrl/DeleteShortUrlCommandTest.php +++ b/module/CLI/test/Command/ShortUrl/DeleteShortUrlCommandTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\ShortUrl\DeleteShortUrlCommand; @@ -30,7 +32,7 @@ class DeleteShortUrlCommandTest extends TestCase $this->commandTester = $this->testerForCommand(new DeleteShortUrlCommand($this->service)); } - /** @test */ + #[Test] public function successMessageIsPrintedIfUrlIsProperlyDeleted(): void { $shortCode = 'abc123'; @@ -48,7 +50,7 @@ class DeleteShortUrlCommandTest extends TestCase ); } - /** @test */ + #[Test] public function invalidShortCodePrintsMessage(): void { $shortCode = 'abc123'; @@ -64,10 +66,7 @@ class DeleteShortUrlCommandTest extends TestCase self::assertStringContainsString(sprintf('No URL found with short code "%s"', $shortCode), $output); } - /** - * @test - * @dataProvider provideRetryDeleteAnswers - */ + #[Test, DataProvider('provideRetryDeleteAnswers')] public function deleteIsRetriedWhenThresholdIsReachedAndQuestionIsAccepted( array $retryAnswer, int $expectedDeleteCalls, @@ -98,14 +97,14 @@ class DeleteShortUrlCommandTest extends TestCase self::assertStringContainsString($expectedMessage, $output); } - public function provideRetryDeleteAnswers(): iterable + public static function provideRetryDeleteAnswers(): iterable { yield 'answering yes to retry' => [['yes'], 2, 'Short URL with short code "abc123" successfully deleted.']; yield 'answering no to retry' => [['no'], 1, 'Short URL was not deleted.']; yield 'answering default to retry' => [[PHP_EOL], 1, 'Short URL was not deleted.']; } - /** @test */ + #[Test] public function deleteIsNotRetriedWhenThresholdIsReachedAndQuestionIsDeclined(): void { $shortCode = 'abc123'; diff --git a/module/CLI/test/Command/ShortUrl/GetShortUrlVisitsCommandTest.php b/module/CLI/test/Command/ShortUrl/GetShortUrlVisitsCommandTest.php index bd2be187..13d36f4b 100644 --- a/module/CLI/test/Command/ShortUrl/GetShortUrlVisitsCommandTest.php +++ b/module/CLI/test/Command/ShortUrl/GetShortUrlVisitsCommandTest.php @@ -6,6 +6,7 @@ namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl; use Cake\Chronos\Chronos; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\ShortUrl\GetShortUrlVisitsCommand; @@ -39,7 +40,7 @@ class GetShortUrlVisitsCommandTest extends TestCase $this->commandTester = $this->testerForCommand($command); } - /** @test */ + #[Test] public function noDateFlagsTriesToListWithoutDateRange(): void { $shortCode = 'abc123'; @@ -51,7 +52,7 @@ class GetShortUrlVisitsCommandTest extends TestCase $this->commandTester->execute(['shortCode' => $shortCode]); } - /** @test */ + #[Test] public function providingDateFlagsTheListGetsFiltered(): void { $shortCode = 'abc123'; @@ -69,7 +70,7 @@ class GetShortUrlVisitsCommandTest extends TestCase ]); } - /** @test */ + #[Test] public function providingInvalidDatesPrintsWarning(): void { $shortCode = 'abc123'; @@ -91,7 +92,7 @@ class GetShortUrlVisitsCommandTest extends TestCase ); } - /** @test */ + #[Test] public function outputIsProperlyGenerated(): void { $visit = Visit::forValidShortUrl(ShortUrl::createFake(), new Visitor('bar', 'foo', '', ''))->locate( diff --git a/module/CLI/test/Command/ShortUrl/ListShortUrlsCommandTest.php b/module/CLI/test/Command/ShortUrl/ListShortUrlsCommandTest.php index 9b45869f..6b1c790d 100644 --- a/module/CLI/test/Command/ShortUrl/ListShortUrlsCommandTest.php +++ b/module/CLI/test/Command/ShortUrl/ListShortUrlsCommandTest.php @@ -6,6 +6,8 @@ namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl; use Cake\Chronos\Chronos; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\ShortUrl\ListShortUrlsCommand; @@ -41,7 +43,7 @@ class ListShortUrlsCommandTest extends TestCase $this->commandTester = $this->testerForCommand($command); } - /** @test */ + #[Test] public function loadingMorePagesCallsListMoreTimes(): void { // The paginator will return more than one page @@ -63,7 +65,7 @@ class ListShortUrlsCommandTest extends TestCase self::assertStringNotContainsString('Continue with page 5?', $output); } - /** @test */ + #[Test] public function havingMorePagesButAnsweringNoCallsListJustOnce(): void { // The paginator will return more than one page @@ -89,7 +91,7 @@ class ListShortUrlsCommandTest extends TestCase self::assertStringNotContainsString('Continue with page 3?', $output); } - /** @test */ + #[Test] public function passingPageWillMakeListStartOnThatPage(): void { $page = 5; @@ -101,10 +103,7 @@ class ListShortUrlsCommandTest extends TestCase $this->commandTester->execute(['--page' => $page]); } - /** - * @test - * @dataProvider provideOptionalFlags - */ + #[Test, DataProvider('provideOptionalFlags')] public function provideOptionalFlagsMakesNewColumnsToBeIncluded( array $input, array $expectedContents, @@ -137,7 +136,7 @@ class ListShortUrlsCommandTest extends TestCase } } - public function provideOptionalFlags(): iterable + public static function provideOptionalFlags(): iterable { $apiKey = ApiKey::fromMeta(ApiKeyMeta::withName('my api key')); $key = $apiKey->toString(); @@ -174,10 +173,7 @@ class ListShortUrlsCommandTest extends TestCase ]; } - /** - * @test - * @dataProvider provideArgs - */ + #[Test, DataProvider('provideArgs')] public function serviceIsInvokedWithProvidedArgs( array $commandArgs, ?int $page, @@ -200,7 +196,7 @@ class ListShortUrlsCommandTest extends TestCase $this->commandTester->execute($commandArgs); } - public function provideArgs(): iterable + public static function provideArgs(): iterable { yield [[], 1, null, [], TagsMode::ANY->value]; yield [['--page' => $page = 3], $page, null, [], TagsMode::ANY->value]; @@ -241,10 +237,7 @@ class ListShortUrlsCommandTest extends TestCase ]; } - /** - * @test - * @dataProvider provideOrderBy - */ + #[Test, DataProvider('provideOrderBy')] public function orderByIsProperlyComputed(array $commandArgs, ?string $expectedOrderBy): void { $this->shortUrlService->expects($this->once())->method('listShortUrls')->with(ShortUrlsParams::fromRawData([ @@ -255,7 +248,7 @@ class ListShortUrlsCommandTest extends TestCase $this->commandTester->execute($commandArgs); } - public function provideOrderBy(): iterable + public static function provideOrderBy(): iterable { yield [[], null]; yield [['--order-by' => 'visits'], 'visits']; @@ -264,7 +257,7 @@ class ListShortUrlsCommandTest extends TestCase yield [['--order-by' => 'title-DESC'], 'title-DESC']; } - /** @test */ + #[Test] public function requestingAllElementsWillSetItemsPerPage(): void { $this->shortUrlService->expects($this->once())->method('listShortUrls')->with(ShortUrlsParams::fromRawData([ diff --git a/module/CLI/test/Command/ShortUrl/ResolveUrlCommandTest.php b/module/CLI/test/Command/ShortUrl/ResolveUrlCommandTest.php index 89614e6f..21452ed6 100644 --- a/module/CLI/test/Command/ShortUrl/ResolveUrlCommandTest.php +++ b/module/CLI/test/Command/ShortUrl/ResolveUrlCommandTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\ShortUrl\ResolveUrlCommand; @@ -31,7 +32,7 @@ class ResolveUrlCommandTest extends TestCase $this->commandTester = $this->testerForCommand(new ResolveUrlCommand($this->urlResolver)); } - /** @test */ + #[Test] public function correctShortCodeResolvesUrl(): void { $shortCode = 'abc123'; @@ -46,7 +47,7 @@ class ResolveUrlCommandTest extends TestCase self::assertEquals('Long URL: ' . $expectedUrl . PHP_EOL, $output); } - /** @test */ + #[Test] public function incorrectShortCodeOutputsErrorMessage(): void { $identifier = ShortUrlIdentifier::fromShortCodeAndDomain('abc123'); diff --git a/module/CLI/test/Command/Tag/DeleteTagsCommandTest.php b/module/CLI/test/Command/Tag/DeleteTagsCommandTest.php index 0528af24..d818ba54 100644 --- a/module/CLI/test/Command/Tag/DeleteTagsCommandTest.php +++ b/module/CLI/test/Command/Tag/DeleteTagsCommandTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Command\Tag; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\Tag\DeleteTagsCommand; @@ -24,7 +25,7 @@ class DeleteTagsCommandTest extends TestCase $this->commandTester = $this->testerForCommand(new DeleteTagsCommand($this->tagService)); } - /** @test */ + #[Test] public function errorIsReturnedWhenNoTagsAreProvided(): void { $this->commandTester->execute([]); @@ -33,7 +34,7 @@ class DeleteTagsCommandTest extends TestCase self::assertStringContainsString('You have to provide at least one tag name', $output); } - /** @test */ + #[Test] public function serviceIsInvokedOnSuccess(): void { $tagNames = ['foo', 'bar']; diff --git a/module/CLI/test/Command/Tag/GetTagVisitsCommandTest.php b/module/CLI/test/Command/Tag/GetTagVisitsCommandTest.php index b7255d0a..ef34952d 100644 --- a/module/CLI/test/Command/Tag/GetTagVisitsCommandTest.php +++ b/module/CLI/test/Command/Tag/GetTagVisitsCommandTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Command\Tag; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\Tag\GetTagVisitsCommand; @@ -37,7 +38,7 @@ class GetTagVisitsCommandTest extends TestCase ); } - /** @test */ + #[Test] public function outputIsProperlyGenerated(): void { $shortUrl = ShortUrl::createFake(); diff --git a/module/CLI/test/Command/Tag/ListTagsCommandTest.php b/module/CLI/test/Command/Tag/ListTagsCommandTest.php index 6ac53f8a..e1020667 100644 --- a/module/CLI/test/Command/Tag/ListTagsCommandTest.php +++ b/module/CLI/test/Command/Tag/ListTagsCommandTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Command\Tag; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\Tag\ListTagsCommand; @@ -27,7 +28,7 @@ class ListTagsCommandTest extends TestCase $this->commandTester = $this->testerForCommand(new ListTagsCommand($this->tagService)); } - /** @test */ + #[Test] public function noTagsPrintsEmptyMessage(): void { $this->tagService->expects($this->once())->method('tagsInfo')->withAnyParameters()->willReturn( @@ -40,7 +41,7 @@ class ListTagsCommandTest extends TestCase self::assertStringContainsString('No tags found', $output); } - /** @test */ + #[Test] public function listOfTagsIsPrinted(): void { $this->tagService->expects($this->once())->method('tagsInfo')->withAnyParameters()->willReturn( diff --git a/module/CLI/test/Command/Tag/RenameTagCommandTest.php b/module/CLI/test/Command/Tag/RenameTagCommandTest.php index 95a1e85d..7dfe474f 100644 --- a/module/CLI/test/Command/Tag/RenameTagCommandTest.php +++ b/module/CLI/test/Command/Tag/RenameTagCommandTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Command\Tag; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\Tag\RenameTagCommand; @@ -27,7 +28,7 @@ class RenameTagCommandTest extends TestCase $this->commandTester = $this->testerForCommand(new RenameTagCommand($this->tagService)); } - /** @test */ + #[Test] public function errorIsPrintedIfExceptionIsThrown(): void { $oldName = 'foo'; @@ -45,7 +46,7 @@ class RenameTagCommandTest extends TestCase self::assertStringContainsString('Tag with name "foo" could not be found', $output); } - /** @test */ + #[Test] public function successIsPrintedIfNoErrorOccurs(): void { $oldName = 'foo'; diff --git a/module/CLI/test/Command/Visit/DownloadGeoLiteDbCommandTest.php b/module/CLI/test/Command/Visit/DownloadGeoLiteDbCommandTest.php index 742fa31b..7f2cb3ac 100644 --- a/module/CLI/test/Command/Visit/DownloadGeoLiteDbCommandTest.php +++ b/module/CLI/test/Command/Visit/DownloadGeoLiteDbCommandTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Command\Visit; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\Visit\DownloadGeoLiteDbCommand; @@ -29,10 +31,7 @@ class DownloadGeoLiteDbCommandTest extends TestCase $this->commandTester = $this->testerForCommand(new DownloadGeoLiteDbCommand($this->dbUpdater)); } - /** - * @test - * @dataProvider provideFailureParams - */ + #[Test, DataProvider('provideFailureParams')] public function showsProperMessageWhenGeoLiteUpdateFails( bool $olderDbExists, string $expectedMessage, @@ -61,7 +60,7 @@ class DownloadGeoLiteDbCommandTest extends TestCase self::assertSame($expectedExitCode, $exitCode); } - public function provideFailureParams(): iterable + public static function provideFailureParams(): iterable { yield 'existing db' => [ true, @@ -75,10 +74,7 @@ class DownloadGeoLiteDbCommandTest extends TestCase ]; } - /** - * @test - * @dataProvider provideSuccessParams - */ + #[Test, DataProvider('provideSuccessParams')] public function printsExpectedMessageWhenNoErrorOccurs(callable $checkUpdateBehavior, string $expectedMessage): void { $this->dbUpdater->expects($this->once())->method('checkDbUpdate')->withAnyParameters()->willReturnCallback( @@ -93,7 +89,7 @@ class DownloadGeoLiteDbCommandTest extends TestCase self::assertSame(ExitCodes::EXIT_SUCCESS, $exitCode); } - public function provideSuccessParams(): iterable + public static function provideSuccessParams(): iterable { yield 'up to date db' => [fn () => GeolocationResult::CHECK_SKIPPED, '[INFO] GeoLite2 db file is up to date.']; yield 'outdated db' => [function (callable $beforeDownload): GeolocationResult { diff --git a/module/CLI/test/Command/Visit/GetNonOrphanVisitsCommandTest.php b/module/CLI/test/Command/Visit/GetNonOrphanVisitsCommandTest.php index c780208a..dabfdb06 100644 --- a/module/CLI/test/Command/Visit/GetNonOrphanVisitsCommandTest.php +++ b/module/CLI/test/Command/Visit/GetNonOrphanVisitsCommandTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Command\Visit; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\Visit\GetNonOrphanVisitsCommand; @@ -37,7 +38,7 @@ class GetNonOrphanVisitsCommandTest extends TestCase ); } - /** @test */ + #[Test] public function outputIsProperlyGenerated(): void { $shortUrl = ShortUrl::createFake(); diff --git a/module/CLI/test/Command/Visit/GetOrphanVisitsCommandTest.php b/module/CLI/test/Command/Visit/GetOrphanVisitsCommandTest.php index 199578f3..226cb927 100644 --- a/module/CLI/test/Command/Visit/GetOrphanVisitsCommandTest.php +++ b/module/CLI/test/Command/Visit/GetOrphanVisitsCommandTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Command\Visit; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\Visit\GetOrphanVisitsCommand; @@ -30,7 +31,7 @@ class GetOrphanVisitsCommandTest extends TestCase $this->commandTester = $this->testerForCommand(new GetOrphanVisitsCommand($this->visitsHelper)); } - /** @test */ + #[Test] public function outputIsProperlyGenerated(): void { $visit = Visit::forBasePath(new Visitor('bar', 'foo', '', ''))->locate( diff --git a/module/CLI/test/Command/Visit/LocateVisitsCommandTest.php b/module/CLI/test/Command/Visit/LocateVisitsCommandTest.php index 44638249..aa775a24 100644 --- a/module/CLI/test/Command/Visit/LocateVisitsCommandTest.php +++ b/module/CLI/test/Command/Visit/LocateVisitsCommandTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Command\Visit; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Command\Visit\DownloadGeoLiteDbCommand; @@ -55,10 +57,7 @@ class LocateVisitsCommandTest extends TestCase $this->commandTester = $this->testerForCommand($command, $this->downloadDbCommand); } - /** - * @test - * @dataProvider provideArgs - */ + #[Test, DataProvider('provideArgs')] public function expectedSetOfVisitsIsProcessedBasedOnArgs( int $expectedUnlocatedCalls, int $expectedEmptyCalls, @@ -100,17 +99,14 @@ class LocateVisitsCommandTest extends TestCase } } - public function provideArgs(): iterable + public static function provideArgs(): iterable { yield 'no args' => [1, 0, 0, false, []]; yield 'retry' => [1, 1, 0, false, ['--retry' => true]]; yield 'all' => [0, 0, 1, true, ['--retry' => true, '--all' => true]]; } - /** - * @test - * @dataProvider provideIgnoredAddresses - */ + #[Test, DataProvider('provideIgnoredAddresses')] public function localhostAndEmptyAddressesAreIgnored(IpCannotBeLocatedException $e, string $message): void { $visit = Visit::forValidShortUrl(ShortUrl::createFake(), Visitor::emptyInstance()); @@ -131,13 +127,13 @@ class LocateVisitsCommandTest extends TestCase self::assertStringContainsString($message, $output); } - public function provideIgnoredAddresses(): iterable + public static function provideIgnoredAddresses(): iterable { yield 'empty address' => [IpCannotBeLocatedException::forEmptyAddress(), 'Ignored visit with no IP address']; yield 'localhost address' => [IpCannotBeLocatedException::forLocalhost(), 'Ignored localhost address']; } - /** @test */ + #[Test] public function errorWhileLocatingIpIsDisplayed(): void { $visit = Visit::forValidShortUrl(ShortUrl::createFake(), new Visitor('', '', '1.2.3.4', '')); @@ -168,7 +164,7 @@ class LocateVisitsCommandTest extends TestCase }; } - /** @test */ + #[Test] public function noActionIsPerformedIfLockIsAcquired(): void { $this->lock->method('acquire')->with($this->isFalse())->willReturn(false); @@ -186,7 +182,7 @@ class LocateVisitsCommandTest extends TestCase ); } - /** @test */ + #[Test] public function showsProperMessageWhenGeoLiteUpdateFails(): void { $this->lock->method('acquire')->with($this->isFalse())->willReturn(true); @@ -199,7 +195,7 @@ class LocateVisitsCommandTest extends TestCase self::assertStringContainsString('It is not possible to locate visits without a GeoLite2 db file.', $output); } - /** @test */ + #[Test] public function providingAllFlagOnItsOwnDisplaysNotice(): void { $this->lock->method('acquire')->with($this->isFalse())->willReturn(true); @@ -211,10 +207,7 @@ class LocateVisitsCommandTest extends TestCase self::assertStringContainsString('The --all flag has no effect on its own', $output); } - /** - * @test - * @dataProvider provideAbortInputs - */ + #[Test, DataProvider('provideAbortInputs')] public function processingAllCancelsCommandIfUserDoesNotActivelyAgreeToConfirmation(array $inputs): void { $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_SUCCESS); @@ -226,7 +219,7 @@ class LocateVisitsCommandTest extends TestCase $this->commandTester->execute(['--all' => true, '--retry' => true]); } - public function provideAbortInputs(): iterable + public static function provideAbortInputs(): iterable { yield 'n' => [['n']]; yield 'no' => [['no']]; diff --git a/module/CLI/test/ConfigProviderTest.php b/module/CLI/test/ConfigProviderTest.php index f01649e0..b87e7cd3 100644 --- a/module/CLI/test/ConfigProviderTest.php +++ b/module/CLI/test/ConfigProviderTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI; use Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\ConfigProvider; @@ -17,7 +18,7 @@ class ConfigProviderTest extends TestCase $this->configProvider = new ConfigProvider(); } - /** @test */ + #[Test] public function configIsProperlyReturned(): void { $config = ($this->configProvider)(); diff --git a/module/CLI/test/Exception/GeolocationDbUpdateFailedExceptionTest.php b/module/CLI/test/Exception/GeolocationDbUpdateFailedExceptionTest.php index 470aed2c..3196dd04 100644 --- a/module/CLI/test/Exception/GeolocationDbUpdateFailedExceptionTest.php +++ b/module/CLI/test/Exception/GeolocationDbUpdateFailedExceptionTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Exception; use Exception; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use RuntimeException; use Shlinkio\Shlink\CLI\Exception\GeolocationDbUpdateFailedException; @@ -12,10 +14,7 @@ use Throwable; class GeolocationDbUpdateFailedExceptionTest extends TestCase { - /** - * @test - * @dataProvider providePrev - */ + #[Test, DataProvider('providePrev')] public function withOlderDbBuildsException(?Throwable $prev): void { $e = GeolocationDbUpdateFailedException::withOlderDb($prev); @@ -29,10 +28,7 @@ class GeolocationDbUpdateFailedExceptionTest extends TestCase self::assertEquals($prev, $e->getPrevious()); } - /** - * @test - * @dataProvider providePrev - */ + #[Test, DataProvider('providePrev')] public function withoutOlderDbBuildsException(?Throwable $prev): void { $e = GeolocationDbUpdateFailedException::withoutOlderDb($prev); @@ -46,14 +42,14 @@ class GeolocationDbUpdateFailedExceptionTest extends TestCase self::assertEquals($prev, $e->getPrevious()); } - public function providePrev(): iterable + public static function providePrev(): iterable { yield 'no prev' => [null]; yield 'RuntimeException' => [new RuntimeException('prev')]; yield 'Exception' => [new Exception('prev')]; } - /** @test */ + #[Test] public function withInvalidEpochInOldDbBuildsException(): void { $e = GeolocationDbUpdateFailedException::withInvalidEpochInOldDb('foobar'); diff --git a/module/CLI/test/Exception/InvalidRoleConfigExceptionTest.php b/module/CLI/test/Exception/InvalidRoleConfigExceptionTest.php index 99c66ea4..180007af 100644 --- a/module/CLI/test/Exception/InvalidRoleConfigExceptionTest.php +++ b/module/CLI/test/Exception/InvalidRoleConfigExceptionTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Exception; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Exception\InvalidRoleConfigException; use Shlinkio\Shlink\Rest\ApiKey\Role; @@ -12,7 +13,7 @@ use function sprintf; class InvalidRoleConfigExceptionTest extends TestCase { - /** @test */ + #[Test] public function forDomainOnlyWithDefaultDomainGeneratesExpectedException(): void { $e = InvalidRoleConfigException::forDomainOnlyWithDefaultDomain(); diff --git a/module/CLI/test/Factory/ApplicationFactoryTest.php b/module/CLI/test/Factory/ApplicationFactoryTest.php index c93731c1..3d75c647 100644 --- a/module/CLI/test/Factory/ApplicationFactoryTest.php +++ b/module/CLI/test/Factory/ApplicationFactoryTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Factory; use Laminas\ServiceManager\ServiceManager; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Factory\ApplicationFactory; use Shlinkio\Shlink\Core\Options\AppOptions; @@ -21,7 +22,7 @@ class ApplicationFactoryTest extends TestCase $this->factory = new ApplicationFactory(); } - /** @test */ + #[Test] public function allCommandsWhichAreServicesAreAdded(): void { $sm = $this->createServiceManager([ diff --git a/module/CLI/test/GeoLite/GeolocationDbUpdaterTest.php b/module/CLI/test/GeoLite/GeolocationDbUpdaterTest.php index 8d6188e9..2d47d79c 100644 --- a/module/CLI/test/GeoLite/GeolocationDbUpdaterTest.php +++ b/module/CLI/test/GeoLite/GeolocationDbUpdaterTest.php @@ -7,6 +7,8 @@ namespace ShlinkioTest\Shlink\CLI\GeoLite; use Cake\Chronos\Chronos; use GeoIp2\Database\Reader; use MaxMind\Db\Reader\Metadata; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Exception\GeolocationDbUpdateFailedException; @@ -35,7 +37,7 @@ class GeolocationDbUpdaterTest extends TestCase $this->lock->method('acquire')->with($this->isTrue())->willReturn(true); } - /** @test */ + #[Test] public function exceptionIsThrownWhenOlderDbDoesNotExistAndDownloadFails(): void { $mustBeUpdated = fn () => self::assertTrue(true); @@ -58,10 +60,7 @@ class GeolocationDbUpdaterTest extends TestCase } } - /** - * @test - * @dataProvider provideBigDays - */ + #[Test, DataProvider('provideBigDays')] public function exceptionIsThrownWhenOlderDbIsTooOldAndDownloadFails(int $days): void { $prev = new DbUpdateException(''); @@ -84,7 +83,7 @@ class GeolocationDbUpdaterTest extends TestCase } } - public function provideBigDays(): iterable + public static function provideBigDays(): iterable { yield [36]; yield [50]; @@ -92,10 +91,7 @@ class GeolocationDbUpdaterTest extends TestCase yield [100]; } - /** - * @test - * @dataProvider provideSmallDays - */ + #[Test, DataProvider('provideSmallDays')] public function databaseIsNotUpdatedIfItIsNewEnough(string|int $buildEpoch): void { $this->dbUpdater->expects($this->once())->method('databaseFileExists')->willReturn(true); @@ -109,7 +105,7 @@ class GeolocationDbUpdaterTest extends TestCase self::assertEquals(GeolocationResult::DB_IS_UP_TO_DATE, $result); } - public function provideSmallDays(): iterable + public static function provideSmallDays(): iterable { $generateParamsWithTimestamp = static function (int $days) { $timestamp = Chronos::now()->subDays($days)->getTimestamp(); @@ -119,7 +115,7 @@ class GeolocationDbUpdaterTest extends TestCase return map(range(0, 34), $generateParamsWithTimestamp); } - /** @test */ + #[Test] public function exceptionIsThrownWhenCheckingExistingDatabaseWithInvalidBuildEpoch(): void { $this->dbUpdater->expects($this->once())->method('databaseFileExists')->willReturn(true); @@ -151,10 +147,7 @@ class GeolocationDbUpdaterTest extends TestCase ]); } - /** - * @test - * @dataProvider provideTrackingOptions - */ + #[Test, DataProvider('provideTrackingOptions')] public function downloadDbIsSkippedIfTrackingIsDisabled(TrackingOptions $options): void { $result = $this->geolocationDbUpdater($options)->checkDbUpdate(); @@ -164,7 +157,7 @@ class GeolocationDbUpdaterTest extends TestCase self::assertEquals(GeolocationResult::CHECK_SKIPPED, $result); } - public function provideTrackingOptions(): iterable + public static function provideTrackingOptions(): iterable { yield 'disableTracking' => [new TrackingOptions(disableTracking: true)]; yield 'disableIpTracking' => [new TrackingOptions(disableIpTracking: true)]; diff --git a/module/CLI/test/Util/ProcessRunnerTest.php b/module/CLI/test/Util/ProcessRunnerTest.php index a23d1b48..16cc2d43 100644 --- a/module/CLI/test/Util/ProcessRunnerTest.php +++ b/module/CLI/test/Util/ProcessRunnerTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Util; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\CLI\Util\ProcessRunner; @@ -34,7 +35,7 @@ class ProcessRunnerTest extends TestCase $this->runner = new ProcessRunner($this->helper, fn () => $this->process); } - /** @test */ + #[Test] public function noMessagesAreWrittenWhenOutputIsNotVerbose(): void { $this->output->expects($this->exactly(2))->method('isVeryVerbose')->with()->willReturn(false); @@ -50,7 +51,7 @@ class ProcessRunnerTest extends TestCase $this->runner->run($this->output, []); } - /** @test */ + #[Test] public function someMessagesAreWrittenWhenOutputIsVerbose(): void { $this->output->expects($this->exactly(2))->method('isVeryVerbose')->with()->willReturn(true); @@ -66,7 +67,7 @@ class ProcessRunnerTest extends TestCase $this->runner->run($this->output, []); } - /** @test */ + #[Test] public function wrapsCallbackWhenOutputIsDebug(): void { $this->output->expects($this->exactly(2))->method('isVeryVerbose')->with()->willReturn(false); diff --git a/module/CLI/test/Util/ShlinkTableTest.php b/module/CLI/test/Util/ShlinkTableTest.php index 829e56d9..19d477ef 100644 --- a/module/CLI/test/Util/ShlinkTableTest.php +++ b/module/CLI/test/Util/ShlinkTableTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\CLI\Util; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use ReflectionObject; @@ -23,7 +24,7 @@ class ShlinkTableTest extends TestCase $this->shlinkTable = ShlinkTable::fromBaseTable($this->baseTable); } - /** @test */ + #[Test] public function renderMakesTableToBeRenderedWithProvidedInfo(): void { $headers = []; @@ -43,7 +44,7 @@ class ShlinkTableTest extends TestCase $this->shlinkTable->render($headers, $rows, $footerTitle, $headerTitle); } - /** @test */ + #[Test] public function newTableIsCreatedForFactoryMethod(): void { $instance = ShlinkTable::default($this->createMock(OutputInterface::class)); diff --git a/module/Core/test-api/Action/RedirectTest.php b/module/Core/test-api/Action/RedirectTest.php index 73b6a1cc..f3edcbe4 100644 --- a/module/Core/test-api/Action/RedirectTest.php +++ b/module/Core/test-api/Action/RedirectTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Core\Action; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; use const ShlinkioTest\Shlink\ANDROID_USER_AGENT; @@ -12,17 +14,14 @@ use const ShlinkioTest\Shlink\IOS_USER_AGENT; class RedirectTest extends ApiTestCase { - /** - * @test - * @dataProvider provideUserAgents - */ + #[Test, DataProvider('provideUserAgents')] public function properRedirectHappensBasedOnUserAgent(?string $userAgent, string $expectedRedirect): void { $response = $this->callShortUrl('def456', $userAgent); 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']; diff --git a/module/Core/test-api/Action/RobotsTest.php b/module/Core/test-api/Action/RobotsTest.php index cf1efdb9..490c82fb 100644 --- a/module/Core/test-api/Action/RobotsTest.php +++ b/module/Core/test-api/Action/RobotsTest.php @@ -4,11 +4,12 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Core\Action; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; class RobotsTest extends ApiTestCase { - /** @test */ + #[Test] public function expectedListOfCrawlableShortCodesIsReturned(): void { $resp = $this->callShortUrl('robots.txt'); diff --git a/module/Core/test-db/Domain/Repository/DomainRepositoryTest.php b/module/Core/test-db/Domain/Repository/DomainRepositoryTest.php index 2b005947..24824ee4 100644 --- a/module/Core/test-db/Domain/Repository/DomainRepositoryTest.php +++ b/module/Core/test-db/Domain/Repository/DomainRepositoryTest.php @@ -6,6 +6,7 @@ namespace ShlinkioDbTest\Shlink\Core\Domain\Repository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\Core\Config\NotFoundRedirects; use Shlinkio\Shlink\Core\Domain\Entity\Domain; use Shlinkio\Shlink\Core\Domain\Repository\DomainRepository; @@ -26,7 +27,7 @@ class DomainRepositoryTest extends DatabaseTestCase $this->repo = $this->getEntityManager()->getRepository(Domain::class); } - /** @test */ + #[Test] public function expectedDomainsAreFoundWhenNoApiKeyIsInvolved(): void { $fooDomain = Domain::withAuthority('foo.com'); @@ -61,7 +62,7 @@ class DomainRepositoryTest extends DatabaseTestCase self::assertTrue($this->repo->domainExists('detached.com')); } - /** @test */ + #[Test] public function expectedDomainsAreFoundWhenApiKeyIsProvided(): void { $authorApiKey = ApiKey::fromMeta(ApiKeyMeta::withRoles(RoleDefinition::forAuthoredShortUrls())); diff --git a/module/Core/test-db/ShortUrl/Repository/CrawlableShortCodesQueryTest.php b/module/Core/test-db/ShortUrl/Repository/CrawlableShortCodesQueryTest.php index 04c670fa..47f13567 100644 --- a/module/Core/test-db/ShortUrl/Repository/CrawlableShortCodesQueryTest.php +++ b/module/Core/test-db/ShortUrl/Repository/CrawlableShortCodesQueryTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioDbTest\Shlink\Core\ShortUrl\Repository; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation; use Shlinkio\Shlink\Core\ShortUrl\Repository\CrawlableShortCodesQuery; @@ -19,7 +20,7 @@ class CrawlableShortCodesQueryTest extends DatabaseTestCase $this->query = new CrawlableShortCodesQuery($em, $em->getClassMetadata(ShortUrl::class)); } - /** @test */ + #[Test] public function invokingQueryReturnsExpectedResult(): void { $createShortUrl = fn (bool $crawlable) => ShortUrl::create( diff --git a/module/Core/test-db/ShortUrl/Repository/ShortUrlListRepositoryTest.php b/module/Core/test-db/ShortUrl/Repository/ShortUrlListRepositoryTest.php index d55c301c..97c6dd22 100644 --- a/module/Core/test-db/ShortUrl/Repository/ShortUrlListRepositoryTest.php +++ b/module/Core/test-db/ShortUrl/Repository/ShortUrlListRepositoryTest.php @@ -6,6 +6,7 @@ namespace ShlinkioDbTest\Shlink\Core\ShortUrl\Repository; use Cake\Chronos\Chronos; use Doctrine\Common\Collections\ArrayCollection; +use PHPUnit\Framework\Attributes\Test; use ReflectionObject; use Shlinkio\Shlink\Common\Util\DateRange; use Shlinkio\Shlink\Core\Model\Ordering; @@ -37,7 +38,7 @@ class ShortUrlListRepositoryTest extends DatabaseTestCase $this->relationResolver = new PersistenceShortUrlRelationResolver($em); } - /** @test */ + #[Test] public function countListReturnsProperNumberOfResults(): void { $count = 5; @@ -49,7 +50,7 @@ class ShortUrlListRepositoryTest extends DatabaseTestCase self::assertEquals($count, $this->repo->countList(new ShortUrlsCountFiltering())); } - /** @test */ + #[Test] public function findListProperlyFiltersResult(): void { $foo = ShortUrl::create( @@ -143,7 +144,7 @@ class ShortUrlListRepositoryTest extends DatabaseTestCase )); } - /** @test */ + #[Test] public function findListProperlyMapsFieldNamesToColumnNamesWhenOrdering(): void { $urls = ['a', 'z', 'c', 'b']; @@ -164,7 +165,7 @@ class ShortUrlListRepositoryTest extends DatabaseTestCase self::assertEquals('z', $result[3]->getLongUrl()); } - /** @test */ + #[Test] public function findListReturnsOnlyThoseWithMatchingTags(): void { $shortUrl1 = ShortUrl::create(ShortUrlCreation::fromRawData([ @@ -273,7 +274,7 @@ class ShortUrlListRepositoryTest extends DatabaseTestCase )); } - /** @test */ + #[Test] public function findListReturnsOnlyThoseWithMatchingDomains(): void { $shortUrl1 = ShortUrl::create(ShortUrlCreation::fromRawData([ @@ -309,7 +310,7 @@ class ShortUrlListRepositoryTest extends DatabaseTestCase self::assertCount(0, $this->repo->findList($buildFiltering('no results'))); } - /** @test */ + #[Test] public function findListReturnsOnlyThoseWithoutExcludedUrls(): void { $shortUrl1 = ShortUrl::create(ShortUrlCreation::fromRawData([ diff --git a/module/Core/test-db/ShortUrl/Repository/ShortUrlRepositoryTest.php b/module/Core/test-db/ShortUrl/Repository/ShortUrlRepositoryTest.php index 31cac3dc..f2cce0f7 100644 --- a/module/Core/test-db/ShortUrl/Repository/ShortUrlRepositoryTest.php +++ b/module/Core/test-db/ShortUrl/Repository/ShortUrlRepositoryTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ShlinkioDbTest\Shlink\Core\ShortUrl\Repository; use Cake\Chronos\Chronos; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\Core\Domain\Entity\Domain; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation; @@ -30,7 +31,7 @@ class ShortUrlRepositoryTest extends DatabaseTestCase $this->relationResolver = new PersistenceShortUrlRelationResolver($this->getEntityManager()); } - /** @test */ + #[Test] public function findOneWithDomainFallbackReturnsProperData(): void { $regularOne = ShortUrl::create(ShortUrlCreation::fromRawData(['customSlug' => 'Foo', 'longUrl' => 'foo'])); @@ -97,7 +98,7 @@ class ShortUrlRepositoryTest extends DatabaseTestCase )); } - /** @test */ + #[Test] public function shortCodeIsInUseLooksForShortUrlInProperSetOfTables(): void { $shortUrlWithoutDomain = ShortUrl::create( @@ -126,7 +127,7 @@ class ShortUrlRepositoryTest extends DatabaseTestCase )); } - /** @test */ + #[Test] public function findOneLooksForShortUrlInProperSetOfTables(): void { $shortUrlWithoutDomain = ShortUrl::create( @@ -153,7 +154,7 @@ class ShortUrlRepositoryTest extends DatabaseTestCase )); } - /** @test */ + #[Test] public function findOneMatchingReturnsNullForNonExistingShortUrls(): void { self::assertNull($this->repo->findOneMatching(ShortUrlCreation::fromRawData(['longUrl' => 'foobar']))); @@ -168,7 +169,7 @@ class ShortUrlRepositoryTest extends DatabaseTestCase ]))); } - /** @test */ + #[Test] public function findOneMatchingAppliesProperConditions(): void { $start = Chronos::parse('2020-03-05 20:18:30'); @@ -237,7 +238,7 @@ class ShortUrlRepositoryTest extends DatabaseTestCase ); } - /** @test */ + #[Test] public function findOneMatchingReturnsOldestOneWhenThereAreMultipleMatches(): void { $start = Chronos::parse('2020-03-05 20:18:30'); @@ -265,7 +266,7 @@ class ShortUrlRepositoryTest extends DatabaseTestCase self::assertNotSame($shortUrl3, $result); } - /** @test */ + #[Test] public function findOneMatchingAppliesProvidedApiKeyConditions(): void { $start = Chronos::parse('2020-03-05 20:18:30'); @@ -391,7 +392,7 @@ class ShortUrlRepositoryTest extends DatabaseTestCase ); } - /** @test */ + #[Test] public function importedShortUrlsAreFoundWhenExpected(): void { $buildImported = static fn (string $shortCode, ?String $domain = null) => diff --git a/module/Core/test-db/Tag/Paginator/Adapter/TagsPaginatorAdapterTest.php b/module/Core/test-db/Tag/Paginator/Adapter/TagsPaginatorAdapterTest.php index 385f2335..0dd83341 100644 --- a/module/Core/test-db/Tag/Paginator/Adapter/TagsPaginatorAdapterTest.php +++ b/module/Core/test-db/Tag/Paginator/Adapter/TagsPaginatorAdapterTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioDbTest\Shlink\Core\Tag\Paginator\Adapter; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\Core\Tag\Entity\Tag; use Shlinkio\Shlink\Core\Tag\Model\TagsParams; use Shlinkio\Shlink\Core\Tag\Paginator\Adapter\TagsPaginatorAdapter; @@ -24,9 +26,8 @@ class TagsPaginatorAdapterTest extends DatabaseTestCase /** * @param int<0, max> $offset * @param int<0, max> $length - * @test - * @dataProvider provideFilters */ + #[Test, DataProvider('provideFilters')] public function expectedListOfTagsIsReturned( ?string $searchTerm, ?string $orderBy, @@ -52,7 +53,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]; diff --git a/module/Core/test-db/Tag/Repository/TagRepositoryTest.php b/module/Core/test-db/Tag/Repository/TagRepositoryTest.php index 97873b20..47b4b41d 100644 --- a/module/Core/test-db/Tag/Repository/TagRepositoryTest.php +++ b/module/Core/test-db/Tag/Repository/TagRepositoryTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioDbTest\Shlink\Core\Tag\Repository; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\Core\Domain\Entity\Domain; use Shlinkio\Shlink\Core\Model\Ordering; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; @@ -34,13 +36,13 @@ class TagRepositoryTest extends DatabaseTestCase $this->relationResolver = new PersistenceShortUrlRelationResolver($this->getEntityManager()); } - /** @test */ + #[Test] public function deleteByNameDoesNothingWhenEmptyListIsProvided(): void { self::assertEquals(0, $this->repo->deleteByName([])); } - /** @test */ + #[Test] public function allTagsWhichMatchNameAreDeleted(): void { $names = ['foo', 'bar', 'baz']; @@ -54,10 +56,7 @@ class TagRepositoryTest extends DatabaseTestCase self::assertEquals(2, $this->repo->deleteByName($toDelete)); } - /** - * @test - * @dataProvider provideFilters - */ + #[Test, DataProvider('provideFilters')] public function properTagsInfoIsReturned(?TagsListFiltering $filtering, array $expectedList): void { $names = ['foo', 'bar', 'baz', 'another']; @@ -109,7 +108,7 @@ class TagRepositoryTest extends DatabaseTestCase } } - public function provideFilters(): iterable + public static function provideFilters(): iterable { $defaultList = [ ['another', 0, 0, 0], @@ -221,7 +220,7 @@ class TagRepositoryTest extends DatabaseTestCase ]]; } - /** @test */ + #[Test] public function tagExistsReturnsExpectedResultBasedOnApiKey(): void { $domain = Domain::withAuthority('foo.com'); diff --git a/module/Core/test-db/Visit/Repository/VisitLocationRepositoryTest.php b/module/Core/test-db/Visit/Repository/VisitLocationRepositoryTest.php index 6b7c1e0d..79c80a24 100644 --- a/module/Core/test-db/Visit/Repository/VisitLocationRepositoryTest.php +++ b/module/Core/test-db/Visit/Repository/VisitLocationRepositoryTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioDbTest\Shlink\Core\Visit\Repository; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; use Shlinkio\Shlink\Core\Visit\Entity\Visit; use Shlinkio\Shlink\Core\Visit\Entity\VisitLocation; @@ -25,10 +27,7 @@ class VisitLocationRepositoryTest extends DatabaseTestCase $this->repo = new VisitLocationRepository($em, $em->getClassMetadata(Visit::class)); } - /** - * @test - * @dataProvider provideBlockSize - */ + #[Test, DataProvider('provideBlockSize')] public function findVisitsReturnsProperVisits(int $blockSize): void { $shortUrl = ShortUrl::createFake(); @@ -56,7 +55,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]); } diff --git a/module/Core/test-db/Visit/Repository/VisitRepositoryTest.php b/module/Core/test-db/Visit/Repository/VisitRepositoryTest.php index f1fed415..3e0ca9bf 100644 --- a/module/Core/test-db/Visit/Repository/VisitRepositoryTest.php +++ b/module/Core/test-db/Visit/Repository/VisitRepositoryTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ShlinkioDbTest\Shlink\Core\Visit\Repository; use Cake\Chronos\Chronos; +use PHPUnit\Framework\Attributes\Test; use ReflectionObject; use Shlinkio\Shlink\Common\Util\DateRange; use Shlinkio\Shlink\Core\Domain\Entity\Domain; @@ -40,7 +41,7 @@ class VisitRepositoryTest extends DatabaseTestCase $this->relationResolver = new PersistenceShortUrlRelationResolver($this->getEntityManager()); } - /** @test */ + #[Test] public function findVisitsByShortCodeReturnsProperData(): void { [$shortCode, $domain] = $this->createShortUrlsAndVisits(); @@ -89,7 +90,7 @@ class VisitRepositoryTest extends DatabaseTestCase )); } - /** @test */ + #[Test] public function countVisitsByShortCodeReturnsProperData(): void { [$shortCode, $domain] = $this->createShortUrlsAndVisits(); @@ -126,7 +127,7 @@ class VisitRepositoryTest extends DatabaseTestCase )); } - /** @test */ + #[Test] public function findVisitsByShortCodeReturnsProperDataWhenUsingAPiKeys(): void { $adminApiKey = ApiKey::create(); @@ -158,7 +159,7 @@ class VisitRepositoryTest extends DatabaseTestCase )); } - /** @test */ + #[Test] public function findVisitsByTagReturnsProperData(): void { $foo = 'foo'; @@ -183,7 +184,7 @@ class VisitRepositoryTest extends DatabaseTestCase ))); } - /** @test */ + #[Test] public function countVisitsByTagReturnsProperData(): void { $foo = 'foo'; @@ -205,7 +206,7 @@ class VisitRepositoryTest extends DatabaseTestCase ))); } - /** @test */ + #[Test] public function findVisitsByDomainReturnsProperData(): void { $this->createShortUrlsAndVisits('s.test'); @@ -229,7 +230,7 @@ class VisitRepositoryTest extends DatabaseTestCase ))); } - /** @test */ + #[Test] public function countVisitsByDomainReturnsProperData(): void { $this->createShortUrlsAndVisits('s.test'); @@ -253,7 +254,7 @@ class VisitRepositoryTest extends DatabaseTestCase ))); } - /** @test */ + #[Test] public function countVisitsReturnsExpectedResultBasedOnApiKey(): void { $domain = Domain::withAuthority('foo.com'); @@ -316,7 +317,7 @@ class VisitRepositoryTest extends DatabaseTestCase self::assertEquals(3, $this->repo->countOrphanVisits(new VisitsCountFiltering(null, true))); } - /** @test */ + #[Test] public function findOrphanVisitsReturnsExpectedResult(): void { $shortUrl = ShortUrl::create(ShortUrlCreation::fromRawData(['longUrl' => 'longUrl'])); @@ -365,7 +366,7 @@ class VisitRepositoryTest extends DatabaseTestCase ))); } - /** @test */ + #[Test] public function countOrphanVisitsReturnsExpectedResult(): void { $shortUrl = ShortUrl::create(ShortUrlCreation::fromRawData(['longUrl' => 'longUrl'])); @@ -402,7 +403,7 @@ class VisitRepositoryTest extends DatabaseTestCase )); } - /** @test */ + #[Test] public function findNonOrphanVisitsReturnsExpectedResult(): void { $shortUrl = ShortUrl::create(ShortUrlCreation::fromRawData(['longUrl' => '1'])); @@ -445,7 +446,7 @@ class VisitRepositoryTest extends DatabaseTestCase self::assertCount(5, $this->repo->findNonOrphanVisits(new VisitsListFiltering(null, false, null, 5, 5))); } - /** @test */ + #[Test] public function findMostRecentOrphanVisitReturnsExpectedVisit(): void { $this->assertNull($this->repo->findMostRecentOrphanVisit()); diff --git a/module/Core/test/Action/PixelActionTest.php b/module/Core/test/Action/PixelActionTest.php index b493e2cb..d6f2566a 100644 --- a/module/Core/test/Action/PixelActionTest.php +++ b/module/Core/test/Action/PixelActionTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Action; use Laminas\Diactoros\ServerRequest; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Server\RequestHandlerInterface; @@ -29,7 +30,7 @@ class PixelActionTest extends TestCase $this->action = new PixelAction($this->urlResolver, $this->requestTracker); } - /** @test */ + #[Test] public function imageIsReturned(): void { $shortCode = 'abc123'; diff --git a/module/Core/test/Action/QrCodeActionTest.php b/module/Core/test/Action/QrCodeActionTest.php index 684e9217..f6850c1f 100644 --- a/module/Core/test/Action/QrCodeActionTest.php +++ b/module/Core/test/Action/QrCodeActionTest.php @@ -7,6 +7,8 @@ namespace ShlinkioTest\Shlink\Core\Action; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequest; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; @@ -37,7 +39,7 @@ class QrCodeActionTest extends TestCase $this->urlResolver = $this->createMock(ShortUrlResolverInterface::class); } - /** @test */ + #[Test] public function aNotFoundShortCodeWillDelegateIntoNextMiddleware(): void { $shortCode = 'abc123'; @@ -50,7 +52,7 @@ class QrCodeActionTest extends TestCase $this->action()->process((new ServerRequest())->withAttribute('shortCode', $shortCode), $delegate); } - /** @test */ + #[Test] public function aCorrectRequestReturnsTheQrCodeResponse(): void { $shortCode = 'abc123'; @@ -66,10 +68,7 @@ class QrCodeActionTest extends TestCase self::assertEquals(200, $resp->getStatusCode()); } - /** - * @test - * @dataProvider provideQueries - */ + #[Test, DataProvider('provideQueries')] public function imageIsReturnedWithExpectedContentTypeBasedOnProvidedFormat( string $defaultFormat, array $query, @@ -87,7 +86,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']; @@ -99,10 +98,7 @@ class QrCodeActionTest extends TestCase yield 'unsupported format, svg default' => ['svg', ['format' => 'jpg'], 'image/svg+xml']; } - /** - * @test - * @dataProvider provideRequestsWithSize - */ + #[Test, DataProvider('provideRequestsWithSize')] public function imageIsReturnedWithExpectedSize( QrCodeOptions $defaultOptions, ServerRequestInterface $req, @@ -122,7 +118,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), @@ -188,10 +184,7 @@ class QrCodeActionTest extends TestCase ]; } - /** - * @test - * @dataProvider provideRoundBlockSize - */ + #[Test, DataProvider('provideRoundBlockSize')] public function imageCanRemoveExtraMarginWhenBlockRoundIsDisabled( QrCodeOptions $defaultOptions, ?string $roundBlockSize, @@ -215,7 +208,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' => [ diff --git a/module/Core/test/Action/RedirectActionTest.php b/module/Core/test/Action/RedirectActionTest.php index 7e4d1cb0..2364371c 100644 --- a/module/Core/test/Action/RedirectActionTest.php +++ b/module/Core/test/Action/RedirectActionTest.php @@ -6,6 +6,7 @@ namespace ShlinkioTest\Shlink\Core\Action; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequest; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Server\RequestHandlerInterface; @@ -44,7 +45,7 @@ class RedirectActionTest extends TestCase ); } - /** @test */ + #[Test] public function redirectionIsPerformedToLongUrl(): void { $shortCode = 'abc123'; @@ -64,7 +65,7 @@ class RedirectActionTest extends TestCase self::assertSame($expectedResp, $response); } - /** @test */ + #[Test] public function nextMiddlewareIsInvokedIfLongUrlIsNotFound(): void { $shortCode = 'abc123'; diff --git a/module/Core/test/Action/RobotsActionTest.php b/module/Core/test/Action/RobotsActionTest.php index db1f7f90..6523c2c5 100644 --- a/module/Core/test/Action/RobotsActionTest.php +++ b/module/Core/test/Action/RobotsActionTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Action; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Action\RobotsAction; @@ -21,10 +23,7 @@ class RobotsActionTest extends TestCase $this->action = new RobotsAction($this->helper); } - /** - * @test - * @dataProvider provideShortCodes - */ + #[Test, DataProvider('provideShortCodes')] public function buildsRobotsLinesFromCrawlableShortCodes(array $shortCodes, string $expected): void { $this->helper @@ -39,7 +38,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'], <<redirectsConfig = new EmptyNotFoundRedirectConfig(); } - /** @test */ + #[Test] public function allMethodsReturnHardcodedValues(): void { self::assertNull($this->redirectsConfig->invalidShortUrlRedirect()); diff --git a/module/Core/test/Config/EnvVarsTest.php b/module/Core/test/Config/EnvVarsTest.php index 6d4b1394..0b012051 100644 --- a/module/Core/test/Config/EnvVarsTest.php +++ b/module/Core/test/Config/EnvVarsTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Config; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Config\EnvVars; @@ -23,16 +25,13 @@ class EnvVarsTest extends TestCase putenv(EnvVars::DB_NAME->value . '='); } - /** - * @test - * @dataProvider provideExistingEnvVars - */ + #[Test, DataProvider('provideExistingEnvVars')] public function existsInEnvReturnsExpectedValue(EnvVars $envVar, bool $exists): void { 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]; @@ -40,16 +39,13 @@ class EnvVarsTest extends TestCase yield 'DEFAULT_REGULAR_404_REDIRECT' => [EnvVars::DEFAULT_REGULAR_404_REDIRECT, false]; } - /** - * @test - * @dataProvider provideEnvVarsValues - */ + #[Test, DataProvider('provideEnvVarsValues')] public function expectedValueIsLoadedFromEnv(EnvVars $envVar, mixed $expected, mixed $default): void { 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']; diff --git a/module/Core/test/Config/NotFoundRedirectResolverTest.php b/module/Core/test/Config/NotFoundRedirectResolverTest.php index 53531b15..0b943099 100644 --- a/module/Core/test/Config/NotFoundRedirectResolverTest.php +++ b/module/Core/test/Config/NotFoundRedirectResolverTest.php @@ -9,11 +9,12 @@ use Laminas\Diactoros\ServerRequestFactory; use Laminas\Diactoros\Uri; use Mezzio\Router\Route; use Mezzio\Router\RouteResult; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; 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 +22,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; @@ -32,10 +35,7 @@ class NotFoundRedirectResolverTest extends TestCase $this->resolver = new NotFoundRedirectResolver($this->helper, new NullLogger()); } - /** - * @test - * @dataProvider provideRedirects - */ + #[Test, DataProvider('provideRedirects')] public function expectedRedirectionIsReturnedDependingOnTheCase( UriInterface $uri, NotFoundType $notFoundType, @@ -52,47 +52,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,22 +100,22 @@ 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', ]; } - /** @test */ + #[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 +123,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 +136,8 @@ class NotFoundRedirectResolverTest extends TestCase RouteResult::fromRoute( new Route( 'foo', - $this->createMock(MiddlewareInterface::class), + middleware(function (): void { + }), ['GET'], $routeName, ), diff --git a/module/Core/test/Config/PostProcessor/BasePathPrefixerTest.php b/module/Core/test/Config/PostProcessor/BasePathPrefixerTest.php index 90c1449a..358ebaec 100644 --- a/module/Core/test/Config/PostProcessor/BasePathPrefixerTest.php +++ b/module/Core/test/Config/PostProcessor/BasePathPrefixerTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Config\PostProcessor; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Config\PostProcessor\BasePathPrefixer; @@ -16,10 +18,7 @@ class BasePathPrefixerTest extends TestCase $this->prefixer = new BasePathPrefixer(); } - /** - * @test - * @dataProvider provideConfig - */ + #[Test, DataProvider('provideConfig')] public function parsesConfigAsExpected( array $originalConfig, array $expectedRoutes, @@ -31,7 +30,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' => [ diff --git a/module/Core/test/Config/PostProcessor/MultiSegmentSlugProcessorTest.php b/module/Core/test/Config/PostProcessor/MultiSegmentSlugProcessorTest.php index cef07a86..d811a2e2 100644 --- a/module/Core/test/Config/PostProcessor/MultiSegmentSlugProcessorTest.php +++ b/module/Core/test/Config/PostProcessor/MultiSegmentSlugProcessorTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Config\PostProcessor; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Config\PostProcessor\MultiSegmentSlugProcessor; @@ -16,16 +18,13 @@ class MultiSegmentSlugProcessorTest extends TestCase $this->processor = new MultiSegmentSlugProcessor(); } - /** - * @test - * @dataProvider provideConfigs - */ + #[Test, DataProvider('provideConfigs')] public function parsesRoutesAsExpected(array $config, array $expectedRoutes): void { self::assertEquals($expectedRoutes, ($this->processor)($config)['routes'] ?? []); } - public function provideConfigs(): iterable + public static function provideConfigs(): iterable { yield [[], []]; yield [['url_shortener' => []], []]; diff --git a/module/Core/test/Config/PostProcessor/ShortUrlMethodsProcessorTest.php b/module/Core/test/Config/PostProcessor/ShortUrlMethodsProcessorTest.php index b73253f7..80d5203a 100644 --- a/module/Core/test/Config/PostProcessor/ShortUrlMethodsProcessorTest.php +++ b/module/Core/test/Config/PostProcessor/ShortUrlMethodsProcessorTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Config\PostProcessor; use Mezzio\Router\Route; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Action\RedirectAction; use Shlinkio\Shlink\Core\Config\PostProcessor\ShortUrlMethodsProcessor; @@ -18,10 +20,7 @@ class ShortUrlMethodsProcessorTest extends TestCase $this->processor = new ShortUrlMethodsProcessor(); } - /** - * @test - * @dataProvider provideConfigs - */ + #[Test, DataProvider('provideConfigs')] public function onlyFirstRouteIdentifiedAsRedirectIsEditedWithProperAllowedMethods( array $config, ?array $expectedRoutes, @@ -29,7 +28,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' => [ diff --git a/module/Core/test/ConfigProviderTest.php b/module/Core/test/ConfigProviderTest.php index 3bb0dbb4..27378d45 100644 --- a/module/Core/test/ConfigProviderTest.php +++ b/module/Core/test/ConfigProviderTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core; use Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\ConfigProvider; @@ -17,7 +18,7 @@ class ConfigProviderTest extends TestCase $this->configProvider = new ConfigProvider(); } - /** @test */ + #[Test] public function properConfigIsReturned(): void { $config = ($this->configProvider)(); diff --git a/module/Core/test/Crawling/CrawlingHelperTest.php b/module/Core/test/Crawling/CrawlingHelperTest.php index 295b7ec3..7d7876f4 100644 --- a/module/Core/test/Crawling/CrawlingHelperTest.php +++ b/module/Core/test/Crawling/CrawlingHelperTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Crawling; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Crawling\CrawlingHelper; @@ -20,7 +21,7 @@ class CrawlingHelperTest extends TestCase $this->helper = new CrawlingHelper($this->query); } - /** @test */ + #[Test] public function listCrawlableShortCodesDelegatesIntoRepository(): void { $this->query->expects($this->once())->method('__invoke')->willReturn([]); diff --git a/module/Core/test/Domain/DomainServiceTest.php b/module/Core/test/Domain/DomainServiceTest.php index 46d3e567..eb14c982 100644 --- a/module/Core/test/Domain/DomainServiceTest.php +++ b/module/Core/test/Domain/DomainServiceTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Domain; use Doctrine\ORM\EntityManagerInterface; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Config\EmptyNotFoundRedirectConfig; @@ -29,10 +31,7 @@ class DomainServiceTest extends TestCase $this->domainService = new DomainService($this->em, 'default.com'); } - /** - * @test - * @dataProvider provideExcludedDomains - */ + #[Test, DataProvider('provideExcludedDomains')] public function listDomainsDelegatesIntoRepository(array $domains, array $expectedResult, ?ApiKey $apiKey): void { $repo = $this->createMock(DomainRepositoryInterface::class); @@ -44,7 +43,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(); @@ -102,7 +101,7 @@ class DomainServiceTest extends TestCase ]; } - /** @test */ + #[Test] public function getDomainThrowsExceptionWhenDomainIsNotFound(): void { $this->em->expects($this->once())->method('find')->with(Domain::class, '123')->willReturn(null); @@ -112,7 +111,7 @@ class DomainServiceTest extends TestCase $this->domainService->getDomain('123'); } - /** @test */ + #[Test] public function getDomainReturnsEntityWhenFound(): void { $domain = Domain::withAuthority(''); @@ -123,10 +122,7 @@ class DomainServiceTest extends TestCase self::assertSame($domain, $result); } - /** - * @test - * @dataProvider provideFoundDomains - */ + #[Test, DataProvider('provideFoundDomains')] public function getOrCreateAlwaysPersistsDomain(?Domain $foundDomain, ?ApiKey $apiKey): void { $authority = 'example.com'; @@ -145,7 +141,7 @@ class DomainServiceTest extends TestCase } } - /** @test */ + #[Test] public function getOrCreateThrowsExceptionForApiKeysWithDomainRole(): void { $authority = 'example.com'; @@ -163,10 +159,7 @@ class DomainServiceTest extends TestCase $this->domainService->getOrCreate($authority, $apiKey); } - /** - * @test - * @dataProvider provideFoundDomains - */ + #[Test, DataProvider('provideFoundDomains')] public function configureNotFoundRedirectsConfiguresFetchedDomain(?Domain $foundDomain, ?ApiKey $apiKey): void { $authority = 'example.com'; @@ -190,7 +183,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(); diff --git a/module/Core/test/ErrorHandler/NotFoundRedirectHandlerTest.php b/module/Core/test/ErrorHandler/NotFoundRedirectHandlerTest.php index c6debfb5..d8a0390d 100644 --- a/module/Core/test/ErrorHandler/NotFoundRedirectHandlerTest.php +++ b/module/Core/test/ErrorHandler/NotFoundRedirectHandlerTest.php @@ -6,6 +6,9 @@ namespace ShlinkioTest\Shlink\Core\ErrorHandler; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\Assert; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; @@ -42,10 +45,7 @@ class NotFoundRedirectHandlerTest extends TestCase ); } - /** - * @test - * @dataProvider provideNonRedirectScenarios - */ + #[Test, DataProvider('provideNonRedirectScenarios')] public function nextIsCalledWhenNoRedirectIsResolved(callable $setUp): void { $expectedResp = new Response(); @@ -58,44 +58,43 @@ 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; + }, + ); }]; } - /** @test */ + #[Test] public function globalRedirectIsUsedIfDomainRedirectIsNotFound(): void { $expectedResp = new Response(); @@ -113,7 +112,7 @@ class NotFoundRedirectHandlerTest extends TestCase self::assertSame($expectedResp, $result); } - /** @test */ + #[Test] public function domainRedirectIsUsedIfFound(): void { $expectedResp = new Response(); diff --git a/module/Core/test/ErrorHandler/NotFoundTemplateHandlerTest.php b/module/Core/test/ErrorHandler/NotFoundTemplateHandlerTest.php index 800dc4e0..d9538ddf 100644 --- a/module/Core/test/ErrorHandler/NotFoundTemplateHandlerTest.php +++ b/module/Core/test/ErrorHandler/NotFoundTemplateHandlerTest.php @@ -9,13 +9,16 @@ use Laminas\Diactoros\ServerRequestFactory; use Laminas\Diactoros\Uri; use Mezzio\Router\Route; use Mezzio\Router\RouteResult; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; 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; @@ -31,10 +34,7 @@ class NotFoundTemplateHandlerTest extends TestCase $this->handler = new NotFoundTemplateHandler($readFile); } - /** - * @test - * @dataProvider provideTemplates - */ + #[Test, DataProvider('provideTemplates')] public function properErrorTemplateIsRendered(ServerRequestInterface $request, string $expectedTemplate): void { $resp = $this->handler->handle($request->withHeader('Accept', 'text/html')); @@ -44,19 +44,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 +67,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); diff --git a/module/Core/test/ErrorHandler/NotFoundTrackerMiddlewareTest.php b/module/Core/test/ErrorHandler/NotFoundTrackerMiddlewareTest.php index d8687223..4558197b 100644 --- a/module/Core/test/ErrorHandler/NotFoundTrackerMiddlewareTest.php +++ b/module/Core/test/ErrorHandler/NotFoundTrackerMiddlewareTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\ErrorHandler; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; @@ -32,7 +33,7 @@ class NotFoundTrackerMiddlewareTest extends TestCase ); } - /** @test */ + #[Test] public function delegatesIntoRequestTracker(): void { $this->handler->expects($this->once())->method('handle')->with($this->request); diff --git a/module/Core/test/ErrorHandler/NotFoundTypeResolverMiddlewareTest.php b/module/Core/test/ErrorHandler/NotFoundTypeResolverMiddlewareTest.php index a58e3713..3f2bd894 100644 --- a/module/Core/test/ErrorHandler/NotFoundTypeResolverMiddlewareTest.php +++ b/module/Core/test/ErrorHandler/NotFoundTypeResolverMiddlewareTest.php @@ -7,6 +7,7 @@ namespace ShlinkioTest\Shlink\Core\ErrorHandler; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequestFactory; use PHPUnit\Framework\Assert; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; @@ -25,7 +26,7 @@ class NotFoundTypeResolverMiddlewareTest extends TestCase $this->handler = $this->createMock(RequestHandlerInterface::class); } - /** @test */ + #[Test] public function notFoundTypeIsAddedToRequest(): void { $request = ServerRequestFactory::fromGlobals(); diff --git a/module/Core/test/EventDispatcher/CloseDbConnectionEventListenerDelegatorTest.php b/module/Core/test/EventDispatcher/CloseDbConnectionEventListenerDelegatorTest.php index 7cad7732..8273c2ea 100644 --- a/module/Core/test/EventDispatcher/CloseDbConnectionEventListenerDelegatorTest.php +++ b/module/Core/test/EventDispatcher/CloseDbConnectionEventListenerDelegatorTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\EventDispatcher; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; @@ -21,7 +22,7 @@ class CloseDbConnectionEventListenerDelegatorTest extends TestCase $this->delegator = new CloseDbConnectionEventListenerDelegator(); } - /** @test */ + #[Test] public function properDependenciesArePassed(): void { $callbackInvoked = false; diff --git a/module/Core/test/EventDispatcher/CloseDbConnectionEventListenerTest.php b/module/Core/test/EventDispatcher/CloseDbConnectionEventListenerTest.php index 430f08a9..1edd834d 100644 --- a/module/Core/test/EventDispatcher/CloseDbConnectionEventListenerTest.php +++ b/module/Core/test/EventDispatcher/CloseDbConnectionEventListenerTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\EventDispatcher; use Doctrine\DBAL\Connection; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use RuntimeException; @@ -22,10 +24,7 @@ class CloseDbConnectionEventListenerTest extends TestCase $this->em = $this->createMock(ReopeningEntityManagerInterface::class); } - /** - * @test - * @dataProvider provideWrapped - */ + #[Test, DataProvider('provideWrapped')] public function connectionIsOpenedBeforeAndClosedAfter(callable $wrapped, bool &$wrappedWasCalled): void { $conn = $this->createMock(Connection::class); @@ -46,7 +45,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; diff --git a/module/Core/test/EventDispatcher/LocateUnlocatedVisitsTest.php b/module/Core/test/EventDispatcher/LocateUnlocatedVisitsTest.php index 7315e286..0dda17b0 100644 --- a/module/Core/test/EventDispatcher/LocateUnlocatedVisitsTest.php +++ b/module/Core/test/EventDispatcher/LocateUnlocatedVisitsTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\EventDispatcher; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\EventDispatcher\Event\GeoLiteDbCreated; @@ -28,14 +29,14 @@ class LocateUnlocatedVisitsTest extends TestCase $this->listener = new LocateUnlocatedVisits($this->locator, $this->visitToLocation); } - /** @test */ + #[Test] public function locatorIsCalledWhenInvoked(): void { $this->locator->expects($this->once())->method('locateUnlocatedVisits')->with($this->listener); ($this->listener)(new GeoLiteDbCreated()); } - /** @test */ + #[Test] public function visitToLocationHelperIsCalledToGeolocateVisits(): void { $visit = Visit::forBasePath(Visitor::emptyInstance()); diff --git a/module/Core/test/EventDispatcher/LocateVisitTest.php b/module/Core/test/EventDispatcher/LocateVisitTest.php index d538bff0..b6f21495 100644 --- a/module/Core/test/EventDispatcher/LocateVisitTest.php +++ b/module/Core/test/EventDispatcher/LocateVisitTest.php @@ -6,6 +6,8 @@ namespace ShlinkioTest\Shlink\Core\EventDispatcher; use Doctrine\ORM\EntityManagerInterface; use OutOfRangeException; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\EventDispatcher\EventDispatcherInterface; @@ -49,7 +51,7 @@ class LocateVisitTest extends TestCase ); } - /** @test */ + #[Test] public function invalidVisitLogsWarning(): void { $event = new UrlVisited('123'); @@ -65,7 +67,7 @@ class LocateVisitTest extends TestCase ($this->locateVisit)($event); } - /** @test */ + #[Test] public function nonExistingGeoLiteDbLogsWarning(): void { $event = new UrlVisited('123'); @@ -84,7 +86,7 @@ class LocateVisitTest extends TestCase ($this->locateVisit)($event); } - /** @test */ + #[Test] public function invalidAddressLogsWarning(): void { $event = new UrlVisited('123'); @@ -105,7 +107,7 @@ class LocateVisitTest extends TestCase ($this->locateVisit)($event); } - /** @test */ + #[Test] public function unhandledExceptionLogsError(): void { $event = new UrlVisited('123'); @@ -126,10 +128,7 @@ class LocateVisitTest extends TestCase ($this->locateVisit)($event); } - /** - * @test - * @dataProvider provideNonLocatableVisits - */ + #[Test, DataProvider('provideNonLocatableVisits')] public function nonLocatableVisitsResolveToEmptyLocations(Visit $visit): void { $event = new UrlVisited('123'); @@ -146,7 +145,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(); @@ -155,10 +154,7 @@ class LocateVisitTest extends TestCase yield 'localhost' => [Visit::forValidShortUrl($shortUrl, new Visitor('', '', IpAddress::LOCALHOST, ''))]; } - /** - * @test - * @dataProvider provideIpAddresses - */ + #[Test, DataProvider('provideIpAddresses')] public function locatableVisitsResolveToLocation(Visit $visit, ?string $originalIpAddress): void { $ipAddr = $originalIpAddress ?? $visit->getRemoteAddr(); @@ -180,7 +176,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', '')), diff --git a/module/Core/test/EventDispatcher/Mercure/NotifyNewShortUrlToMercureTest.php b/module/Core/test/EventDispatcher/Mercure/NotifyNewShortUrlToMercureTest.php index 855f6c14..ceec7235 100644 --- a/module/Core/test/EventDispatcher/Mercure/NotifyNewShortUrlToMercureTest.php +++ b/module/Core/test/EventDispatcher/Mercure/NotifyNewShortUrlToMercureTest.php @@ -6,6 +6,7 @@ namespace ShlinkioTest\Shlink\Core\EventDispatcher\Mercure; use Doctrine\ORM\EntityManagerInterface; use Exception; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -39,7 +40,7 @@ class NotifyNewShortUrlToMercureTest extends TestCase ); } - /** @test */ + #[Test] public function messageIsLoggedWhenShortUrlIsNotFound(): void { $this->em->expects($this->once())->method('find')->with(ShortUrl::class, '123')->willReturn(null); @@ -54,7 +55,7 @@ class NotifyNewShortUrlToMercureTest extends TestCase ($this->listener)(new ShortUrlCreated('123')); } - /** @test */ + #[Test] public function expectedNotificationIsPublished(): void { $shortUrl = ShortUrl::withLongUrl('longUrl'); @@ -71,7 +72,7 @@ class NotifyNewShortUrlToMercureTest extends TestCase ($this->listener)(new ShortUrlCreated('123')); } - /** @test */ + #[Test] public function messageIsPrintedIfPublishingFails(): void { $shortUrl = ShortUrl::withLongUrl('longUrl'); diff --git a/module/Core/test/EventDispatcher/Mercure/NotifyVisitToMercureTest.php b/module/Core/test/EventDispatcher/Mercure/NotifyVisitToMercureTest.php index 23450fd3..aa21411e 100644 --- a/module/Core/test/EventDispatcher/Mercure/NotifyVisitToMercureTest.php +++ b/module/Core/test/EventDispatcher/Mercure/NotifyVisitToMercureTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\EventDispatcher\Mercure; use Doctrine\ORM\EntityManagerInterface; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -37,7 +39,7 @@ class NotifyVisitToMercureTest extends TestCase $this->listener = new NotifyVisitToMercure($this->helper, $this->updatesGenerator, $this->em, $this->logger); } - /** @test */ + #[Test] public function notificationsAreNotSentWhenVisitCannotBeFound(): void { $visitId = '123'; @@ -55,7 +57,7 @@ class NotifyVisitToMercureTest extends TestCase ($this->listener)(new VisitLocated($visitId)); } - /** @test */ + #[Test] public function notificationsAreSentWhenVisitIsFound(): void { $visitId = '123'; @@ -75,7 +77,7 @@ class NotifyVisitToMercureTest extends TestCase ($this->listener)(new VisitLocated($visitId)); } - /** @test */ + #[Test] public function debugIsLoggedWhenExceptionIsThrown(): void { $visitId = '123'; @@ -99,10 +101,7 @@ class NotifyVisitToMercureTest extends TestCase ($this->listener)(new VisitLocated($visitId)); } - /** - * @test - * @dataProvider provideOrphanVisits - */ + #[Test, DataProvider('provideOrphanVisits')] public function notificationsAreSentForOrphanVisits(Visit $visit): void { $visitId = '123'; @@ -121,7 +120,7 @@ class NotifyVisitToMercureTest extends TestCase ($this->listener)(new VisitLocated($visitId)); } - public function provideOrphanVisits(): iterable + public static function provideOrphanVisits(): iterable { $visitor = Visitor::emptyInstance(); diff --git a/module/Core/test/EventDispatcher/NotifyVisitToWebHooksTest.php b/module/Core/test/EventDispatcher/NotifyVisitToWebHooksTest.php index 17b26a74..f85a9d44 100644 --- a/module/Core/test/EventDispatcher/NotifyVisitToWebHooksTest.php +++ b/module/Core/test/EventDispatcher/NotifyVisitToWebHooksTest.php @@ -12,6 +12,8 @@ use GuzzleHttp\Promise\FulfilledPromise; use GuzzleHttp\Promise\RejectedPromise; use GuzzleHttp\RequestOptions; use PHPUnit\Framework\Assert; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -41,7 +43,7 @@ class NotifyVisitToWebHooksTest extends TestCase $this->logger = $this->createMock(LoggerInterface::class); } - /** @test */ + #[Test] public function emptyWebhooksMakeNoFurtherActions(): void { $this->em->expects($this->never())->method('find'); @@ -49,7 +51,7 @@ class NotifyVisitToWebHooksTest extends TestCase $this->createListener([])(new VisitLocated('1')); } - /** @test */ + #[Test] public function invalidVisitDoesNotPerformAnyRequest(): void { $this->em->expects($this->once())->method('find')->with(Visit::class, '1')->willReturn(null); @@ -62,7 +64,7 @@ class NotifyVisitToWebHooksTest extends TestCase $this->createListener(['foo', 'bar'])(new VisitLocated('1')); } - /** @test */ + #[Test] public function orphanVisitDoesNotPerformAnyRequestWhenDisabled(): void { $this->em->expects($this->once())->method('find')->with(Visit::class, '1')->willReturn( @@ -74,10 +76,7 @@ class NotifyVisitToWebHooksTest extends TestCase $this->createListener(['foo', 'bar'], false)(new VisitLocated('1')); } - /** - * @test - * @dataProvider provideVisits - */ + #[Test, DataProvider('provideVisits')] public function expectedRequestsArePerformedToWebhooks(Visit $visit, array $expectedResponseKeys): void { $webhooks = ['foo', 'invalid', 'bar', 'baz']; @@ -120,13 +119,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 diff --git a/module/Core/test/EventDispatcher/PublishingUpdatesGeneratorTest.php b/module/Core/test/EventDispatcher/PublishingUpdatesGeneratorTest.php index 924996f9..d2d5b0e2 100644 --- a/module/Core/test/EventDispatcher/PublishingUpdatesGeneratorTest.php +++ b/module/Core/test/EventDispatcher/PublishingUpdatesGeneratorTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\EventDispatcher; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Common\UpdatePublishing\Update; use Shlinkio\Shlink\Core\EventDispatcher\PublishingUpdatesGenerator; @@ -30,10 +32,7 @@ class PublishingUpdatesGeneratorTest extends TestCase ); } - /** - * @test - * @dataProvider provideMethod - */ + #[Test, DataProvider('provideMethod')] public function visitIsProperlySerializedIntoUpdate(string $method, string $expectedTopic, ?string $title): void { $shortUrl = ShortUrl::create(ShortUrlCreation::fromRawData([ @@ -77,16 +76,13 @@ 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]; } - /** - * @test - * @dataProvider provideOrphanVisits - */ + #[Test, DataProvider('provideOrphanVisits')] public function orphanVisitIsProperlySerializedIntoUpdate(Visit $orphanVisit): void { $update = $this->generator->newOrphanVisitUpdate($orphanVisit); @@ -105,7 +101,7 @@ class PublishingUpdatesGeneratorTest extends TestCase ], $update->payload); } - public function provideOrphanVisits(): iterable + public static function provideOrphanVisits(): iterable { $visitor = Visitor::emptyInstance(); @@ -114,7 +110,7 @@ class PublishingUpdatesGeneratorTest extends TestCase yield VisitType::BASE_URL->value => [Visit::forBasePath($visitor)]; } - /** @test */ + #[Test] public function shortUrlIsProperlySerializedIntoUpdate(): void { $shortUrl = ShortUrl::create(ShortUrlCreation::fromRawData([ diff --git a/module/Core/test/EventDispatcher/RabbitMq/NotifyNewShortUrlToRabbitMqTest.php b/module/Core/test/EventDispatcher/RabbitMq/NotifyNewShortUrlToRabbitMqTest.php index 52e9630d..a3bd9fcc 100644 --- a/module/Core/test/EventDispatcher/RabbitMq/NotifyNewShortUrlToRabbitMqTest.php +++ b/module/Core/test/EventDispatcher/RabbitMq/NotifyNewShortUrlToRabbitMqTest.php @@ -7,6 +7,8 @@ namespace ShlinkioTest\Shlink\Core\EventDispatcher\RabbitMq; use Doctrine\ORM\EntityManagerInterface; use DomainException; use Exception; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -36,7 +38,7 @@ class NotifyNewShortUrlToRabbitMqTest extends TestCase $this->logger = $this->createMock(LoggerInterface::class); } - /** @test */ + #[Test] public function doesNothingWhenTheFeatureIsNotEnabled(): void { $this->helper->expects($this->never())->method('publishUpdate'); @@ -47,7 +49,7 @@ class NotifyNewShortUrlToRabbitMqTest extends TestCase ($this->listener(false))(new ShortUrlCreated('123')); } - /** @test */ + #[Test] public function notificationsAreNotSentWhenShortUrlCannotBeFound(): void { $shortUrlId = '123'; @@ -62,7 +64,7 @@ class NotifyNewShortUrlToRabbitMqTest extends TestCase ($this->listener())(new ShortUrlCreated($shortUrlId)); } - /** @test */ + #[Test] public function expectedChannelIsNotified(): void { $shortUrlId = '123'; @@ -79,10 +81,7 @@ class NotifyNewShortUrlToRabbitMqTest extends TestCase ($this->listener())(new ShortUrlCreated($shortUrlId)); } - /** - * @test - * @dataProvider provideExceptions - */ + #[Test, DataProvider('provideExceptions')] public function printsDebugMessageInCaseOfError(Throwable $e): void { $shortUrlId = '123'; @@ -102,7 +101,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')]; diff --git a/module/Core/test/EventDispatcher/RabbitMq/NotifyVisitToRabbitMqTest.php b/module/Core/test/EventDispatcher/RabbitMq/NotifyVisitToRabbitMqTest.php index 6211ad2b..e8a0f0d5 100644 --- a/module/Core/test/EventDispatcher/RabbitMq/NotifyVisitToRabbitMqTest.php +++ b/module/Core/test/EventDispatcher/RabbitMq/NotifyVisitToRabbitMqTest.php @@ -8,6 +8,8 @@ use Doctrine\ORM\EntityManagerInterface; use DomainException; use Exception; use PHPUnit\Framework\Assert; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -44,7 +46,7 @@ class NotifyVisitToRabbitMqTest extends TestCase $this->logger = $this->createMock(LoggerInterface::class); } - /** @test */ + #[Test] public function doesNothingWhenTheFeatureIsNotEnabled(): void { $this->helper->expects($this->never())->method('publishUpdate'); @@ -55,7 +57,7 @@ class NotifyVisitToRabbitMqTest extends TestCase ($this->listener(new RabbitMqOptions(enabled: false)))(new VisitLocated('123')); } - /** @test */ + #[Test] public function notificationsAreNotSentWhenVisitCannotBeFound(): void { $visitId = '123'; @@ -70,10 +72,7 @@ class NotifyVisitToRabbitMqTest extends TestCase ($this->listener())(new VisitLocated($visitId)); } - /** - * @test - * @dataProvider provideVisits - */ + #[Test, DataProvider('provideVisits')] public function expectedChannelsAreNotifiedBasedOnTheVisitType(Visit $visit, array $expectedChannels): void { $visitId = '123'; @@ -91,7 +90,7 @@ class NotifyVisitToRabbitMqTest extends TestCase ($this->listener())(new VisitLocated($visitId)); } - public function provideVisits(): iterable + public static function provideVisits(): iterable { $visitor = Visitor::emptyInstance(); @@ -108,10 +107,7 @@ class NotifyVisitToRabbitMqTest extends TestCase ]; } - /** - * @test - * @dataProvider provideExceptions - */ + #[Test, DataProvider('provideExceptions')] public function printsDebugMessageInCaseOfError(Throwable $e): void { $visitId = '123'; @@ -130,17 +126,14 @@ 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')]; yield [new DomainException('DomainException Error')]; } - /** - * @test - * @dataProvider provideLegacyPayloads - */ + #[Test, DataProvider('provideLegacyPayloads')] public function expectedPayloadIsPublishedDependingOnConfig( bool $legacy, Visit $visit, @@ -155,14 +148,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 +172,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 +186,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 +201,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)); }, ]; } diff --git a/module/Core/test/EventDispatcher/RedisPubSub/NotifyNewShortUrlToRedisTest.php b/module/Core/test/EventDispatcher/RedisPubSub/NotifyNewShortUrlToRedisTest.php index a913de15..894abceb 100644 --- a/module/Core/test/EventDispatcher/RedisPubSub/NotifyNewShortUrlToRedisTest.php +++ b/module/Core/test/EventDispatcher/RedisPubSub/NotifyNewShortUrlToRedisTest.php @@ -7,6 +7,8 @@ namespace ShlinkioTest\Shlink\Core\EventDispatcher\RedisPubSub; use Doctrine\ORM\EntityManagerInterface; use DomainException; use Exception; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -35,7 +37,7 @@ class NotifyNewShortUrlToRedisTest extends TestCase $this->logger = $this->createMock(LoggerInterface::class); } - /** @test */ + #[Test] public function doesNothingWhenTheFeatureIsNotEnabled(): void { $this->helper->expects($this->never())->method('publishUpdate'); @@ -46,10 +48,7 @@ class NotifyNewShortUrlToRedisTest extends TestCase $this->createListener(false)(new ShortUrlCreated('123')); } - /** - * @test - * @dataProvider provideExceptions - */ + #[Test, DataProvider('provideExceptions')] public function printsDebugMessageInCaseOfError(Throwable $e): void { $shortUrlId = '123'; @@ -69,7 +68,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')]; diff --git a/module/Core/test/EventDispatcher/RedisPubSub/NotifyVisitToRedisTest.php b/module/Core/test/EventDispatcher/RedisPubSub/NotifyVisitToRedisTest.php index f50cf906..cbccffd7 100644 --- a/module/Core/test/EventDispatcher/RedisPubSub/NotifyVisitToRedisTest.php +++ b/module/Core/test/EventDispatcher/RedisPubSub/NotifyVisitToRedisTest.php @@ -7,6 +7,8 @@ namespace ShlinkioTest\Shlink\Core\EventDispatcher\RedisPubSub; use Doctrine\ORM\EntityManagerInterface; use DomainException; use Exception; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -35,7 +37,7 @@ class NotifyVisitToRedisTest extends TestCase $this->logger = $this->createMock(LoggerInterface::class); } - /** @test */ + #[Test] public function doesNothingWhenTheFeatureIsNotEnabled(): void { $this->helper->expects($this->never())->method('publishUpdate'); @@ -46,10 +48,7 @@ class NotifyVisitToRedisTest extends TestCase $this->createListener(false)(new VisitLocated('123')); } - /** - * @test - * @dataProvider provideExceptions - */ + #[Test, DataProvider('provideExceptions')] public function printsDebugMessageInCaseOfError(Throwable $e): void { $visitId = '123'; @@ -68,7 +67,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')]; diff --git a/module/Core/test/EventDispatcher/UpdateGeoLiteDbTest.php b/module/Core/test/EventDispatcher/UpdateGeoLiteDbTest.php index 5b496123..6ba20ec8 100644 --- a/module/Core/test/EventDispatcher/UpdateGeoLiteDbTest.php +++ b/module/Core/test/EventDispatcher/UpdateGeoLiteDbTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\EventDispatcher; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\EventDispatcher\EventDispatcherInterface; @@ -32,7 +34,7 @@ class UpdateGeoLiteDbTest extends TestCase $this->listener = new UpdateGeoLiteDb($this->dbUpdater, $this->logger, $this->eventDispatcher); } - /** @test */ + #[Test] public function exceptionWhileUpdatingDbLogsError(): void { $e = new RuntimeException(); @@ -48,10 +50,7 @@ class UpdateGeoLiteDbTest extends TestCase ($this->listener)(); } - /** - * @test - * @dataProvider provideFlags - */ + #[Test, DataProvider('provideFlags')] public function noticeMessageIsPrintedWhenFirstCallbackIsInvoked(bool $oldDbExists, string $expectedMessage): void { $this->dbUpdater->expects($this->once())->method('checkDbUpdate')->withAnyParameters()->willReturnCallback( @@ -67,16 +66,13 @@ 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...']; } - /** - * @test - * @dataProvider provideDownloaded - */ + #[Test, DataProvider('provideDownloaded')] public function noticeMessageIsPrintedWhenSecondCallbackIsInvoked( int $total, int $downloaded, @@ -101,7 +97,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]; @@ -113,10 +109,7 @@ class UpdateGeoLiteDbTest extends TestCase yield [100, 101, false, 'Finished downloading GeoLite2 db file']; } - /** - * @test - * @dataProvider provideGeolocationResults - */ + #[Test, DataProvider('provideGeolocationResults')] public function dispatchesEventOnlyWhenDbFileHasBeenCreatedForTheFirstTime( GeolocationResult $result, int $expectedDispatches, @@ -129,7 +122,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, diff --git a/module/Core/test/Exception/DeleteShortUrlExceptionTest.php b/module/Core/test/Exception/DeleteShortUrlExceptionTest.php index bfdce269..8d82c11e 100644 --- a/module/Core/test/Exception/DeleteShortUrlExceptionTest.php +++ b/module/Core/test/Exception/DeleteShortUrlExceptionTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Exception; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\DeleteShortUrlException; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlIdentifier; @@ -15,10 +17,7 @@ use function sprintf; class DeleteShortUrlExceptionTest extends TestCase { - /** - * @test - * @dataProvider provideThresholds - */ + #[Test, DataProvider('provideThresholds')] public function fromVisitsThresholdGeneratesMessageProperly( int $threshold, string $shortCode, @@ -41,7 +40,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( @@ -52,7 +51,7 @@ class DeleteShortUrlExceptionTest extends TestCase }); } - /** @test */ + #[Test] public function domainIsPartOfAdditionalWhenProvidedInIdentifier(): void { $e = DeleteShortUrlException::fromVisitsThreshold( diff --git a/module/Core/test/Exception/DomainNotFoundExceptionTest.php b/module/Core/test/Exception/DomainNotFoundExceptionTest.php index f2f5daba..b52ea8ce 100644 --- a/module/Core/test/Exception/DomainNotFoundExceptionTest.php +++ b/module/Core/test/Exception/DomainNotFoundExceptionTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Exception; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\DomainNotFoundException; @@ -11,7 +12,7 @@ use function sprintf; class DomainNotFoundExceptionTest extends TestCase { - /** @test */ + #[Test] public function properlyCreatesExceptionFromId(): void { $id = '123'; @@ -26,7 +27,7 @@ class DomainNotFoundExceptionTest extends TestCase self::assertEquals(404, $e->getStatus()); } - /** @test */ + #[Test] public function properlyCreatesExceptionFromAuthority(): void { $authority = 'example.com'; diff --git a/module/Core/test/Exception/ForbiddenTagOperationExceptionTest.php b/module/Core/test/Exception/ForbiddenTagOperationExceptionTest.php index b064cf91..45cba045 100644 --- a/module/Core/test/Exception/ForbiddenTagOperationExceptionTest.php +++ b/module/Core/test/Exception/ForbiddenTagOperationExceptionTest.php @@ -4,15 +4,14 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Exception; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\ForbiddenTagOperationException; class ForbiddenTagOperationExceptionTest extends TestCase { - /** - * @test - * @dataProvider provideExceptions - */ + #[Test, DataProvider('provideExceptions')] public function createsExpectedExceptionForDeletion( ForbiddenTagOperationException $e, string $expectedMessage, @@ -29,7 +28,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']; diff --git a/module/Core/test/Exception/InvalidUrlExceptionTest.php b/module/Core/test/Exception/InvalidUrlExceptionTest.php index e9b0d75a..5e31d27a 100644 --- a/module/Core/test/Exception/InvalidUrlExceptionTest.php +++ b/module/Core/test/Exception/InvalidUrlExceptionTest.php @@ -6,6 +6,8 @@ namespace ShlinkioTest\Shlink\Core\Exception; use Exception; use Fig\Http\Message\StatusCodeInterface; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\InvalidUrlException; use Throwable; @@ -14,10 +16,7 @@ use function sprintf; class InvalidUrlExceptionTest extends TestCase { - /** - * @test - * @dataProvider providePrevious - */ + #[Test, DataProvider('providePrevious')] public function properlyCreatesExceptionFromUrl(?Throwable $prev): void { $url = 'http://the_url.com'; @@ -34,7 +33,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)]; diff --git a/module/Core/test/Exception/IpCannotBeLocatedExceptionTest.php b/module/Core/test/Exception/IpCannotBeLocatedExceptionTest.php index 2089daba..21507333 100644 --- a/module/Core/test/Exception/IpCannotBeLocatedExceptionTest.php +++ b/module/Core/test/Exception/IpCannotBeLocatedExceptionTest.php @@ -6,6 +6,8 @@ namespace ShlinkioTest\Shlink\Core\Exception; use Exception; use LogicException; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\IpCannotBeLocatedException; use Shlinkio\Shlink\Core\Exception\RuntimeException; @@ -14,7 +16,7 @@ use Throwable; class IpCannotBeLocatedExceptionTest extends TestCase { - /** @test */ + #[Test] public function forEmptyAddressInitializesException(): void { $e = IpCannotBeLocatedException::forEmptyAddress(); @@ -26,7 +28,7 @@ class IpCannotBeLocatedExceptionTest extends TestCase self::assertEquals(UnlocatableIpType::EMPTY_ADDRESS, $e->type); } - /** @test */ + #[Test] public function forLocalhostInitializesException(): void { $e = IpCannotBeLocatedException::forLocalhost(); @@ -38,10 +40,7 @@ class IpCannotBeLocatedExceptionTest extends TestCase self::assertEquals(UnlocatableIpType::LOCALHOST, $e->type); } - /** - * @test - * @dataProvider provideErrors - */ + #[Test, DataProvider('provideErrors')] public function forErrorInitializesException(Throwable $prev): void { $e = IpCannotBeLocatedException::forError($prev); @@ -53,7 +52,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)]; diff --git a/module/Core/test/Exception/MalformedBodyExceptionTest.php b/module/Core/test/Exception/MalformedBodyExceptionTest.php index ecccfdf2..b601d6fe 100644 --- a/module/Core/test/Exception/MalformedBodyExceptionTest.php +++ b/module/Core/test/Exception/MalformedBodyExceptionTest.php @@ -6,12 +6,13 @@ namespace ShlinkioTest\Shlink\Core\Exception; use Fig\Http\Message\StatusCodeInterface; use JsonException; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\MalformedBodyException; class MalformedBodyExceptionTest extends TestCase { - /** @test */ + #[Test] public function createsExpectedException(): void { $prev = new JsonException(); diff --git a/module/Core/test/Exception/NonUniqueSlugExceptionTest.php b/module/Core/test/Exception/NonUniqueSlugExceptionTest.php index 77a71df3..c1e0d158 100644 --- a/module/Core/test/Exception/NonUniqueSlugExceptionTest.php +++ b/module/Core/test/Exception/NonUniqueSlugExceptionTest.php @@ -4,15 +4,14 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Exception; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException; class NonUniqueSlugExceptionTest extends TestCase { - /** - * @test - * @dataProvider provideMessages - */ + #[Test, DataProvider('provideMessages')] public function properlyCreatesExceptionFromSlug(string $expectedMessage, string $slug, ?string $domain): void { $expectedAdditional = ['customSlug' => $slug]; @@ -30,7 +29,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.', diff --git a/module/Core/test/Exception/ShortUrlNotFoundExceptionTest.php b/module/Core/test/Exception/ShortUrlNotFoundExceptionTest.php index 9557044b..aee8a29f 100644 --- a/module/Core/test/Exception/ShortUrlNotFoundExceptionTest.php +++ b/module/Core/test/Exception/ShortUrlNotFoundExceptionTest.php @@ -4,16 +4,15 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Exception; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlIdentifier; class ShortUrlNotFoundExceptionTest extends TestCase { - /** - * @test - * @dataProvider provideMessages - */ + #[Test, DataProvider('provideMessages')] public function properlyCreatesExceptionFromNotFoundShortCode( string $expectedMessage, string $shortCode, @@ -34,7 +33,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"', diff --git a/module/Core/test/Exception/TagConflictExceptionTest.php b/module/Core/test/Exception/TagConflictExceptionTest.php index ba7dfa1d..2f4bd66a 100644 --- a/module/Core/test/Exception/TagConflictExceptionTest.php +++ b/module/Core/test/Exception/TagConflictExceptionTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Exception; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\TagConflictException; use Shlinkio\Shlink\Core\Tag\Model\TagRenaming; @@ -12,7 +13,7 @@ use function sprintf; class TagConflictExceptionTest extends TestCase { - /** @test */ + #[Test] public function properlyCreatesExceptionForExistingTag(): void { $oldName = 'foo'; diff --git a/module/Core/test/Exception/TagNotFoundExceptionTest.php b/module/Core/test/Exception/TagNotFoundExceptionTest.php index f22463c2..8d31f036 100644 --- a/module/Core/test/Exception/TagNotFoundExceptionTest.php +++ b/module/Core/test/Exception/TagNotFoundExceptionTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Exception; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\TagNotFoundException; @@ -11,7 +12,7 @@ use function sprintf; class TagNotFoundExceptionTest extends TestCase { - /** @test */ + #[Test] public function properlyCreatesExceptionFromNotFoundTag(): void { $tag = 'foo'; diff --git a/module/Core/test/Exception/ValidationExceptionTest.php b/module/Core/test/Exception/ValidationExceptionTest.php index b34badf3..5bb3baa8 100644 --- a/module/Core/test/Exception/ValidationExceptionTest.php +++ b/module/Core/test/Exception/ValidationExceptionTest.php @@ -7,6 +7,8 @@ namespace ShlinkioTest\Shlink\Core\Exception; use Fig\Http\Message\StatusCodeInterface; use Laminas\InputFilter\InputFilterInterface; use LogicException; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use RuntimeException; use Shlinkio\Shlink\Core\Exception\ValidationException; @@ -17,10 +19,7 @@ use function print_r; class ValidationExceptionTest extends TestCase { - /** - * @test - * @dataProvider provideExceptions - */ + #[Test, DataProvider('provideExceptions')] public function createsExceptionFromInputFilter(?Throwable $prev): void { $invalidData = [ @@ -46,7 +45,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()]]; } diff --git a/module/Core/test/Functions/FunctionsTest.php b/module/Core/test/Functions/FunctionsTest.php index ad45812f..3f6026a0 100644 --- a/module/Core/test/Functions/FunctionsTest.php +++ b/module/Core/test/Functions/FunctionsTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Functions; use BackedEnum; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Config\EnvVars; use Shlinkio\Shlink\Core\Model\DeviceType; @@ -18,15 +20,14 @@ class FunctionsTest extends TestCase { /** * @param class-string $enum - * @test - * @dataProvider provideEnums */ + #[Test, DataProvider('provideEnums')] public function enumValuesReturnsExpectedValueForEnum(string $enum, array $expectedValues): void { 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 => [ diff --git a/module/Core/test/Importer/ImportedLinksProcessorTest.php b/module/Core/test/Importer/ImportedLinksProcessorTest.php index f1b2f3bb..c8132699 100644 --- a/module/Core/test/Importer/ImportedLinksProcessorTest.php +++ b/module/Core/test/Importer/ImportedLinksProcessorTest.php @@ -7,6 +7,8 @@ namespace ShlinkioTest\Shlink\Core\Importer; use Cake\Chronos\Chronos; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\EntityManagerInterface; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use RuntimeException; @@ -61,7 +63,7 @@ class ImportedLinksProcessorTest extends TestCase $this->io = $this->createMock(StyleInterface::class); } - /** @test */ + #[Test] public function newUrlsWithNoErrorsAreAllPersisted(): void { $urls = [ @@ -84,7 +86,7 @@ class ImportedLinksProcessorTest extends TestCase $this->processor->process($this->io, ImportResult::withShortUrls($urls), $this->buildParams()); } - /** @test */ + #[Test] public function newUrlsWithErrorsAreSkipped(): void { $urls = [ @@ -111,7 +113,7 @@ class ImportedLinksProcessorTest extends TestCase self::assertEquals(1, $textCalls->skippedCount); } - /** @test */ + #[Test] public function alreadyImportedUrlsAreSkipped(): void { $urls = [ @@ -137,7 +139,7 @@ class ImportedLinksProcessorTest extends TestCase self::assertEquals(3, $textCalls->skippedCount); } - /** @test */ + #[Test] public function nonUniqueShortCodesAreAskedToUser(): void { $urls = [ @@ -165,10 +167,7 @@ class ImportedLinksProcessorTest extends TestCase self::assertEquals(3, $textCalls->skippedCount); } - /** - * @test - * @dataProvider provideUrlsWithVisits - */ + #[Test, DataProvider('provideUrlsWithVisits')] public function properAmountOfVisitsIsImported( ImportedShlinkUrl $importedUrl, string $expectedOutput, @@ -188,7 +187,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) => @@ -230,9 +229,8 @@ class ImportedLinksProcessorTest extends TestCase /** * @param iterable $visits - * @test - * @dataProvider provideOrphanVisits */ + #[Test, DataProvider('provideOrphanVisits')] public function properAmountOfOrphanVisitsIsImported( bool $importOrphanVisits, iterable $visits, @@ -262,7 +260,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]; diff --git a/module/Core/test/ShortUrl/DeleteShortUrlServiceTest.php b/module/Core/test/ShortUrl/DeleteShortUrlServiceTest.php index 3173e2ee..65351a93 100644 --- a/module/Core/test/ShortUrl/DeleteShortUrlServiceTest.php +++ b/module/Core/test/ShortUrl/DeleteShortUrlServiceTest.php @@ -6,6 +6,7 @@ namespace ShlinkioTest\Shlink\Core\ShortUrl; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\EntityManagerInterface; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\DeleteShortUrlException; @@ -40,7 +41,7 @@ class DeleteShortUrlServiceTest extends TestCase $this->urlResolver->method('resolveShortUrl')->willReturn($shortUrl); } - /** @test */ + #[Test] public function deleteByShortCodeThrowsExceptionWhenThresholdIsReached(): void { $service = $this->createService(); @@ -54,7 +55,7 @@ class DeleteShortUrlServiceTest extends TestCase $service->deleteByShortCode(ShortUrlIdentifier::fromShortCodeAndDomain($this->shortCode)); } - /** @test */ + #[Test] public function deleteByShortCodeDeletesUrlWhenThresholdIsReachedButExplicitlyIgnored(): void { $service = $this->createService(); @@ -67,7 +68,7 @@ class DeleteShortUrlServiceTest extends TestCase $service->deleteByShortCode(ShortUrlIdentifier::fromShortCodeAndDomain($this->shortCode), true); } - /** @test */ + #[Test] public function deleteByShortCodeDeletesUrlWhenThresholdIsReachedButCheckIsDisabled(): void { $service = $this->createService(false); @@ -80,7 +81,7 @@ class DeleteShortUrlServiceTest extends TestCase $service->deleteByShortCode(ShortUrlIdentifier::fromShortCodeAndDomain($this->shortCode)); } - /** @test */ + #[Test] public function deleteByShortCodeDeletesUrlWhenThresholdIsNotReached(): void { $service = $this->createService(true, 100); diff --git a/module/Core/test/ShortUrl/Entity/ShortUrlTest.php b/module/Core/test/ShortUrl/Entity/ShortUrlTest.php index 8b40baca..54e21461 100644 --- a/module/Core/test/ShortUrl/Entity/ShortUrlTest.php +++ b/module/Core/test/ShortUrl/Entity/ShortUrlTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\ShortUrl\Entity; use Cake\Chronos\Chronos; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\ShortCodeCannotBeRegeneratedException; use Shlinkio\Shlink\Core\Model\DeviceType; @@ -27,10 +29,7 @@ use const Shlinkio\Shlink\DEFAULT_SHORT_CODES_LENGTH; class ShortUrlTest extends TestCase { - /** - * @test - * @dataProvider provideInvalidShortUrls - */ + #[Test, DataProvider('provideInvalidShortUrls')] public function regenerateShortCodeThrowsExceptionIfStateIsInvalid( ShortUrl $shortUrl, string $expectedMessage, @@ -41,7 +40,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'])), @@ -53,10 +52,7 @@ class ShortUrlTest extends TestCase ]; } - /** - * @test - * @dataProvider provideValidShortUrls - */ + #[Test, DataProvider('provideValidShortUrls')] public function regenerateShortCodeProperlyChangesTheValueOnValidShortUrls( ShortUrl $shortUrl, ): void { @@ -68,7 +64,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( @@ -77,10 +73,7 @@ class ShortUrlTest extends TestCase )]; } - /** - * @test - * @dataProvider provideLengths - */ + #[Test, DataProvider('provideLengths')] public function shortCodesHaveExpectedLength(?int $length, int $expectedLength): void { $shortUrl = ShortUrl::create(ShortUrlCreation::fromRawData( @@ -90,13 +83,13 @@ 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]); } - /** @test */ + #[Test] public function deviceLongUrlsAreUpdated(): void { $shortUrl = ShortUrl::withLongUrl('foo'); @@ -138,7 +131,7 @@ class ShortUrlTest extends TestCase ], $shortUrl->deviceLongUrls()); } - /** @test */ + #[Test] public function generatesLowercaseOnlyShortCodesInLooseMode(): void { $range = range(1, 1000); // Use a "big" number to reduce false negatives diff --git a/module/Core/test/ShortUrl/Helper/ShortCodeUniquenessHelperTest.php b/module/Core/test/ShortUrl/Helper/ShortCodeUniquenessHelperTest.php index ae0d9363..efbbde21 100644 --- a/module/Core/test/ShortUrl/Helper/ShortCodeUniquenessHelperTest.php +++ b/module/Core/test/ShortUrl/Helper/ShortCodeUniquenessHelperTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\ShortUrl\Helper; use Doctrine\ORM\EntityManagerInterface; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Domain\Entity\Domain; @@ -29,10 +31,7 @@ class ShortCodeUniquenessHelperTest extends TestCase $this->shortUrl->method('getShortCode')->willReturn('abc123'); } - /** - * @test - * @dataProvider provideDomains - */ + #[Test, DataProvider('provideDomains')] public function shortCodeIsRegeneratedIfAlreadyInUse(?Domain $domain, ?string $expectedAuthority): void { $callIndex = 0; @@ -55,13 +54,13 @@ 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]; } - /** @test */ + #[Test] public function inUseSlugReturnsError(): void { $repo = $this->createMock(ShortUrlRepository::class); diff --git a/module/Core/test/ShortUrl/Helper/ShortUrlRedirectionBuilderTest.php b/module/Core/test/ShortUrl/Helper/ShortUrlRedirectionBuilderTest.php index 341ff6bf..cf88db35 100644 --- a/module/Core/test/ShortUrl/Helper/ShortUrlRedirectionBuilderTest.php +++ b/module/Core/test/ShortUrl/Helper/ShortUrlRedirectionBuilderTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\ShortUrl\Helper; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; use Shlinkio\Shlink\Core\Model\DeviceType; @@ -27,10 +29,7 @@ class ShortUrlRedirectionBuilderTest extends TestCase $this->redirectionBuilder = new ShortUrlRedirectionBuilder($trackingOptions); } - /** - * @test - * @dataProvider provideData - */ + #[Test, DataProvider('provideData')] public function buildShortUrlRedirectBuildsExpectedUrl( string $expectedUrl, ServerRequestInterface $request, @@ -50,7 +49,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); diff --git a/module/Core/test/ShortUrl/Helper/ShortUrlStringifierTest.php b/module/Core/test/ShortUrl/Helper/ShortUrlStringifierTest.php index fc8c7579..1ccd6eac 100644 --- a/module/Core/test/ShortUrl/Helper/ShortUrlStringifierTest.php +++ b/module/Core/test/ShortUrl/Helper/ShortUrlStringifierTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\ShortUrl\Helper; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifier; @@ -11,10 +13,7 @@ use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation; class ShortUrlStringifierTest extends TestCase { - /** - * @test - * @dataProvider provideConfigAndShortUrls - */ + #[Test, DataProvider('provideConfigAndShortUrls')] public function generatesExpectedOutputBasedOnConfigAndShortUrl( array $config, string $basePath, @@ -26,7 +25,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([ diff --git a/module/Core/test/ShortUrl/Helper/ShortUrlTitleResolutionHelperTest.php b/module/Core/test/ShortUrl/Helper/ShortUrlTitleResolutionHelperTest.php index 2d48b294..ae89fa6f 100644 --- a/module/Core/test/ShortUrl/Helper/ShortUrlTitleResolutionHelperTest.php +++ b/module/Core/test/ShortUrl/Helper/ShortUrlTitleResolutionHelperTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\ShortUrl\Helper; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlTitleResolutionHelper; @@ -21,10 +23,7 @@ class ShortUrlTitleResolutionHelperTest extends TestCase $this->helper = new ShortUrlTitleResolutionHelper($this->urlValidator); } - /** - * @test - * @dataProvider provideTitles - */ + #[Test, DataProvider('provideTitles')] public function urlIsProperlyShortened(?string $title, int $validateWithTitleCallsNum, int $validateCallsNum): void { $longUrl = 'http://foobar.com/12345/hello?foo=bar'; @@ -42,7 +41,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]; diff --git a/module/Core/test/ShortUrl/Middleware/ExtraPathRedirectMiddlewareTest.php b/module/Core/test/ShortUrl/Middleware/ExtraPathRedirectMiddlewareTest.php index c157403e..bbe8e770 100644 --- a/module/Core/test/ShortUrl/Middleware/ExtraPathRedirectMiddlewareTest.php +++ b/module/Core/test/ShortUrl/Middleware/ExtraPathRedirectMiddlewareTest.php @@ -9,10 +9,11 @@ use Laminas\Diactoros\ServerRequestFactory; use Laminas\Diactoros\Uri; use Mezzio\Router\Route; use Mezzio\Router\RouteResult; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; 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 +27,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 @@ -46,10 +48,7 @@ class ExtraPathRedirectMiddlewareTest extends TestCase $this->handler->method('handle')->willReturn(new RedirectResponse('')); } - /** - * @test - * @dataProvider provideNonRedirectingRequests - */ + #[Test, DataProvider('provideNonRedirectingRequests')] public function handlerIsCalledWhenConfigPreventsRedirectWithExtraPath( bool $appendExtraPath, bool $multiSegmentEnabled, @@ -68,7 +67,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 +83,8 @@ class ExtraPathRedirectMiddlewareTest extends TestCase RouteResult::class, RouteResult::fromRoute(new Route( '/foo', - $this->createMock(MiddlewareInterface::class), + middleware(function (): void { + }), ['GET'], RedirectAction::class, )), @@ -100,10 +100,7 @@ class ExtraPathRedirectMiddlewareTest extends TestCase ]; } - /** - * @test - * @dataProvider provideResolves - */ + #[Test, DataProvider('provideResolves')] public function handlerIsCalledWhenNoShortUrlIsFoundAfterExpectedAmountOfIterations( bool $multiSegmentEnabled, int $expectedResolveCalls, @@ -126,10 +123,7 @@ class ExtraPathRedirectMiddlewareTest extends TestCase $this->middleware($options)->process($request, $this->handler); } - /** - * @test - * @dataProvider provideResolves - */ + #[Test, DataProvider('provideResolves')] public function visitIsTrackedAndRedirectIsReturnedWhenShortUrlIsFoundAfterExpectedAmountOfIterations( bool $multiSegmentEnabled, int $expectedResolveCalls, @@ -170,7 +164,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]; diff --git a/module/Core/test/ShortUrl/Middleware/TrimTrailingSlashMiddlewareTest.php b/module/Core/test/ShortUrl/Middleware/TrimTrailingSlashMiddlewareTest.php index eb078902..b43eed91 100644 --- a/module/Core/test/ShortUrl/Middleware/TrimTrailingSlashMiddlewareTest.php +++ b/module/Core/test/ShortUrl/Middleware/TrimTrailingSlashMiddlewareTest.php @@ -7,6 +7,8 @@ namespace ShlinkioTest\Shlink\Core\ShortUrl\Middleware; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequestFactory; use PHPUnit\Framework\Assert; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; @@ -26,10 +28,7 @@ class TrimTrailingSlashMiddlewareTest extends TestCase $this->requestHandler = $this->createMock(RequestHandlerInterface::class); } - /** - * @test - * @dataProvider provideRequests - */ + #[Test, DataProvider('provideRequests')] public function returnsExpectedResponse( bool $trailingSlashEnabled, ServerRequestInterface $inputRequest, @@ -43,7 +42,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, diff --git a/module/Core/test/ShortUrl/Model/ShortUrlCreationTest.php b/module/Core/test/ShortUrl/Model/ShortUrlCreationTest.php index 904dab01..a46474c0 100644 --- a/module/Core/test/ShortUrl/Model/ShortUrlCreationTest.php +++ b/module/Core/test/ShortUrl/Model/ShortUrlCreationTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\ShortUrl\Model; use Cake\Chronos\Chronos; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\ValidationException; use Shlinkio\Shlink\Core\Model\DeviceType; @@ -20,18 +22,14 @@ use const STR_PAD_BOTH; class ShortUrlCreationTest extends TestCase { - /** - * @param array $data - * @test - * @dataProvider provideInvalidData - */ + #[Test, DataProvider('provideInvalidData')] public function exceptionIsThrownIfProvidedDataIsInvalid(array $data): void { $this->expectException(ValidationException::class); ShortUrlCreation::fromRawData($data); } - public function provideInvalidData(): iterable + public static function provideInvalidData(): iterable { yield [[]]; yield [[ @@ -107,10 +105,7 @@ class ShortUrlCreationTest extends TestCase ]]; } - /** - * @test - * @dataProvider provideCustomSlugs - */ + #[Test, DataProvider('provideCustomSlugs')] public function properlyCreatedInstanceReturnsValues( string $customSlug, string $expectedSlug, @@ -136,7 +131,7 @@ class ShortUrlCreationTest extends TestCase self::assertNull($creation->maxVisits); } - public function provideCustomSlugs(): iterable + public static function provideCustomSlugs(): iterable { yield ['🔥', '🔥']; yield ['🦣 🍅', '🦣-🍅']; @@ -161,10 +156,7 @@ class ShortUrlCreationTest extends TestCase yield ['гугл', 'гугл']; } - /** - * @test - * @dataProvider provideTitles - */ + #[Test, DataProvider('provideTitles')] public function titleIsCroppedIfTooLong(?string $title, ?string $expectedTitle): void { $creation = ShortUrlCreation::fromRawData([ @@ -175,7 +167,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']; @@ -187,10 +179,7 @@ class ShortUrlCreationTest extends TestCase yield [str_pad('', 800, 'e'), str_pad('', 512, 'e')]; } - /** - * @test - * @dataProvider provideDomains - */ + #[Test, DataProvider('provideDomains')] public function emptyDomainIsDiscarded(?string $domain, ?string $expectedDomain): void { $creation = ShortUrlCreation::fromRawData([ @@ -201,7 +190,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]; diff --git a/module/Core/test/ShortUrl/Model/ShortUrlEditionTest.php b/module/Core/test/ShortUrl/Model/ShortUrlEditionTest.php index e03bb1ac..720c290f 100644 --- a/module/Core/test/ShortUrl/Model/ShortUrlEditionTest.php +++ b/module/Core/test/ShortUrl/Model/ShortUrlEditionTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\ShortUrl\Model; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Model\DeviceType; use Shlinkio\Shlink\Core\ShortUrl\Model\DeviceLongUrlPair; @@ -12,10 +14,7 @@ use Shlinkio\Shlink\Core\ShortUrl\Model\Validation\ShortUrlInputFilter; class ShortUrlEditionTest extends TestCase { - /** - * @test - * @dataProvider provideDeviceLongUrls - */ + #[Test, DataProvider('provideDeviceLongUrls')] public function expectedDeviceLongUrlsAreResolved( ?array $deviceLongUrls, array $expectedDeviceLongUrls, @@ -27,7 +26,7 @@ class ShortUrlEditionTest extends TestCase self::assertEquals($expectedDevicesToRemove, $edition->devicesToRemove); } - public function provideDeviceLongUrls(): iterable + public static function provideDeviceLongUrls(): iterable { yield 'null' => [null, [], []]; yield 'empty' => [[], [], []]; diff --git a/module/Core/test/ShortUrl/Model/ShortUrlModeTest.php b/module/Core/test/ShortUrl/Model/ShortUrlModeTest.php index 18aa2d54..f2ca7cce 100644 --- a/module/Core/test/ShortUrl/Model/ShortUrlModeTest.php +++ b/module/Core/test/ShortUrl/Model/ShortUrlModeTest.php @@ -4,21 +4,20 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\ShortUrl\Model; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlMode; class ShortUrlModeTest extends TestCase { - /** - * @test - * @dataProvider provideModes - */ + #[Test, DataProvider('provideModes')] public function deprecatedValuesAreProperlyParsed(string $mode, ?ShortUrlMode $expected): void { self::assertSame($expected, ShortUrlMode::tryDeprecated($mode)); } - public function provideModes(): iterable + public static function provideModes(): iterable { yield 'invalid' => ['invalid', null]; yield 'foo' => ['foo', null]; diff --git a/module/Core/test/ShortUrl/Model/Validation/DeviceLongUrlsValidatorTest.php b/module/Core/test/ShortUrl/Model/Validation/DeviceLongUrlsValidatorTest.php index 8bac2f98..860e2a39 100644 --- a/module/Core/test/ShortUrl/Model/Validation/DeviceLongUrlsValidatorTest.php +++ b/module/Core/test/ShortUrl/Model/Validation/DeviceLongUrlsValidatorTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\ShortUrl\Model\Validation; use Laminas\Validator\NotEmpty; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Model\DeviceType; use Shlinkio\Shlink\Core\ShortUrl\Model\Validation\DeviceLongUrlsValidator; @@ -19,17 +21,14 @@ class DeviceLongUrlsValidatorTest extends TestCase $this->validator = new DeviceLongUrlsValidator(new NotEmpty()); } - /** - * @test - * @dataProvider provideNonArrayValues - */ + #[Test, DataProvider('provideNonArrayValues')] public function nonArrayValuesAreNotValid(mixed $invalidValue): void { self::assertFalse($this->validator->isValid($invalidValue)); 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]; @@ -39,7 +38,7 @@ class DeviceLongUrlsValidatorTest extends TestCase yield 'null' => [null]; } - /** @test */ + #[Test] public function unrecognizedKeysAreNotValid(): void { self::assertFalse($this->validator->isValid(['foo' => 'bar'])); @@ -49,7 +48,7 @@ class DeviceLongUrlsValidatorTest extends TestCase ); } - /** @test */ + #[Test] public function everyUrlMustMatchLongUrlValidator(): void { self::assertFalse($this->validator->isValid([DeviceType::ANDROID->value => ''])); @@ -59,7 +58,7 @@ class DeviceLongUrlsValidatorTest extends TestCase ); } - /** @test */ + #[Test] public function validValuesResultInValidResult(): void { self::assertTrue($this->validator->isValid([ diff --git a/module/Core/test/ShortUrl/Paginator/Adapter/ShortUrlRepositoryAdapterTest.php b/module/Core/test/ShortUrl/Paginator/Adapter/ShortUrlRepositoryAdapterTest.php index 684c1528..2ef213d2 100644 --- a/module/Core/test/ShortUrl/Paginator/Adapter/ShortUrlRepositoryAdapterTest.php +++ b/module/Core/test/ShortUrl/Paginator/Adapter/ShortUrlRepositoryAdapterTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\ShortUrl\Paginator\Adapter; use Cake\Chronos\Chronos; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlsParams; @@ -24,10 +26,7 @@ class ShortUrlRepositoryAdapterTest extends TestCase $this->repo = $this->createMock(ShortUrlListRepositoryInterface::class); } - /** - * @test - * @dataProvider provideFilteringArgs - */ + #[Test, DataProvider('provideFilteringArgs')] public function getItemsFallsBackToFindList( ?string $searchTerm = null, array $tags = [], @@ -53,10 +52,7 @@ class ShortUrlRepositoryAdapterTest extends TestCase $adapter->getSlice(5, 10); } - /** - * @test - * @dataProvider provideFilteringArgs - */ + #[Test, DataProvider('provideFilteringArgs')] public function countFallsBackToCountList( ?string $searchTerm = null, array $tags = [], @@ -79,7 +75,7 @@ class ShortUrlRepositoryAdapterTest extends TestCase $adapter->getNbResults(); } - public function provideFilteringArgs(): iterable + public static function provideFilteringArgs(): iterable { yield []; yield ['search']; diff --git a/module/Core/test/ShortUrl/Resolver/PersistenceShortUrlRelationResolverTest.php b/module/Core/test/ShortUrl/Resolver/PersistenceShortUrlRelationResolverTest.php index fedfd96f..43f99462 100644 --- a/module/Core/test/ShortUrl/Resolver/PersistenceShortUrlRelationResolverTest.php +++ b/module/Core/test/ShortUrl/Resolver/PersistenceShortUrlRelationResolverTest.php @@ -6,6 +6,8 @@ namespace ShlinkioTest\Shlink\Core\ShortUrl\Resolver; use Doctrine\Common\EventManager; use Doctrine\ORM\EntityManagerInterface; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Domain\Entity\Domain; @@ -29,17 +31,14 @@ class PersistenceShortUrlRelationResolverTest extends TestCase $this->resolver = new PersistenceShortUrlRelationResolver($this->em); } - /** @test */ + #[Test] public function returnsEmptyWhenNoDomainIsProvided(): void { $this->em->expects($this->never())->method('getRepository')->with(Domain::class); self::assertNull($this->resolver->resolveDomain(null)); } - /** - * @test - * @dataProvider provideFoundDomains - */ + #[Test, DataProvider('provideFoundDomains')] public function findsOrCreatesDomainWhenValueIsProvided(?Domain $foundDomain, string $authority): void { $repo = $this->createMock(DomainRepositoryInterface::class); @@ -55,7 +54,7 @@ class PersistenceShortUrlRelationResolverTest extends TestCase self::assertEquals($authority, $result->authority); } - public function provideFoundDomains(): iterable + public static function provideFoundDomains(): iterable { $authority = 's.test'; @@ -63,10 +62,7 @@ class PersistenceShortUrlRelationResolverTest extends TestCase yield 'found domain' => [Domain::withAuthority($authority), $authority]; } - /** - * @test - * @dataProvider provideTags - */ + #[Test, DataProvider('provideTags')] public function findsAndPersistsTagsWrappedIntoCollection(array $tags, array $expectedTags): void { $expectedPersistedTags = count($expectedTags); @@ -89,13 +85,13 @@ 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')]]; } - /** @test */ + #[Test] public function returnsEmptyCollectionWhenProvidingEmptyListOfTags(): void { $this->em->expects($this->never())->method('getRepository')->with(Tag::class); @@ -106,7 +102,7 @@ class PersistenceShortUrlRelationResolverTest extends TestCase self::assertEmpty($result); } - /** @test */ + #[Test] public function newDomainsAreMemoizedUntilStateIsCleared(): void { $repo = $this->createMock(DomainRepositoryInterface::class); @@ -125,7 +121,7 @@ class PersistenceShortUrlRelationResolverTest extends TestCase self::assertNotSame($domain1, $domain3); } - /** @test */ + #[Test] public function newTagsAreMemoizedUntilStateIsCleared(): void { $tagRepo = $this->createMock(TagRepositoryInterface::class); diff --git a/module/Core/test/ShortUrl/Resolver/SimpleShortUrlRelationResolverTest.php b/module/Core/test/ShortUrl/Resolver/SimpleShortUrlRelationResolverTest.php index 443710bb..f74480ba 100644 --- a/module/Core/test/ShortUrl/Resolver/SimpleShortUrlRelationResolverTest.php +++ b/module/Core/test/ShortUrl/Resolver/SimpleShortUrlRelationResolverTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\ShortUrl\Resolver; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Domain\Entity\Domain; use Shlinkio\Shlink\Core\ShortUrl\Resolver\SimpleShortUrlRelationResolver; @@ -18,10 +20,7 @@ class SimpleShortUrlRelationResolverTest extends TestCase $this->resolver = new SimpleShortUrlRelationResolver(); } - /** - * @test - * @dataProvider provideDomains - */ + #[Test, DataProvider('provideDomains')] public function resolvesExpectedDomain(?string $domain): void { $result = $this->resolver->resolveDomain($domain); @@ -34,13 +33,13 @@ class SimpleShortUrlRelationResolverTest extends TestCase } } - public function provideDomains(): iterable + public static function provideDomains(): iterable { yield 'empty domain' => [null]; yield 'non-empty domain' => ['domain.com']; } - /** @test */ + #[Test] public function tagsAreWrappedInEntityCollection(): void { $tags = ['foo', 'bar', 'baz']; diff --git a/module/Core/test/ShortUrl/ShortUrlListServiceTest.php b/module/Core/test/ShortUrl/ShortUrlListServiceTest.php index 446e95eb..37a3eb36 100644 --- a/module/Core/test/ShortUrl/ShortUrlListServiceTest.php +++ b/module/Core/test/ShortUrl/ShortUrlListServiceTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\ShortUrl; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Options\UrlShortenerOptions; @@ -29,10 +31,7 @@ class ShortUrlListServiceTest extends TestCase $this->service = new ShortUrlListService($this->repo, new UrlShortenerOptions()); } - /** - * @test - * @dataProvider provideAdminApiKeys - */ + #[Test, DataProvider('provideAdminApiKeys')] public function listedUrlsAreReturnedFromEntityManager(?ApiKey $apiKey): void { $list = [ diff --git a/module/Core/test/ShortUrl/ShortUrlResolverTest.php b/module/Core/test/ShortUrl/ShortUrlResolverTest.php index 9c42fefb..0ecafd3a 100644 --- a/module/Core/test/ShortUrl/ShortUrlResolverTest.php +++ b/module/Core/test/ShortUrl/ShortUrlResolverTest.php @@ -7,6 +7,8 @@ namespace ShlinkioTest\Shlink\Core\ShortUrl; use Cake\Chronos\Chronos; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\EntityManagerInterface; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException; @@ -40,10 +42,7 @@ class ShortUrlResolverTest extends TestCase $this->urlResolver = new ShortUrlResolver($this->em, new UrlShortenerOptions()); } - /** - * @test - * @dataProvider provideAdminApiKeys - */ + #[Test, DataProvider('provideAdminApiKeys')] public function shortCodeIsProperlyParsed(?ApiKey $apiKey): void { $shortUrl = ShortUrl::withLongUrl('expected_url'); @@ -60,10 +59,7 @@ class ShortUrlResolverTest extends TestCase self::assertSame($shortUrl, $result); } - /** - * @test - * @dataProvider provideAdminApiKeys - */ + #[Test, DataProvider('provideAdminApiKeys')] public function exceptionIsThrownIfShortcodeIsNotFound(?ApiKey $apiKey): void { $shortCode = 'abc123'; @@ -77,7 +73,7 @@ class ShortUrlResolverTest extends TestCase $this->urlResolver->resolveShortUrl($identifier, $apiKey); } - /** @test */ + #[Test] public function shortCodeToEnabledShortUrlProperlyParsesShortCode(): void { $shortUrl = ShortUrl::withLongUrl('expected_url'); @@ -94,10 +90,7 @@ class ShortUrlResolverTest extends TestCase self::assertSame($shortUrl, $result); } - /** - * @test - * @dataProvider provideDisabledShortUrls - */ + #[Test, DataProvider('provideDisabledShortUrls')] public function shortCodeToEnabledShortUrlThrowsExceptionIfUrlIsNotEnabled(ShortUrl $shortUrl): void { $shortCode = $shortUrl->getShortCode(); @@ -113,7 +106,7 @@ class ShortUrlResolverTest extends TestCase $this->urlResolver->resolveEnabledShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode)); } - public function provideDisabledShortUrls(): iterable + public static function provideDisabledShortUrls(): iterable { $now = Chronos::now(); diff --git a/module/Core/test/ShortUrl/ShortUrlServiceTest.php b/module/Core/test/ShortUrl/ShortUrlServiceTest.php index 7851aa9b..60959215 100644 --- a/module/Core/test/ShortUrl/ShortUrlServiceTest.php +++ b/module/Core/test/ShortUrl/ShortUrlServiceTest.php @@ -6,8 +6,11 @@ namespace ShlinkioTest\Shlink\Core\ShortUrl; use Cake\Chronos\Chronos; use Doctrine\ORM\EntityManagerInterface; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; 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; @@ -48,10 +51,7 @@ class ShortUrlServiceTest extends TestCase ); } - /** - * @test - * @dataProvider provideShortUrlEdits - */ + #[Test, DataProvider('provideShortUrlEdits')] public function updateShortUrlUpdatesProvidedData( InvocationOrder $expectedValidateCalls, ShortUrlEdition $shortUrlEdit, @@ -93,23 +93,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', diff --git a/module/Core/test/ShortUrl/Transformer/ShortUrlDataTransformerTest.php b/module/Core/test/ShortUrl/Transformer/ShortUrlDataTransformerTest.php index 6159294b..34474ea3 100644 --- a/module/Core/test/ShortUrl/Transformer/ShortUrlDataTransformerTest.php +++ b/module/Core/test/ShortUrl/Transformer/ShortUrlDataTransformerTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\ShortUrl\Transformer; use Cake\Chronos\Chronos; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifier; @@ -22,10 +24,7 @@ class ShortUrlDataTransformerTest extends TestCase $this->transformer = new ShortUrlDataTransformer(new ShortUrlStringifier([])); } - /** - * @test - * @dataProvider provideShortUrls - */ + #[Test, DataProvider('provideShortUrls')] public function properMetadataIsReturned(ShortUrl $shortUrl, array $expectedMeta): void { ['meta' => $meta] = $this->transformer->transform($shortUrl); @@ -33,7 +32,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(); diff --git a/module/Core/test/ShortUrl/UrlShortenerTest.php b/module/Core/test/ShortUrl/UrlShortenerTest.php index d59de634..713fee95 100644 --- a/module/Core/test/ShortUrl/UrlShortenerTest.php +++ b/module/Core/test/ShortUrl/UrlShortenerTest.php @@ -6,6 +6,8 @@ namespace ShlinkioTest\Shlink\Core\ShortUrl; use Cake\Chronos\Chronos; use Doctrine\ORM\EntityManager; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\EventDispatcher\EventDispatcherInterface; @@ -46,7 +48,7 @@ class UrlShortenerTest extends TestCase ); } - /** @test */ + #[Test] public function urlIsProperlyShortened(): void { $longUrl = 'http://foobar.com/12345/hello?foo=bar'; @@ -61,7 +63,7 @@ class UrlShortenerTest extends TestCase self::assertEquals($longUrl, $shortUrl->getLongUrl()); } - /** @test */ + #[Test] public function exceptionIsThrownWhenNonUniqueSlugIsProvided(): void { $meta = ShortUrlCreation::fromRawData( @@ -78,10 +80,7 @@ class UrlShortenerTest extends TestCase $this->urlShortener->shorten($meta); } - /** - * @test - * @dataProvider provideExistingShortUrls - */ + #[Test, DataProvider('provideExistingShortUrls')] public function existingShortUrlIsReturnedWhenRequested(ShortUrlCreation $meta, ShortUrl $expected): void { $repo = $this->createMock(ShortUrlRepository::class); @@ -95,7 +94,7 @@ class UrlShortenerTest extends TestCase self::assertSame($expected, $result); } - public function provideExistingShortUrls(): iterable + public static function provideExistingShortUrls(): iterable { $url = 'http://foo.com'; diff --git a/module/Core/test/Tag/Entity/TagTest.php b/module/Core/test/Tag/Entity/TagTest.php index 892868d6..d821efb7 100644 --- a/module/Core/test/Tag/Entity/TagTest.php +++ b/module/Core/test/Tag/Entity/TagTest.php @@ -4,12 +4,13 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Tag\Entity; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Tag\Entity\Tag; class TagTest extends TestCase { - /** @test */ + #[Test] public function jsonSerializationOfTagsReturnsItsStringRepresentation(): void { $tag = new Tag('This is my name'); diff --git a/module/Core/test/Tag/Paginator/Adapter/TagsInfoPaginatorAdapterTest.php b/module/Core/test/Tag/Paginator/Adapter/TagsInfoPaginatorAdapterTest.php index fe105ce1..71a535e0 100644 --- a/module/Core/test/Tag/Paginator/Adapter/TagsInfoPaginatorAdapterTest.php +++ b/module/Core/test/Tag/Paginator/Adapter/TagsInfoPaginatorAdapterTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Tag\Paginator\Adapter; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Tag\Model\TagsParams; @@ -21,14 +22,14 @@ class TagsInfoPaginatorAdapterTest extends TestCase $this->adapter = new TagsInfoPaginatorAdapter($this->repo, TagsParams::fromRawData([]), null); } - /** @test */ + #[Test] public function getSliceIsDelegatedToRepository(): void { $this->repo->expects($this->once())->method('findTagsWithInfo')->willReturn([]); $this->adapter->getSlice(1, 1); } - /** @test */ + #[Test] public function getNbResultsIsDelegatedToRepository(): void { $this->repo->expects($this->once())->method('matchSingleScalarResult')->willReturn(3); diff --git a/module/Core/test/Tag/Paginator/Adapter/TagsPaginatorAdapterTest.php b/module/Core/test/Tag/Paginator/Adapter/TagsPaginatorAdapterTest.php index a3b36215..e753db7e 100644 --- a/module/Core/test/Tag/Paginator/Adapter/TagsPaginatorAdapterTest.php +++ b/module/Core/test/Tag/Paginator/Adapter/TagsPaginatorAdapterTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Tag\Paginator\Adapter; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Tag\Model\TagsParams; @@ -21,7 +22,7 @@ class TagsPaginatorAdapterTest extends TestCase $this->adapter = new TagsPaginatorAdapter($this->repo, TagsParams::fromRawData([]), null); } - /** @test */ + #[Test] public function getSliceDelegatesToRepository(): void { $this->repo->expects($this->once())->method('match')->willReturn([]); diff --git a/module/Core/test/Tag/TagServiceTest.php b/module/Core/test/Tag/TagServiceTest.php index 069bca20..5e1b2665 100644 --- a/module/Core/test/Tag/TagServiceTest.php +++ b/module/Core/test/Tag/TagServiceTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Tag; use Doctrine\ORM\EntityManagerInterface; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\ForbiddenTagOperationException; @@ -39,7 +41,7 @@ class TagServiceTest extends TestCase $this->service = new TagService($this->em); } - /** @test */ + #[Test] public function listTagsDelegatesOnRepository(): void { $expected = [new Tag('foo'), new Tag('bar')]; @@ -52,10 +54,7 @@ class TagServiceTest extends TestCase self::assertEquals($expected, $result->getCurrentPageResults()); } - /** - * @test - * @dataProvider provideApiKeysAndSearchTerm - */ + #[Test, DataProvider('provideApiKeysAndSearchTerm')] public function tagsInfoDelegatesOnRepository( ?ApiKey $apiKey, TagsParams $params, @@ -74,7 +73,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, @@ -102,17 +101,14 @@ class TagServiceTest extends TestCase ]; } - /** - * @test - * @dataProvider provideAdminApiKeys - */ + #[Test, DataProvider('provideAdminApiKeys')] public function deleteTagsDelegatesOnRepository(?ApiKey $apiKey): void { $this->repo->expects($this->once())->method('deleteByName')->with(['foo', 'bar'])->willReturn(4); $this->service->deleteTags(['foo', 'bar'], $apiKey); } - /** @test */ + #[Test] public function deleteTagsThrowsExceptionWhenProvidedApiKeyIsNotAdmin(): void { $this->repo->expects($this->never())->method('deleteByName'); @@ -126,10 +122,7 @@ class TagServiceTest extends TestCase ); } - /** - * @test - * @dataProvider provideAdminApiKeys - */ + #[Test, DataProvider('provideAdminApiKeys')] public function renameInvalidTagThrowsException(?ApiKey $apiKey): void { $this->repo->expects($this->once())->method('findOneBy')->willReturn(null); @@ -138,10 +131,7 @@ class TagServiceTest extends TestCase $this->service->renameTag(TagRenaming::fromNames('foo', 'bar'), $apiKey); } - /** - * @test - * @dataProvider provideValidRenames - */ + #[Test, DataProvider('provideValidRenames')] public function renameValidTagChangesItsName(string $oldName, string $newName, int $count): void { $expected = new Tag('foo'); @@ -156,16 +146,13 @@ 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]; } - /** - * @test - * @dataProvider provideAdminApiKeys - */ + #[Test, DataProvider('provideAdminApiKeys')] public function renameTagToAnExistingNameThrowsException(?ApiKey $apiKey): void { $this->repo->expects($this->once())->method('findOneBy')->willReturn(new Tag('foo')); @@ -177,7 +164,7 @@ class TagServiceTest extends TestCase $this->service->renameTag(TagRenaming::fromNames('foo', 'bar'), $apiKey); } - /** @test */ + #[Test] public function renamingTagThrowsExceptionWhenProvidedApiKeyIsNotAdmin(): void { $this->em->expects($this->never())->method('getRepository')->with(Tag::class); diff --git a/module/Core/test/Util/ApiKeyHelpersTrait.php b/module/Core/test/Util/ApiKeyHelpersTrait.php index 6624c8dd..fc6af8af 100644 --- a/module/Core/test/Util/ApiKeyHelpersTrait.php +++ b/module/Core/test/Util/ApiKeyHelpersTrait.php @@ -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()]; diff --git a/module/Core/test/Util/DoctrineBatchHelperTest.php b/module/Core/test/Util/DoctrineBatchHelperTest.php index 2fc0f985..3c86f839 100644 --- a/module/Core/test/Util/DoctrineBatchHelperTest.php +++ b/module/Core/test/Util/DoctrineBatchHelperTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Util; use Doctrine\ORM\EntityManagerInterface; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use RuntimeException; @@ -21,10 +23,7 @@ class DoctrineBatchHelperTest extends TestCase $this->helper = new DoctrineBatchHelper($this->em); } - /** - * @test - * @dataProvider provideIterables - */ + #[Test, DataProvider('provideIterables')] public function entityManagerIsFlushedAndClearedTheExpectedAmountOfTimes( array $iterable, int $batchSize, @@ -43,14 +42,14 @@ 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]; yield [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 11, 1]; } - /** @test */ + #[Test] public function transactionIsRolledBackWhenAnErrorOccurs(): void { $this->em->expects($this->once())->method('flush')->willThrowException(new RuntimeException()); diff --git a/module/Core/test/Util/RedirectResponseHelperTest.php b/module/Core/test/Util/RedirectResponseHelperTest.php index 0e7ec018..63e55e2e 100644 --- a/module/Core/test/Util/RedirectResponseHelperTest.php +++ b/module/Core/test/Util/RedirectResponseHelperTest.php @@ -5,16 +5,15 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Util; use Laminas\Diactoros\Response\RedirectResponse; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Options\RedirectOptions; use Shlinkio\Shlink\Core\Util\RedirectResponseHelper; class RedirectResponseHelperTest extends TestCase { - /** - * @test - * @dataProvider provideRedirectConfigs - */ + #[Test, DataProvider('provideRedirectConfigs')] public function expectedStatusCodeAndCacheIsReturnedBasedOnConfig( int $configuredStatus, int $configuredLifetime, @@ -33,7 +32,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]; diff --git a/module/Core/test/Util/UrlValidatorTest.php b/module/Core/test/Util/UrlValidatorTest.php index 90ab2fd7..233d69bd 100644 --- a/module/Core/test/Util/UrlValidatorTest.php +++ b/module/Core/test/Util/UrlValidatorTest.php @@ -12,6 +12,7 @@ use GuzzleHttp\RequestOptions; use Laminas\Diactoros\Response; use Laminas\Diactoros\Stream; use PHPUnit\Framework\Assert; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\InvalidUrlException; @@ -27,7 +28,7 @@ class UrlValidatorTest extends TestCase $this->httpClient = $this->createMock(ClientInterface::class); } - /** @test */ + #[Test] public function exceptionIsThrownWhenUrlIsInvalid(): void { $this->httpClient->expects($this->once())->method('request')->willThrowException($this->clientException()); @@ -36,7 +37,7 @@ class UrlValidatorTest extends TestCase $this->urlValidator()->validateUrl('http://foobar.com/12345/hello?foo=bar', true); } - /** @test */ + #[Test] public function expectedUrlIsCalledWhenTryingToVerify(): void { $expectedUrl = 'http://foobar.com'; @@ -59,14 +60,14 @@ class UrlValidatorTest extends TestCase $this->urlValidator()->validateUrl($expectedUrl, true); } - /** @test */ + #[Test] public function noCheckIsPerformedWhenUrlValidationIsDisabled(): void { $this->httpClient->expects($this->never())->method('request'); $this->urlValidator()->validateUrl('', false); } - /** @test */ + #[Test] public function validateUrlWithTitleReturnsNullWhenRequestFailsAndValidationIsDisabled(): void { $this->httpClient->expects($this->once())->method('request')->willThrowException($this->clientException()); @@ -76,7 +77,7 @@ class UrlValidatorTest extends TestCase self::assertNull($result); } - /** @test */ + #[Test] public function validateUrlWithTitleReturnsNullWhenAutoResolutionIsDisabled(): void { $this->httpClient->expects($this->never())->method('request'); @@ -86,7 +87,7 @@ class UrlValidatorTest extends TestCase self::assertNull($result); } - /** @test */ + #[Test] public function validateUrlWithTitleReturnsNullWhenAutoResolutionIsDisabledAndValidationIsEnabled(): void { $this->httpClient->expects($this->once())->method('request')->with( @@ -100,7 +101,7 @@ class UrlValidatorTest extends TestCase self::assertNull($result); } - /** @test */ + #[Test] public function validateUrlWithTitleResolvesTitleWhenAutoResolutionIsEnabled(): void { $this->httpClient->expects($this->once())->method('request')->with( @@ -114,7 +115,7 @@ class UrlValidatorTest extends TestCase self::assertEquals('Resolved "title"', $result); } - /** @test */ + #[Test] public function validateUrlWithTitleReturnsNullWhenAutoResolutionIsEnabledAndReturnedContentTypeIsInvalid(): void { $this->httpClient->expects($this->once())->method('request')->with( @@ -128,7 +129,7 @@ class UrlValidatorTest extends TestCase self::assertNull($result); } - /** @test */ + #[Test] public function validateUrlWithTitleReturnsNullWhenAutoResolutionIsEnabledAndBodyDoesNotContainTitle(): void { $this->httpClient->expects($this->once())->method('request')->with( diff --git a/module/Core/test/Visit/Entity/VisitLocationTest.php b/module/Core/test/Visit/Entity/VisitLocationTest.php index ee9e570d..46400f70 100644 --- a/module/Core/test/Visit/Entity/VisitLocationTest.php +++ b/module/Core/test/Visit/Entity/VisitLocationTest.php @@ -4,16 +4,15 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Visit\Entity; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Visit\Entity\VisitLocation; use Shlinkio\Shlink\IpGeolocation\Model\Location; class VisitLocationTest extends TestCase { - /** - * @test - * @dataProvider provideArgs - */ + #[Test, DataProvider('provideArgs')] public function isEmptyReturnsTrueWhenAllValuesAreEmpty(array $args, bool $isEmpty): void { $payload = new Location(...$args); @@ -22,7 +21,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]; diff --git a/module/Core/test/Visit/Entity/VisitTest.php b/module/Core/test/Visit/Entity/VisitTest.php index 5ae22005..5eb88527 100644 --- a/module/Core/test/Visit/Entity/VisitTest.php +++ b/module/Core/test/Visit/Entity/VisitTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Visit\Entity; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Common\Util\IpAddress; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; @@ -12,10 +14,7 @@ use Shlinkio\Shlink\Core\Visit\Model\Visitor; class VisitTest extends TestCase { - /** - * @test - * @dataProvider provideUserAgents - */ + #[Test, DataProvider('provideUserAgents')] public function isProperlyJsonSerialized(string $userAgent, bool $expectedToBePotentialBot): void { $visit = Visit::forValidShortUrl(ShortUrl::createFake(), new Visitor($userAgent, 'some site', '1.2.3.4', '')); @@ -29,7 +28,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', @@ -41,10 +40,7 @@ class VisitTest extends TestCase yield 'Guzzle' => ['guzzlehttp', true]; } - /** - * @test - * @dataProvider provideAddresses - */ + #[Test, DataProvider('provideAddresses')] public function addressIsAnonymizedWhenRequested(bool $anonymize, ?string $address, ?string $expectedAddress): void { $visit = Visit::forValidShortUrl( @@ -56,7 +52,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]; diff --git a/module/Core/test/Visit/Geolocation/VisitLocatorTest.php b/module/Core/test/Visit/Geolocation/VisitLocatorTest.php index ba0d70c4..4621f1a7 100644 --- a/module/Core/test/Visit/Geolocation/VisitLocatorTest.php +++ b/module/Core/test/Visit/Geolocation/VisitLocatorTest.php @@ -6,6 +6,8 @@ namespace ShlinkioTest\Shlink\Core\Visit\Geolocation; use Doctrine\ORM\EntityManager; use Exception; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\IpCannotBeLocatedException; @@ -38,10 +40,7 @@ class VisitLocatorTest extends TestCase $this->visitService = new VisitLocator($this->em, $this->repo); } - /** - * @test - * @dataProvider provideMethodNames - */ + #[Test, DataProvider('provideMethodNames')] public function locateVisitsIteratesAndLocatesExpectedVisits( string $serviceMethodName, string $expectedRepoMethodName, @@ -72,17 +71,14 @@ class VisitLocatorTest extends TestCase }); } - public function provideMethodNames(): iterable + public static function provideMethodNames(): iterable { yield 'locateUnlocatedVisits' => ['locateUnlocatedVisits', 'findUnlocatedVisits']; yield 'locateVisitsWithEmptyLocation' => ['locateVisitsWithEmptyLocation', 'findVisitsWithEmptyLocation']; yield 'locateAllVisits' => ['locateAllVisits', 'findAllVisits']; } - /** - * @test - * @dataProvider provideIsNonLocatableAddress - */ + #[Test, DataProvider('provideIsNonLocatableAddress')] public function visitsWhichCannotBeLocatedAreIgnoredOrLocatedAsEmpty( string $serviceMethodName, string $expectedRepoMethodName, @@ -120,7 +116,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]; diff --git a/module/Core/test/Visit/Geolocation/VisitToLocationHelperTest.php b/module/Core/test/Visit/Geolocation/VisitToLocationHelperTest.php index 7d0fb7f1..57926afe 100644 --- a/module/Core/test/Visit/Geolocation/VisitToLocationHelperTest.php +++ b/module/Core/test/Visit/Geolocation/VisitToLocationHelperTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Visit\Geolocation; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Common\Util\IpAddress; @@ -25,10 +27,7 @@ class VisitToLocationHelperTest extends TestCase $this->helper = new VisitToLocationHelper($this->ipLocationResolver); } - /** - * @test - * @dataProvider provideNonLocatableVisits - */ + #[Test, DataProvider('provideNonLocatableVisits')] public function throwsExpectedErrorForNonLocatableVisit( Visit $visit, IpCannotBeLocatedException $expectedException, @@ -39,7 +38,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 [ @@ -48,7 +47,7 @@ class VisitToLocationHelperTest extends TestCase ]; } - /** @test */ + #[Test] public function throwsGenericErrorWhenResolvingIpFails(): void { $e = new WrongIpException(''); diff --git a/module/Core/test/Visit/Model/VisitorTest.php b/module/Core/test/Visit/Model/VisitorTest.php index 90d238a5..74065d7d 100644 --- a/module/Core/test/Visit/Model/VisitorTest.php +++ b/module/Core/test/Visit/Model/VisitorTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Visit\Model; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Options\TrackingOptions; use Shlinkio\Shlink\Core\Visit\Model\Visitor; @@ -15,10 +17,7 @@ use function substr; class VisitorTest extends TestCase { - /** - * @test - * @dataProvider provideParams - */ + #[Test, DataProvider('provideParams')] public function providedFieldsValuesAreCropped(array $params, array $expected): void { $visitor = new Visitor(...$params); @@ -29,7 +28,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 +48,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 +61,7 @@ class VisitorTest extends TestCase ]; } - private function generateRandomString(int $length): string + private static function generateRandomString(int $length): string { $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $charactersLength = strlen($characters); @@ -73,14 +72,14 @@ class VisitorTest extends TestCase return $randomString; } - /** @test */ + #[Test] 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, diff --git a/module/Core/test/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapterTest.php b/module/Core/test/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapterTest.php index ec256eeb..dd998f71 100644 --- a/module/Core/test/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapterTest.php +++ b/module/Core/test/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapterTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Visit\Paginator\Adapter; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Visit\Entity\Visit; @@ -31,7 +33,7 @@ class NonOrphanVisitsPaginatorAdapterTest extends TestCase $this->adapter = new NonOrphanVisitsPaginatorAdapter($this->repo, $this->params, $this->apiKey); } - /** @test */ + #[Test] public function countDelegatesToRepository(): void { $expectedCount = 5; @@ -47,9 +49,8 @@ class NonOrphanVisitsPaginatorAdapterTest extends TestCase /** * @param int<0, max> $limit * @param int<0, max> $offset - * @test - * @dataProvider provideLimitAndOffset */ + #[Test, DataProvider('provideLimitAndOffset')] public function getSliceDelegatesToRepository(int $limit, int $offset): void { $visitor = Visitor::emptyInstance(); @@ -67,7 +68,7 @@ class NonOrphanVisitsPaginatorAdapterTest extends TestCase self::assertEquals($list, $result); } - public function provideLimitAndOffset(): iterable + public static function provideLimitAndOffset(): iterable { yield [1, 5]; yield [10, 4]; diff --git a/module/Core/test/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapterTest.php b/module/Core/test/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapterTest.php index 6b91a20b..6a367ed7 100644 --- a/module/Core/test/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapterTest.php +++ b/module/Core/test/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapterTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Visit\Paginator\Adapter; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Visit\Entity\Visit; @@ -27,7 +29,7 @@ class OrphanVisitsPaginatorAdapterTest extends TestCase $this->adapter = new OrphanVisitsPaginatorAdapter($this->repo, $this->params); } - /** @test */ + #[Test] public function countDelegatesToRepository(): void { $expectedCount = 5; @@ -43,9 +45,8 @@ class OrphanVisitsPaginatorAdapterTest extends TestCase /** * @param int<0, max> $limit * @param int<0, max> $offset - * @test - * @dataProvider provideLimitAndOffset */ + #[Test, DataProvider('provideLimitAndOffset')] public function getSliceDelegatesToRepository(int $limit, int $offset): void { $visitor = Visitor::emptyInstance(); @@ -59,7 +60,7 @@ class OrphanVisitsPaginatorAdapterTest extends TestCase self::assertEquals($list, $result); } - public function provideLimitAndOffset(): iterable + public static function provideLimitAndOffset(): iterable { yield [1, 5]; yield [10, 4]; diff --git a/module/Core/test/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapterTest.php b/module/Core/test/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapterTest.php index 8ebf1afc..c96e5be5 100644 --- a/module/Core/test/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapterTest.php +++ b/module/Core/test/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapterTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Visit\Paginator\Adapter; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Common\Util\DateRange; @@ -24,7 +25,7 @@ class ShortUrlVisitsPaginatorAdapterTest extends TestCase $this->repo = $this->createMock(VisitRepositoryInterface::class); } - /** @test */ + #[Test] public function repoIsCalledEveryTimeItemsAreFetched(): void { $count = 3; @@ -41,7 +42,7 @@ class ShortUrlVisitsPaginatorAdapterTest extends TestCase } } - /** @test */ + #[Test] public function repoIsCalledOnlyOnceForCount(): void { $count = 3; diff --git a/module/Core/test/Visit/Paginator/Adapter/VisitsForTagPaginatorAdapterTest.php b/module/Core/test/Visit/Paginator/Adapter/VisitsForTagPaginatorAdapterTest.php index a9aec03f..59ce2082 100644 --- a/module/Core/test/Visit/Paginator/Adapter/VisitsForTagPaginatorAdapterTest.php +++ b/module/Core/test/Visit/Paginator/Adapter/VisitsForTagPaginatorAdapterTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Visit\Paginator\Adapter; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Common\Util\DateRange; @@ -23,7 +24,7 @@ class VisitsForTagPaginatorAdapterTest extends TestCase $this->repo = $this->createMock(VisitRepositoryInterface::class); } - /** @test */ + #[Test] public function repoIsCalledEveryTimeItemsAreFetched(): void { $count = 3; @@ -40,7 +41,7 @@ class VisitsForTagPaginatorAdapterTest extends TestCase } } - /** @test */ + #[Test] public function repoIsCalledOnlyOnceForCount(): void { $count = 3; diff --git a/module/Core/test/Visit/RequestTrackerTest.php b/module/Core/test/Visit/RequestTrackerTest.php index 0e1705ee..fdf7e493 100644 --- a/module/Core/test/Visit/RequestTrackerTest.php +++ b/module/Core/test/Visit/RequestTrackerTest.php @@ -7,6 +7,8 @@ namespace ShlinkioTest\Shlink\Core\Visit; use Fig\Http\Message\RequestMethodInterface; use Laminas\Diactoros\ServerRequestFactory; use Mezzio\Router\Middleware\ImplicitHeadMiddleware; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; @@ -45,10 +47,7 @@ class RequestTrackerTest extends TestCase ); } - /** - * @test - * @dataProvider provideNonTrackingRequests - */ + #[Test, DataProvider('provideNonTrackingRequests')] public function trackingIsDisabledWhenRequestDoesNotMeetConditions(ServerRequestInterface $request): void { $this->visitsTracker->expects($this->never())->method('track'); @@ -57,7 +56,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, @@ -81,7 +80,7 @@ class RequestTrackerTest extends TestCase )]; } - /** @test */ + #[Test] public function trackingHappensOverShortUrlsWhenRequestMeetsConditions(): void { $shortUrl = ShortUrl::withLongUrl(self::LONG_URL); @@ -93,7 +92,7 @@ class RequestTrackerTest extends TestCase $this->requestTracker->trackIfApplicable($shortUrl, $this->request); } - /** @test */ + #[Test] public function baseUrlErrorIsTracked(): void { $this->notFoundType->expects($this->once())->method('isBaseUrl')->willReturn(true); @@ -108,7 +107,7 @@ class RequestTrackerTest extends TestCase $this->requestTracker->trackNotFoundIfApplicable($this->request); } - /** @test */ + #[Test] public function regularNotFoundErrorIsTracked(): void { $this->notFoundType->expects($this->once())->method('isBaseUrl')->willReturn(false); @@ -123,7 +122,7 @@ class RequestTrackerTest extends TestCase $this->requestTracker->trackNotFoundIfApplicable($this->request); } - /** @test */ + #[Test] public function invalidShortUrlErrorIsTracked(): void { $this->notFoundType->expects($this->once())->method('isBaseUrl')->willReturn(false); @@ -138,10 +137,7 @@ class RequestTrackerTest extends TestCase $this->requestTracker->trackNotFoundIfApplicable($this->request); } - /** - * @test - * @dataProvider provideNonTrackingRequests - */ + #[Test, DataProvider('provideNonTrackingRequests')] public function notFoundIsNotTrackedIfRequestDoesNotMeetConditions(ServerRequestInterface $request): void { $this->visitsTracker->expects($this->never())->method('trackBaseUrlVisit'); diff --git a/module/Core/test/Visit/Transformer/OrphanVisitDataTransformerTest.php b/module/Core/test/Visit/Transformer/OrphanVisitDataTransformerTest.php index 2f38a17a..527f4fc9 100644 --- a/module/Core/test/Visit/Transformer/OrphanVisitDataTransformerTest.php +++ b/module/Core/test/Visit/Transformer/OrphanVisitDataTransformerTest.php @@ -6,6 +6,8 @@ namespace ShlinkioTest\Shlink\Core\Visit\Transformer; use Laminas\Diactoros\ServerRequestFactory; use Laminas\Diactoros\Uri; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Visit\Entity\Visit; use Shlinkio\Shlink\Core\Visit\Entity\VisitLocation; @@ -23,10 +25,7 @@ class OrphanVisitDataTransformerTest extends TestCase $this->transformer = new OrphanVisitDataTransformer(); } - /** - * @test - * @dataProvider provideVisits - */ + #[Test, DataProvider('provideVisits')] public function visitsAreParsedAsExpected(Visit $visit, array $expectedResult): void { $result = $this->transformer->transform($visit); @@ -34,7 +33,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()), diff --git a/module/Core/test/Visit/VisitsStatsHelperTest.php b/module/Core/test/Visit/VisitsStatsHelperTest.php index 0ed06e7d..18954a22 100644 --- a/module/Core/test/Visit/VisitsStatsHelperTest.php +++ b/module/Core/test/Visit/VisitsStatsHelperTest.php @@ -6,6 +6,9 @@ namespace ShlinkioTest\Shlink\Core\Visit; use Doctrine\ORM\EntityManagerInterface; use Laminas\Stdlib\ArrayUtils; +use PHPUnit\Framework\Assert; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Domain\Entity\Domain; @@ -46,20 +49,21 @@ class VisitsStatsHelperTest extends TestCase $this->helper = new VisitsStatsHelper($this->em); } - /** - * @test - * @dataProvider provideCounts - */ + #[Test, DataProvider('provideCounts')] 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,15 +72,12 @@ 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]); } - /** - * @test - * @dataProvider provideAdminApiKeys - */ + #[Test, DataProvider('provideAdminApiKeys')] public function infoReturnsVisitsForCertainShortCode(?ApiKey $apiKey): void { $shortCode = '123ABC'; @@ -107,7 +108,7 @@ class VisitsStatsHelperTest extends TestCase self::assertEquals($list, ArrayUtils::iteratorToArray($paginator->getCurrentPageResults())); } - /** @test */ + #[Test] public function throwsExceptionWhenRequestingVisitsForInvalidShortCode(): void { $shortCode = '123ABC'; @@ -122,7 +123,7 @@ class VisitsStatsHelperTest extends TestCase $this->helper->visitsForShortUrl($identifier, new VisitsParams()); } - /** @test */ + #[Test] public function throwsExceptionWhenRequestingVisitsForInvalidTag(): void { $tag = 'foo'; @@ -136,10 +137,7 @@ class VisitsStatsHelperTest extends TestCase $this->helper->visitsForTag($tag, new VisitsParams(), $apiKey); } - /** - * @test - * @dataProvider provideAdminApiKeys - */ + #[Test, DataProvider('provideAdminApiKeys')] public function visitsForTagAreReturnedAsExpected(?ApiKey $apiKey): void { $tag = 'foo'; @@ -163,7 +161,7 @@ class VisitsStatsHelperTest extends TestCase self::assertEquals($list, ArrayUtils::iteratorToArray($paginator->getCurrentPageResults())); } - /** @test */ + #[Test] public function throwsExceptionWhenRequestingVisitsForInvalidDomain(): void { $domain = 'foo.com'; @@ -177,10 +175,7 @@ class VisitsStatsHelperTest extends TestCase $this->helper->visitsForDomain($domain, new VisitsParams(), $apiKey); } - /** - * @test - * @dataProvider provideAdminApiKeys - */ + #[Test, DataProvider('provideAdminApiKeys')] public function visitsForNonDefaultDomainAreReturnedAsExpected(?ApiKey $apiKey): void { $domain = 'foo.com'; @@ -208,10 +203,7 @@ class VisitsStatsHelperTest extends TestCase self::assertEquals($list, ArrayUtils::iteratorToArray($paginator->getCurrentPageResults())); } - /** - * @test - * @dataProvider provideAdminApiKeys - */ + #[Test, DataProvider('provideAdminApiKeys')] public function visitsForDefaultDomainAreReturnedAsExpected(?ApiKey $apiKey): void { $repo = $this->createMock(DomainRepository::class); @@ -238,7 +230,7 @@ class VisitsStatsHelperTest extends TestCase self::assertEquals($list, ArrayUtils::iteratorToArray($paginator->getCurrentPageResults())); } - /** @test */ + #[Test] public function orphanVisitsAreReturnedAsExpected(): void { $list = map(range(0, 3), fn () => Visit::forBasePath(Visitor::emptyInstance())); @@ -256,7 +248,7 @@ class VisitsStatsHelperTest extends TestCase self::assertEquals($list, ArrayUtils::iteratorToArray($paginator->getCurrentPageResults())); } - /** @test */ + #[Test] public function nonOrphanVisitsAreReturnedAsExpected(): void { $list = map(range(0, 3), fn () => Visit::forValidShortUrl(ShortUrl::createFake(), Visitor::emptyInstance())); diff --git a/module/Core/test/Visit/VisitsTrackerTest.php b/module/Core/test/Visit/VisitsTrackerTest.php index 9c27d5df..32cd10a8 100644 --- a/module/Core/test/Visit/VisitsTrackerTest.php +++ b/module/Core/test/Visit/VisitsTrackerTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Visit; use Doctrine\ORM\EntityManager; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\EventDispatcher\EventDispatcherInterface; @@ -26,10 +28,7 @@ class VisitsTrackerTest extends TestCase $this->eventDispatcher = $this->createMock(EventDispatcherInterface::class); } - /** - * @test - * @dataProvider provideTrackingMethodNames - */ + #[Test, DataProvider('provideTrackingMethodNames')] public function trackPersistsVisitAndDispatchesEvent(string $method, array $args): void { $this->em->expects($this->once())->method('persist')->with( @@ -43,10 +42,7 @@ class VisitsTrackerTest extends TestCase $this->visitsTracker()->{$method}(...$args); } - /** - * @test - * @dataProvider provideTrackingMethodNames - */ + #[Test, DataProvider('provideTrackingMethodNames')] public function trackingIsSkippedCompletelyWhenDisabledFromOptions(string $method, array $args): void { $this->em->expects($this->never())->method('persist'); @@ -56,7 +52,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()]]; @@ -64,10 +60,7 @@ class VisitsTrackerTest extends TestCase yield 'trackRegularNotFoundVisit' => ['trackRegularNotFoundVisit', [Visitor::emptyInstance()]]; } - /** - * @test - * @dataProvider provideOrphanTrackingMethodNames - */ + #[Test, DataProvider('provideOrphanTrackingMethodNames')] public function orphanVisitsAreNotTrackedWhenDisabled(string $method): void { $this->em->expects($this->never())->method('persist'); @@ -77,7 +70,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']; diff --git a/module/Rest/test-api/Action/CreateShortUrlTest.php b/module/Rest/test-api/Action/CreateShortUrlTest.php index 0bb02c9e..d93fc9f1 100644 --- a/module/Rest/test-api/Action/CreateShortUrlTest.php +++ b/module/Rest/test-api/Action/CreateShortUrlTest.php @@ -6,6 +6,8 @@ namespace ShlinkioApiTest\Shlink\Rest\Action; use Cake\Chronos\Chronos; use GuzzleHttp\RequestOptions; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; use function Functional\map; @@ -14,7 +16,7 @@ use function sprintf; class CreateShortUrlTest extends ApiTestCase { - /** @test */ + #[Test] public function createsNewShortUrlWhenOnlyLongUrlIsProvided(): void { $expectedKeys = ['shortCode', 'shortUrl', 'longUrl', 'dateCreated', 'visitsCount', 'tags']; @@ -26,7 +28,7 @@ class CreateShortUrlTest extends ApiTestCase } } - /** @test */ + #[Test] public function createsNewShortUrlWithCustomSlug(): void { [$statusCode, $payload] = $this->createShortUrl(['customSlug' => 'my cool slug']); @@ -35,10 +37,7 @@ class CreateShortUrlTest extends ApiTestCase self::assertEquals('my-cool-slug', $payload['shortCode']); } - /** - * @test - * @dataProvider provideConflictingSlugs - */ + #[Test, DataProvider('provideConflictingSlugs')] public function failsToCreateShortUrlWithDuplicatedSlug(string $slug, ?string $domain): void { $suffix = $domain === null ? '' : sprintf(' for domain "%s"', $domain); @@ -60,10 +59,7 @@ class CreateShortUrlTest extends ApiTestCase } } - /** - * @test - * @dataProvider provideDuplicatedSlugApiVersions - */ + #[Test, DataProvider('provideDuplicatedSlugApiVersions')] public function expectedTypeIsReturnedForConflictingSlugBasedOnApiVersion( string $version, string $expectedType, @@ -72,17 +68,14 @@ class CreateShortUrlTest extends ApiTestCase self::assertEquals($expectedType, $payload['type']); } - public function provideDuplicatedSlugApiVersions(): iterable + public static function provideDuplicatedSlugApiVersions(): iterable { yield ['1', 'INVALID_SLUG']; yield ['2', 'INVALID_SLUG']; yield ['3', 'https://shlink.io/api/error/non-unique-slug']; } - /** - * @test - * @dataProvider provideTags - */ + #[Test, DataProvider('provideTags')] public function createsNewShortUrlWithTags(array $providedTags, array $expectedTags): void { [$statusCode, ['tags' => $tags]] = $this->createShortUrl(['tags' => $providedTags]); @@ -91,17 +84,14 @@ class CreateShortUrlTest extends ApiTestCase self::assertEquals($expectedTags, $tags); } - public function provideTags(): iterable + public static function provideTags(): iterable { yield 'simple tags' => [$simpleTags = ['foo', 'bar', 'baz'], $simpleTags]; yield 'tags with spaces' => [['fo o', ' bar', 'b az'], ['fo-o', 'bar', 'b-az']]; yield 'tags with special chars' => [['UUU', 'Aäa'], ['uuu', 'aäa']]; } - /** - * @test - * @dataProvider provideMaxVisits - */ + #[Test, DataProvider('provideMaxVisits')] public function createsNewShortUrlWithVisitsLimit(int $maxVisits): void { [$statusCode, ['shortCode' => $shortCode]] = $this->createShortUrl(['maxVisits' => $maxVisits]); @@ -116,12 +106,12 @@ class CreateShortUrlTest extends ApiTestCase self::assertEquals(self::STATUS_NOT_FOUND, $lastResp->getStatusCode()); } - public function provideMaxVisits(): array + public static function provideMaxVisits(): array { return map(range(10, 15), fn(int $i) => [$i]); } - /** @test */ + #[Test] public function createsShortUrlWithValidSince(): void { [$statusCode, ['shortCode' => $shortCode]] = $this->createShortUrl([ @@ -135,7 +125,7 @@ class CreateShortUrlTest extends ApiTestCase self::assertEquals(self::STATUS_NOT_FOUND, $lastResp->getStatusCode()); } - /** @test */ + #[Test] public function createsShortUrlWithValidUntil(): void { [$statusCode, ['shortCode' => $shortCode]] = $this->createShortUrl([ @@ -149,10 +139,7 @@ class CreateShortUrlTest extends ApiTestCase self::assertEquals(self::STATUS_NOT_FOUND, $lastResp->getStatusCode()); } - /** - * @test - * @dataProvider provideMatchingBodies - */ + #[Test, DataProvider('provideMatchingBodies')] public function returnsAnExistingShortUrlWhenRequested(array $body): void { [$firstStatusCode, ['shortCode' => $firstShortCode]] = $this->createShortUrl($body); @@ -165,7 +152,7 @@ class CreateShortUrlTest extends ApiTestCase self::assertEquals($firstShortCode, $secondShortCode); } - public function provideMatchingBodies(): iterable + public static function provideMatchingBodies(): iterable { $longUrl = 'https://www.alejandrocelaya.com'; @@ -182,10 +169,7 @@ class CreateShortUrlTest extends ApiTestCase ]; } - /** - * @test - * @dataProvider provideConflictingSlugs - */ + #[Test, DataProvider('provideConflictingSlugs')] public function returnsErrorWhenRequestingReturnExistingButCustomSlugIsInUse(string $slug, ?string $domain): void { $longUrl = 'https://www.alejandrocelaya.com'; @@ -202,13 +186,13 @@ class CreateShortUrlTest extends ApiTestCase self::assertEquals(self::STATUS_BAD_REQUEST, $secondStatusCode); } - public function provideConflictingSlugs(): iterable + public static function provideConflictingSlugs(): iterable { yield 'without domain' => ['custom', null]; yield 'with domain' => ['custom-with-domain', 'some-domain.com']; } - /** @test */ + #[Test] public function createsNewShortUrlIfRequestedToFindButThereIsNoMatch(): void { [$firstStatusCode, ['shortCode' => $firstShortCode]] = $this->createShortUrl([ @@ -224,10 +208,7 @@ class CreateShortUrlTest extends ApiTestCase self::assertNotEquals($firstShortCode, $secondShortCode); } - /** - * @test - * @dataProvider provideIdn - */ + #[Test, DataProvider('provideIdn')] public function createsNewShortUrlWithInternationalizedDomainName(string $longUrl): void { [$statusCode, $payload] = $this->createShortUrl(['longUrl' => $longUrl]); @@ -236,17 +217,14 @@ class CreateShortUrlTest extends ApiTestCase self::assertEquals($payload['longUrl'], $longUrl); } - public function provideIdn(): iterable + public static function provideIdn(): iterable { yield ['http://tést.shlink.io']; // Redirects to https://shlink.io yield ['http://test.shlink.io']; // Redirects to http://tést.shlink.io yield ['http://téstb.shlink.io']; // Redirects to http://tést.shlink.io } - /** - * @test - * @dataProvider provideInvalidUrls - */ + #[Test, DataProvider('provideInvalidUrls')] public function failsToCreateShortUrlWithInvalidLongUrl(string $url, string $version, string $expectedType): void { $expectedDetail = sprintf('Provided URL %s is invalid. Try with a different one.', $url); @@ -261,16 +239,13 @@ class CreateShortUrlTest extends ApiTestCase self::assertEquals($url, $payload['url']); } - public function provideInvalidUrls(): iterable + public static function provideInvalidUrls(): iterable { yield 'API version 2' => ['https://this-has-to-be-invalid.com', '2', 'INVALID_URL']; yield 'API version 3' => ['https://this-has-to-be-invalid.com', '3', 'https://shlink.io/api/error/invalid-url']; } - /** - * @test - * @dataProvider provideInvalidArgumentApiVersions - */ + #[Test, DataProvider('provideInvalidArgumentApiVersions')] public function failsToCreateShortUrlWithoutLongUrl(array $payload, string $version, string $expectedType): void { $resp = $this->callApiWithKey( @@ -287,7 +262,7 @@ class CreateShortUrlTest extends ApiTestCase self::assertEquals('Invalid data', $payload['title']); } - public function provideInvalidArgumentApiVersions(): iterable + public static function provideInvalidArgumentApiVersions(): iterable { yield 'missing long url v2' => [[], '2', 'INVALID_ARGUMENT']; yield 'missing long url v3' => [[], '3', 'https://shlink.io/api/error/invalid-data']; @@ -307,7 +282,7 @@ class CreateShortUrlTest extends ApiTestCase ], '3', 'https://shlink.io/api/error/invalid-data']; } - /** @test */ + #[Test] public function defaultDomainIsDroppedIfProvided(): void { [$createStatusCode, ['shortCode' => $shortCode]] = $this->createShortUrl([ @@ -323,10 +298,7 @@ class CreateShortUrlTest extends ApiTestCase self::assertNull($payload['domain']); } - /** - * @test - * @dataProvider provideDomains - */ + #[Test, DataProvider('provideDomains')] public function apiKeyDomainIsEnforced(?string $providedDomain): void { [$statusCode, ['domain' => $returnedDomain]] = $this->createShortUrl( @@ -338,24 +310,21 @@ class CreateShortUrlTest extends ApiTestCase self::assertEquals('example.com', $returnedDomain); } - public function provideDomains(): iterable + public static function provideDomains(): iterable { yield 'no domain' => [null]; yield 'invalid domain' => ['this-will-be-overwritten.com']; yield 'example domain' => ['example.com']; } - /** - * @test - * @dataProvider provideTwitterUrls - */ + #[Test, DataProvider('provideTwitterUrls')] public function urlsWithBothProtectionCanBeShortenedWithUrlValidationEnabled(string $longUrl): void { [$statusCode] = $this->createShortUrl(['longUrl' => $longUrl, 'validateUrl' => true]); self::assertEquals(self::STATUS_OK, $statusCode); } - public function provideTwitterUrls(): iterable + public static function provideTwitterUrls(): iterable { yield ['https://twitter.com/shlinkio']; yield ['https://mobile.twitter.com/shlinkio']; @@ -363,7 +332,7 @@ class CreateShortUrlTest extends ApiTestCase yield ['https://mobile.twitter.com/shlinkio/status/1360637738421268481']; } - /** @test */ + #[Test] public function canCreateShortUrlsWithEmojis(): void { [$statusCode, $payload] = $this->createShortUrl([ @@ -377,7 +346,7 @@ class CreateShortUrlTest extends ApiTestCase self::assertEquals('http://s.test/🦣🦣🦣', $payload['shortUrl']); } - /** @test */ + #[Test] public function canCreateShortUrlsWithDeviceLongUrls(): void { [$statusCode, $payload] = $this->createShortUrl([ diff --git a/module/Rest/test-api/Action/DeleteShortUrlTest.php b/module/Rest/test-api/Action/DeleteShortUrlTest.php index f8ba6ef1..e15910ac 100644 --- a/module/Rest/test-api/Action/DeleteShortUrlTest.php +++ b/module/Rest/test-api/Action/DeleteShortUrlTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Action; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; use ShlinkioApiTest\Shlink\Rest\Utils\NotFoundUrlHelpersTrait; @@ -13,10 +15,7 @@ class DeleteShortUrlTest extends ApiTestCase { use NotFoundUrlHelpersTrait; - /** - * @test - * @dataProvider provideInvalidUrls - */ + #[Test, DataProvider('provideInvalidUrls')] public function notFoundErrorIsReturnWhenDeletingInvalidUrl( string $shortCode, ?string $domain, @@ -35,10 +34,7 @@ class DeleteShortUrlTest extends ApiTestCase self::assertEquals($domain, $payload['domain'] ?? null); } - /** - * @test - * @dataProvider provideApiVersions - */ + #[Test, DataProvider('provideApiVersions')] public function expectedTypeIsReturnedBasedOnApiVersion(string $version, string $expectedType): void { $resp = $this->callApiWithKey( @@ -50,14 +46,14 @@ class DeleteShortUrlTest extends ApiTestCase self::assertEquals($expectedType, $payload['type']); } - public function provideApiVersions(): iterable + public static function provideApiVersions(): iterable { yield ['1', 'INVALID_SHORTCODE']; yield ['2', 'INVALID_SHORTCODE']; yield ['3', 'https://shlink.io/api/error/short-url-not-found']; } - /** @test */ + #[Test] public function properShortUrlIsDeletedWhenDomainIsProvided(): void { $fetchWithDomainBefore = $this->callApiWithKey(self::METHOD_GET, '/short-urls/ghi789?domain=example.com'); diff --git a/module/Rest/test-api/Action/DeleteTagsTest.php b/module/Rest/test-api/Action/DeleteTagsTest.php index c81d7906..b04fbaf5 100644 --- a/module/Rest/test-api/Action/DeleteTagsTest.php +++ b/module/Rest/test-api/Action/DeleteTagsTest.php @@ -5,16 +5,15 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Action; use GuzzleHttp\RequestOptions; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; use function sprintf; class DeleteTagsTest extends ApiTestCase { - /** - * @test - * @dataProvider provideNonAdminApiKeys - */ + #[Test, DataProvider('provideNonAdminApiKeys')] public function anErrorIsReturnedWithNonAdminApiKeys(string $apiKey, string $version, string $expectedType): void { $resp = $this->callApiWithKey(self::METHOD_DELETE, sprintf('/rest/v%s/tags', $version), [ @@ -29,7 +28,7 @@ class DeleteTagsTest extends ApiTestCase self::assertEquals('Forbidden tag operation', $payload['title']); } - public function provideNonAdminApiKeys(): iterable + public static function provideNonAdminApiKeys(): iterable { yield 'author' => ['author_api_key', '2', 'FORBIDDEN_OPERATION']; yield 'domain' => ['domain_api_key', '2', 'FORBIDDEN_OPERATION']; diff --git a/module/Rest/test-api/Action/DomainRedirectsTest.php b/module/Rest/test-api/Action/DomainRedirectsTest.php index 7abd4d5e..bc78d035 100644 --- a/module/Rest/test-api/Action/DomainRedirectsTest.php +++ b/module/Rest/test-api/Action/DomainRedirectsTest.php @@ -5,14 +5,13 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Action; use GuzzleHttp\RequestOptions; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; class DomainRedirectsTest extends ApiTestCase { - /** - * @test - * @dataProvider provideInvalidDomains - */ + #[Test, DataProvider('provideInvalidDomains')] public function anErrorIsReturnedWhenTryingToEditAnInvalidDomain(array $request): void { $resp = $this->callApiWithKey(self::METHOD_PATCH, '/domains/redirects', [ @@ -27,7 +26,7 @@ class DomainRedirectsTest extends ApiTestCase self::assertEquals('Invalid data', $payload['title']); } - public function provideInvalidDomains(): iterable + public static function provideInvalidDomains(): iterable { yield 'no domain' => [[]]; yield 'empty domain' => [['domain' => '']]; @@ -35,10 +34,7 @@ class DomainRedirectsTest extends ApiTestCase yield 'invalid domain' => [['domain' => '192.168.1.1']]; } - /** - * @test - * @dataProvider provideRequests - */ + #[Test, DataProvider('provideRequests')] public function allowsToEditDomainRedirects(array $request, array $expectedResponse): void { $resp = $this->callApiWithKey(self::METHOD_PATCH, '/domains/redirects', [ @@ -50,7 +46,7 @@ class DomainRedirectsTest extends ApiTestCase self::assertEquals($expectedResponse, $payload); } - public function provideRequests(): iterable + public static function provideRequests(): iterable { yield 'new domain' => [[ 'domain' => 'my-new-domain.com', diff --git a/module/Rest/test-api/Action/DomainVisitsTest.php b/module/Rest/test-api/Action/DomainVisitsTest.php index c6c31ebb..2c1d1d2e 100644 --- a/module/Rest/test-api/Action/DomainVisitsTest.php +++ b/module/Rest/test-api/Action/DomainVisitsTest.php @@ -5,16 +5,15 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Action; use GuzzleHttp\RequestOptions; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; use function sprintf; class DomainVisitsTest extends ApiTestCase { - /** - * @test - * @dataProvider provideDomains - */ + #[Test, DataProvider('provideDomains')] public function expectedVisitsAreReturned( string $apiKey, string $domain, @@ -32,7 +31,7 @@ class DomainVisitsTest extends ApiTestCase self::assertCount($expectedVisitsAmount, $payload['visits']['data']); } - public function provideDomains(): iterable + public static function provideDomains(): iterable { yield 'example.com with admin API key' => ['valid_api_key', 'example.com', false, 0]; yield 'DEFAULT with admin API key' => ['valid_api_key', 'DEFAULT', false, 7]; @@ -42,10 +41,7 @@ class DomainVisitsTest extends ApiTestCase yield 'DEFAULT with author API key and no bots' => ['author_api_key', 'DEFAULT', true, 4]; } - /** - * @test - * @dataProvider provideApiKeysAndTags - */ + #[Test, DataProvider('provideApiKeysAndTags')] public function notFoundErrorIsReturnedForInvalidTags(string $apiKey, string $domain): void { $resp = $this->callApiWithKey(self::METHOD_GET, sprintf('/domains/%s/visits', $domain), [], $apiKey); @@ -59,17 +55,14 @@ class DomainVisitsTest extends ApiTestCase self::assertEquals($domain, $payload['authority']); } - public function provideApiKeysAndTags(): iterable + public static function provideApiKeysAndTags(): iterable { yield 'admin API key with invalid domain' => ['valid_api_key', 'invalid_domain.com']; yield 'domain API key with not-owned valid domain' => ['domain_api_key', 'this_domain_is_detached.com']; yield 'author API key with valid domain not used in URLs' => ['author_api_key', 'this_domain_is_detached.com']; } - /** - * @test - * @dataProvider provideApiVersions - */ + #[Test, DataProvider('provideApiVersions')] public function expectedNotFoundTypeIsReturnedForApiVersion(string $version, string $expectedType): void { $resp = $this->callApiWithKey(self::METHOD_GET, sprintf('/rest/v%s/domains/invalid.com/visits', $version)); @@ -78,7 +71,7 @@ class DomainVisitsTest extends ApiTestCase self::assertEquals($expectedType, $payload['type']); } - public function provideApiVersions(): iterable + public static function provideApiVersions(): iterable { yield ['1', 'DOMAIN_NOT_FOUND']; yield ['2', 'DOMAIN_NOT_FOUND']; diff --git a/module/Rest/test-api/Action/EditShortUrlTest.php b/module/Rest/test-api/Action/EditShortUrlTest.php index 74fdebc5..8ac26a27 100644 --- a/module/Rest/test-api/Action/EditShortUrlTest.php +++ b/module/Rest/test-api/Action/EditShortUrlTest.php @@ -5,10 +5,11 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Action; use Cake\Chronos\Chronos; -use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts; use GuzzleHttp\Psr7\Query; use GuzzleHttp\RequestOptions; use Laminas\Diactoros\Uri; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; use ShlinkioApiTest\Shlink\Rest\Utils\NotFoundUrlHelpersTrait; @@ -16,13 +17,9 @@ use function sprintf; class EditShortUrlTest extends ApiTestCase { - use ArraySubsetAsserts; use NotFoundUrlHelpersTrait; - /** - * @test - * @dataProvider provideMeta - */ + #[Test, DataProvider('provideMeta')] public function metadataCanBeReset(array $meta): void { $shortCode = 'abc123'; @@ -47,7 +44,14 @@ class EditShortUrlTest extends ApiTestCase self::assertArraySubset($meta, $metaAfterEditing); } - public function provideMeta(): iterable + private static function assertArraySubset(array $a, array $b): void + { + foreach ($a as $key => $expectedValue) { + self::assertEquals($expectedValue, $b[$key]); + } + } + + public static function provideMeta(): iterable { $now = Chronos::now(); @@ -71,10 +75,7 @@ class EditShortUrlTest extends ApiTestCase return $matchingShortUrl['meta'] ?? []; } - /** - * @test - * @dataProvider provideLongUrls - */ + #[Test, DataProvider('provideLongUrls')] public function longUrlCanBeEditedIfItIsValid(string $longUrl, int $expectedStatus, ?string $expectedError): void { $shortCode = 'abc123'; @@ -92,16 +93,13 @@ class EditShortUrlTest extends ApiTestCase } } - public function provideLongUrls(): iterable + public static function provideLongUrls(): iterable { yield 'valid URL' => ['https://shlink.io', self::STATUS_OK, null]; yield 'invalid URL' => ['htt:foo', self::STATUS_BAD_REQUEST, 'INVALID_URL']; } - /** - * @test - * @dataProvider provideInvalidUrls - */ + #[Test, DataProvider('provideInvalidUrls')] public function tryingToEditInvalidUrlReturnsNotFoundError( string $shortCode, ?string $domain, @@ -121,7 +119,7 @@ class EditShortUrlTest extends ApiTestCase self::assertEquals($domain, $payload['domain'] ?? null); } - /** @test */ + #[Test] public function providingInvalidDataReturnsBadRequest(): void { $expectedDetail = 'Provided data is not valid'; @@ -138,10 +136,7 @@ class EditShortUrlTest extends ApiTestCase self::assertEquals('Invalid data', $payload['title']); } - /** - * @test - * @dataProvider provideDomains - */ + #[Test, DataProvider('provideDomains')] public function metadataIsEditedOnProperShortUrlBasedOnDomain(?string $domain, string $expectedUrl): void { $shortCode = 'ghi789'; @@ -162,7 +157,7 @@ class EditShortUrlTest extends ApiTestCase self::assertEquals(100, $editedShortUrl['meta']['maxVisits'] ?? null); } - public function provideDomains(): iterable + public static function provideDomains(): iterable { yield 'domain' => [ 'example.com', @@ -171,7 +166,7 @@ class EditShortUrlTest extends ApiTestCase yield 'no domain' => [null, 'https://shlink.io/documentation/']; } - /** @test */ + #[Test] public function deviceLongUrlsCanBeEdited(): void { $shortCode = 'def456'; diff --git a/module/Rest/test-api/Action/GlobalVisitsTest.php b/module/Rest/test-api/Action/GlobalVisitsTest.php index 1b71f976..50591a14 100644 --- a/module/Rest/test-api/Action/GlobalVisitsTest.php +++ b/module/Rest/test-api/Action/GlobalVisitsTest.php @@ -4,14 +4,13 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Action; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; class GlobalVisitsTest extends ApiTestCase { - /** - * @test - * @dataProvider provideApiKeys - */ + #[Test, DataProvider('provideApiKeys')] public function returnsExpectedVisitsStats(string $apiKey, int $expectedVisits): void { $resp = $this->callApiWithKey(self::METHOD_GET, '/visits', [], $apiKey); @@ -24,7 +23,7 @@ class GlobalVisitsTest extends ApiTestCase self::assertEquals(3, $payload['visits']['orphanVisitsCount']); } - public function provideApiKeys(): iterable + public static function provideApiKeys(): iterable { yield 'admin API key' => ['valid_api_key', 7]; yield 'domain API key' => ['domain_api_key', 0]; diff --git a/module/Rest/test-api/Action/ListDomainsTest.php b/module/Rest/test-api/Action/ListDomainsTest.php index 42f011c7..b63b6d16 100644 --- a/module/Rest/test-api/Action/ListDomainsTest.php +++ b/module/Rest/test-api/Action/ListDomainsTest.php @@ -4,14 +4,13 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Action; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; class ListDomainsTest extends ApiTestCase { - /** - * @test - * @dataProvider provideApiKeysAndDomains - */ + #[Test, DataProvider('provideApiKeysAndDomains')] public function domainsAreProperlyListed(string $apiKey, array $expectedDomains): void { $resp = $this->callApiWithKey(self::METHOD_GET, '/domains', [], $apiKey); @@ -30,7 +29,7 @@ class ListDomainsTest extends ApiTestCase ], $respPayload); } - public function provideApiKeysAndDomains(): iterable + public static function provideApiKeysAndDomains(): iterable { yield 'admin API key' => ['valid_api_key', [ [ diff --git a/module/Rest/test-api/Action/ListShortUrlsTest.php b/module/Rest/test-api/Action/ListShortUrlsTest.php index c35c8fec..6c599a4f 100644 --- a/module/Rest/test-api/Action/ListShortUrlsTest.php +++ b/module/Rest/test-api/Action/ListShortUrlsTest.php @@ -6,6 +6,8 @@ namespace ShlinkioApiTest\Shlink\Rest\Action; use Cake\Chronos\Chronos; use GuzzleHttp\RequestOptions; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\Core\Model\DeviceType; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; @@ -150,10 +152,7 @@ class ListShortUrlsTest extends ApiTestCase 'forwardQuery' => true, ]; - /** - * @test - * @dataProvider provideFilteredLists - */ + #[Test, DataProvider('provideFilteredLists')] public function shortUrlsAreProperlyListed(array $query, array $expectedShortUrls, string $apiKey): void { $resp = $this->callApiWithKey(self::METHOD_GET, '/short-urls', [RequestOptions::QUERY => $query], $apiKey); @@ -168,7 +167,7 @@ class ListShortUrlsTest extends ApiTestCase ], $respPayload); } - public function provideFilteredLists(): iterable + public static function provideFilteredLists(): iterable { // FIXME Cannot use enums in constants in PHP 8.1. Change this once support for PHP 8.1 is dropped $withDeviceLongUrls = static fn (array $shortUrl, ?array $longUrls = null) => [ @@ -302,10 +301,7 @@ class ListShortUrlsTest extends ApiTestCase ]; } - /** - * @test - * @dataProvider provideInvalidFiltering - */ + #[Test, DataProvider('provideInvalidFiltering')] public function errorIsReturnedWhenProvidingInvalidValues(array $query, array $expectedInvalidElements): void { $resp = $this->callApiWithKey(self::METHOD_GET, '/short-urls', [RequestOptions::QUERY => $query]); @@ -321,7 +317,7 @@ class ListShortUrlsTest extends ApiTestCase ], $respPayload); } - public function provideInvalidFiltering(): iterable + public static function provideInvalidFiltering(): iterable { yield [['tagsMode' => 'invalid'], ['tagsMode']]; yield [['orderBy' => 'invalid'], ['orderBy']]; diff --git a/module/Rest/test-api/Action/ListTagsTest.php b/module/Rest/test-api/Action/ListTagsTest.php index 4c627e7c..1851a0e1 100644 --- a/module/Rest/test-api/Action/ListTagsTest.php +++ b/module/Rest/test-api/Action/ListTagsTest.php @@ -5,14 +5,13 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Action; use GuzzleHttp\RequestOptions; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; class ListTagsTest extends ApiTestCase { - /** - * @test - * @dataProvider provideQueries - */ + #[Test, DataProvider('provideQueries')] public function expectedListOfTagsIsReturned(string $apiKey, array $query, array $expectedTags): void { $resp = $this->callApiWithKey(self::METHOD_GET, '/tags', [RequestOptions::QUERY => $query], $apiKey); @@ -21,7 +20,7 @@ class ListTagsTest extends ApiTestCase self::assertEquals(['tags' => $expectedTags], $payload); } - public function provideQueries(): iterable + public static function provideQueries(): iterable { yield 'admin API key' => ['valid_api_key', [], [ 'data' => ['bar', 'baz', 'foo'], diff --git a/module/Rest/test-api/Action/NonOrphanVisitsTest.php b/module/Rest/test-api/Action/NonOrphanVisitsTest.php index c53e29cc..f4f7601c 100644 --- a/module/Rest/test-api/Action/NonOrphanVisitsTest.php +++ b/module/Rest/test-api/Action/NonOrphanVisitsTest.php @@ -6,15 +6,14 @@ namespace ShlinkioApiTest\Shlink\Rest\Action; use Cake\Chronos\Chronos; use GuzzleHttp\RequestOptions; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\Common\Paginator\Paginator; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; class NonOrphanVisitsTest extends ApiTestCase { - /** - * @test - * @dataProvider provideQueries - */ + #[Test, DataProvider('provideQueries')] public function properVisitsAreReturnedBasedInQuery(array $query, int $totalItems, int $returnedItems): void { $resp = $this->callApiWithKey(self::METHOD_GET, '/visits/non-orphan', [RequestOptions::QUERY => $query]); @@ -24,7 +23,7 @@ class NonOrphanVisitsTest extends ApiTestCase self::assertCount($returnedItems, $payload['visits']['data'] ?? []); } - public function provideQueries(): iterable + public static function provideQueries(): iterable { yield 'all data' => [[], 7, 7]; yield 'middle page' => [['page' => 2, 'itemsPerPage' => 3], 7, 3]; diff --git a/module/Rest/test-api/Action/OrphanVisitsTest.php b/module/Rest/test-api/Action/OrphanVisitsTest.php index eee35d73..2049d80d 100644 --- a/module/Rest/test-api/Action/OrphanVisitsTest.php +++ b/module/Rest/test-api/Action/OrphanVisitsTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Action; use GuzzleHttp\RequestOptions; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\Common\Paginator\Paginator; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; @@ -38,10 +40,7 @@ class OrphanVisitsTest extends ApiTestCase 'type' => 'base_url', ]; - /** - * @test - * @dataProvider provideQueries - */ + #[Test, DataProvider('provideQueries')] public function properVisitsAreReturnedBasedInQuery( array $query, int $totalItems, @@ -57,7 +56,7 @@ class OrphanVisitsTest extends ApiTestCase self::assertEquals($expectedVisits, $visits); } - public function provideQueries(): iterable + public static function provideQueries(): iterable { yield 'all data' => [[], 3, 3, [self::INVALID_SHORT_URL, self::REGULAR_NOT_FOUND, self::BASE_URL]]; yield 'limit items' => [['itemsPerPage' => 2], 3, 2, [self::INVALID_SHORT_URL, self::REGULAR_NOT_FOUND]]; diff --git a/module/Rest/test-api/Action/RenameTagTest.php b/module/Rest/test-api/Action/RenameTagTest.php index 7ed4ff4f..e401da1d 100644 --- a/module/Rest/test-api/Action/RenameTagTest.php +++ b/module/Rest/test-api/Action/RenameTagTest.php @@ -5,14 +5,13 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Action; use GuzzleHttp\RequestOptions; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; class RenameTagTest extends ApiTestCase { - /** - * @test - * @dataProvider provideNonAdminApiKeys - */ + #[Test, DataProvider('provideNonAdminApiKeys')] public function anErrorIsReturnedWithNonAdminApiKeys(string $apiKey): void { $resp = $this->callApiWithKey(self::METHOD_PUT, '/tags', [ @@ -30,7 +29,7 @@ class RenameTagTest extends ApiTestCase self::assertEquals('Forbidden tag operation', $payload['title']); } - public function provideNonAdminApiKeys(): iterable + public static function provideNonAdminApiKeys(): iterable { yield 'author' => ['author_api_key']; yield 'domain' => ['domain_api_key']; diff --git a/module/Rest/test-api/Action/ResolveShortUrlTest.php b/module/Rest/test-api/Action/ResolveShortUrlTest.php index 216e35e9..08bc6cb0 100644 --- a/module/Rest/test-api/Action/ResolveShortUrlTest.php +++ b/module/Rest/test-api/Action/ResolveShortUrlTest.php @@ -6,6 +6,8 @@ namespace ShlinkioApiTest\Shlink\Rest\Action; use Cake\Chronos\Chronos; use GuzzleHttp\RequestOptions; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; use ShlinkioApiTest\Shlink\Rest\Utils\NotFoundUrlHelpersTrait; @@ -15,10 +17,7 @@ class ResolveShortUrlTest extends ApiTestCase { use NotFoundUrlHelpersTrait; - /** - * @test - * @dataProvider provideDisabledMeta - */ + #[Test, DataProvider('provideDisabledMeta')] public function shortUrlIsProperlyResolvedEvenWhenNotEnabled(array $disabledMeta): void { $shortCode = 'abc123'; @@ -34,7 +33,7 @@ class ResolveShortUrlTest extends ApiTestCase self::assertEquals(self::STATUS_OK, $fetchResp->getStatusCode()); } - public function provideDisabledMeta(): iterable + public static function provideDisabledMeta(): iterable { $now = Chronos::now(); @@ -43,10 +42,7 @@ class ResolveShortUrlTest extends ApiTestCase yield 'maxVisits reached' => [['maxVisits' => 1]]; } - /** - * @test - * @dataProvider provideInvalidUrls - */ + #[Test, DataProvider('provideInvalidUrls')] public function tryingToResolveInvalidUrlReturnsNotFoundError( string $shortCode, ?string $domain, diff --git a/module/Rest/test-api/Action/ShortUrlVisitsTest.php b/module/Rest/test-api/Action/ShortUrlVisitsTest.php index a9e571da..70659ed8 100644 --- a/module/Rest/test-api/Action/ShortUrlVisitsTest.php +++ b/module/Rest/test-api/Action/ShortUrlVisitsTest.php @@ -6,6 +6,8 @@ namespace ShlinkioApiTest\Shlink\Rest\Action; use GuzzleHttp\Psr7\Query; use Laminas\Diactoros\Uri; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\Common\Paginator\Paginator; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; use ShlinkioApiTest\Shlink\Rest\Utils\NotFoundUrlHelpersTrait; @@ -16,10 +18,7 @@ class ShortUrlVisitsTest extends ApiTestCase { use NotFoundUrlHelpersTrait; - /** - * @test - * @dataProvider provideInvalidUrls - */ + #[Test, DataProvider('provideInvalidUrls')] public function tryingToGetVisitsForInvalidUrlReturnsNotFoundError( string $shortCode, ?string $domain, @@ -43,10 +42,7 @@ class ShortUrlVisitsTest extends ApiTestCase self::assertEquals($domain, $payload['domain'] ?? null); } - /** - * @test - * @dataProvider provideDomains - */ + #[Test, DataProvider('provideDomains')] public function properVisitsAreReturnedWhenDomainIsProvided(?string $domain, int $expectedAmountOfVisits): void { $shortCode = 'ghi789'; @@ -66,16 +62,13 @@ class ShortUrlVisitsTest extends ApiTestCase self::assertCount($expectedAmountOfVisits, $payload['visits']['data'] ?? []); } - public function provideDomains(): iterable + public static function provideDomains(): iterable { yield 'domain' => ['example.com', 0]; yield 'no domain' => [null, 2]; } - /** - * @test - * @dataProvider provideVisitsForBots - */ + #[Test, DataProvider('provideVisitsForBots')] public function properVisitsAreReturnedWhenExcludingBots(bool $excludeBots, int $expectedAmountOfVisits): void { $shortCode = 'def456'; @@ -95,7 +88,7 @@ class ShortUrlVisitsTest extends ApiTestCase self::assertCount($expectedAmountOfVisits, $payload['visits']['data'] ?? []); } - public function provideVisitsForBots(): iterable + public static function provideVisitsForBots(): iterable { yield 'bots excluded' => [true, 1]; yield 'bots not excluded' => [false, 2]; diff --git a/module/Rest/test-api/Action/SingleStepCreateShortUrlTest.php b/module/Rest/test-api/Action/SingleStepCreateShortUrlTest.php index 0c5ab1b4..faed281d 100644 --- a/module/Rest/test-api/Action/SingleStepCreateShortUrlTest.php +++ b/module/Rest/test-api/Action/SingleStepCreateShortUrlTest.php @@ -5,15 +5,14 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Action; use GuzzleHttp\RequestOptions; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Psr\Http\Message\ResponseInterface; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; class SingleStepCreateShortUrlTest extends ApiTestCase { - /** - * @test - * @dataProvider provideFormats - */ + #[Test, DataProvider('provideFormats')] public function createsNewShortUrlWithExpectedResponse(?string $format, string $expectedContentType): void { $resp = $this->createShortUrl($format, 'valid_api_key'); @@ -22,14 +21,14 @@ class SingleStepCreateShortUrlTest extends ApiTestCase self::assertEquals($expectedContentType, $resp->getHeaderLine('Content-Type')); } - public function provideFormats(): iterable + public static function provideFormats(): iterable { yield 'txt format' => ['txt', 'text/plain']; yield 'json format' => ['json', 'application/json']; yield ' format' => [null, 'application/json']; } - /** @test */ + #[Test] public function authorizationErrorIsReturnedIfNoApiKeyIsSent(): void { $expectedDetail = 'Expected authentication to be provided in "apiKey" query param'; diff --git a/module/Rest/test-api/Action/TagVisitsTest.php b/module/Rest/test-api/Action/TagVisitsTest.php index 544fcccf..fc54c111 100644 --- a/module/Rest/test-api/Action/TagVisitsTest.php +++ b/module/Rest/test-api/Action/TagVisitsTest.php @@ -5,16 +5,15 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Action; use GuzzleHttp\RequestOptions; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; use function sprintf; class TagVisitsTest extends ApiTestCase { - /** - * @test - * @dataProvider provideTags - */ + #[Test, DataProvider('provideTags')] public function expectedVisitsAreReturned( string $apiKey, string $tag, @@ -32,7 +31,7 @@ class TagVisitsTest extends ApiTestCase self::assertCount($expectedVisitsAmount, $payload['visits']['data']); } - public function provideTags(): iterable + public static function provideTags(): iterable { yield 'foo with admin API key' => ['valid_api_key', 'foo', false, 5]; yield 'foo with admin API key and no bots' => ['valid_api_key', 'foo', true, 4]; @@ -46,10 +45,7 @@ class TagVisitsTest extends ApiTestCase yield 'foo with domain API key' => ['domain_api_key', 'foo', false, 0]; } - /** - * @test - * @dataProvider provideApiKeysAndTags - */ + #[Test, DataProvider('provideApiKeysAndTags')] public function notFoundErrorIsReturnedForInvalidTags(string $apiKey, string $tag): void { $resp = $this->callApiWithKey(self::METHOD_GET, sprintf('/tags/%s/visits', $tag), [], $apiKey); @@ -62,7 +58,7 @@ class TagVisitsTest extends ApiTestCase self::assertEquals('Tag not found', $payload['title']); } - public function provideApiKeysAndTags(): iterable + public static function provideApiKeysAndTags(): iterable { yield 'admin API key with invalid tag' => ['valid_api_key', 'invalid_tag']; yield 'domain API key with valid tag not used' => ['domain_api_key', 'bar']; diff --git a/module/Rest/test-api/Action/TagsStatsTest.php b/module/Rest/test-api/Action/TagsStatsTest.php index 573f1c38..4ee94d42 100644 --- a/module/Rest/test-api/Action/TagsStatsTest.php +++ b/module/Rest/test-api/Action/TagsStatsTest.php @@ -5,14 +5,13 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Action; use GuzzleHttp\RequestOptions; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; class TagsStatsTest extends ApiTestCase { - /** - * @test - * @dataProvider provideQueries - */ + #[Test, DataProvider('provideQueries')] public function expectedListOfTagsIsReturned( string $apiKey, array $query, @@ -26,10 +25,7 @@ class TagsStatsTest extends ApiTestCase self::assertEquals($expectedPagination, $tags['pagination']); } - /** - * @test - * @dataProvider provideQueries - */ + #[Test, DataProvider('provideQueries')] public function expectedListOfTagsIsReturnedForDeprecatedApproach( string $apiKey, array $query, @@ -45,7 +41,7 @@ class TagsStatsTest extends ApiTestCase self::assertArrayHasKey('data', $tags); } - public function provideQueries(): iterable + public static function provideQueries(): iterable { yield 'admin API key' => ['valid_api_key', [], [ [ diff --git a/module/Rest/test-api/Action/UpdateTagTest.php b/module/Rest/test-api/Action/UpdateTagTest.php index 414e7670..96b8ed62 100644 --- a/module/Rest/test-api/Action/UpdateTagTest.php +++ b/module/Rest/test-api/Action/UpdateTagTest.php @@ -5,16 +5,15 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Action; use GuzzleHttp\RequestOptions; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; use function sprintf; class UpdateTagTest extends ApiTestCase { - /** - * @test - * @dataProvider provideInvalidBody - */ + #[Test, DataProvider('provideInvalidBody')] public function notProvidingTagsReturnsBadRequest(array $body): void { $expectedDetail = 'Provided data is not valid'; @@ -29,17 +28,14 @@ class UpdateTagTest extends ApiTestCase self::assertEquals('Invalid data', $payload['title']); } - public function provideInvalidBody(): iterable + public static function provideInvalidBody(): iterable { yield [[]]; yield [['oldName' => 'foo']]; yield [['newName' => 'foo']]; } - /** - * @test - * @dataProvider provideTagNotFoundApiVersions - */ + #[Test, DataProvider('provideTagNotFoundApiVersions')] public function tryingToRenameInvalidTagReturnsNotFound(string $version, string $expectedType): void { $expectedDetail = 'Tag with name "invalid_tag" could not be found'; @@ -57,17 +53,14 @@ class UpdateTagTest extends ApiTestCase self::assertEquals('Tag not found', $payload['title']); } - public function provideTagNotFoundApiVersions(): iterable + public static function provideTagNotFoundApiVersions(): iterable { yield 'version 1' => ['1', 'TAG_NOT_FOUND']; yield 'version 2' => ['2', 'TAG_NOT_FOUND']; yield 'version 3' => ['3', 'https://shlink.io/api/error/tag-not-found']; } - /** - * @test - * @dataProvider provideTagConflictsApiVersions - */ + #[Test, DataProvider('provideTagConflictsApiVersions')] public function errorIsThrownWhenTryingToRenameTagToAnotherTagName(string $version, string $expectedType): void { $expectedDetail = 'You cannot rename tag foo to bar, because it already exists'; @@ -85,14 +78,14 @@ class UpdateTagTest extends ApiTestCase self::assertEquals('Tag conflict', $payload['title']); } - public function provideTagConflictsApiVersions(): iterable + public static function provideTagConflictsApiVersions(): iterable { yield 'version 1' => ['1', 'TAG_CONFLICT']; yield 'version 2' => ['2', 'TAG_CONFLICT']; yield 'version 3' => ['3', 'https://shlink.io/api/error/tag-conflict']; } - /** @test */ + #[Test] public function tagIsProperlyRenamedWhenRenamingToItself(): void { $resp = $this->callApiWithKey(self::METHOD_PUT, '/tags', [RequestOptions::JSON => [ diff --git a/module/Rest/test-api/Action/VisitStatsTest.php b/module/Rest/test-api/Action/VisitStatsTest.php index 424eba73..10a4de0c 100644 --- a/module/Rest/test-api/Action/VisitStatsTest.php +++ b/module/Rest/test-api/Action/VisitStatsTest.php @@ -4,14 +4,13 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Action; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; class VisitStatsTest extends ApiTestCase { - /** - * @test - * @dataProvider provideApiKeysAndResults - */ + #[Test, DataProvider('provideApiKeysAndResults')] public function expectedStatsAreReturned(string $apiKey, array $expectedPayload): void { $resp = $this->callApiWithKey(self::METHOD_GET, '/visits', apiKey: $apiKey); @@ -20,7 +19,7 @@ class VisitStatsTest extends ApiTestCase self::assertEquals(['visits' => $expectedPayload], $payload); } - public function provideApiKeysAndResults(): iterable + public static function provideApiKeysAndResults(): iterable { yield 'valid API key' => ['valid_api_key', [ 'nonOrphanVisits' => [ diff --git a/module/Rest/test-api/Middleware/AuthenticationTest.php b/module/Rest/test-api/Middleware/AuthenticationTest.php index 51128079..d086f6a6 100644 --- a/module/Rest/test-api/Middleware/AuthenticationTest.php +++ b/module/Rest/test-api/Middleware/AuthenticationTest.php @@ -4,16 +4,15 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Middleware; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; use function sprintf; class AuthenticationTest extends ApiTestCase { - /** - * @test - * @dataProvider provideApiVersions - */ + #[Test, DataProvider('provideApiVersions')] public function authorizationErrorIsReturnedIfNoApiKeyIsSent(string $version, string $expectedType): void { $expectedDetail = 'Expected one of the following authentication headers, ["X-Api-Key"], but none were provided'; @@ -28,17 +27,14 @@ class AuthenticationTest extends ApiTestCase self::assertEquals('Invalid authorization', $payload['title']); } - public function provideApiVersions(): iterable + public static function provideApiVersions(): iterable { yield 'version 1' => ['1', 'INVALID_AUTHORIZATION']; yield 'version 2' => ['2', 'INVALID_AUTHORIZATION']; yield 'version 3' => ['3', 'https://shlink.io/api/error/missing-authentication']; } - /** - * @test - * @dataProvider provideInvalidApiKeys - */ + #[Test, DataProvider('provideInvalidApiKeys')] public function apiKeyErrorIsReturnedWhenProvidedApiKeyIsInvalid( string $apiKey, string $version, @@ -60,7 +56,7 @@ class AuthenticationTest extends ApiTestCase self::assertEquals('Invalid API key', $payload['title']); } - public function provideInvalidApiKeys(): iterable + public static function provideInvalidApiKeys(): iterable { yield 'key which does not exist' => ['invalid', '2', 'INVALID_API_KEY']; yield 'key which is expired' => ['expired_api_key', '2', 'INVALID_API_KEY']; diff --git a/module/Rest/test-api/Middleware/BodyParserTest.php b/module/Rest/test-api/Middleware/BodyParserTest.php index e2170c76..5956a0cc 100644 --- a/module/Rest/test-api/Middleware/BodyParserTest.php +++ b/module/Rest/test-api/Middleware/BodyParserTest.php @@ -5,11 +5,12 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Middleware; use GuzzleHttp\RequestOptions; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; class BodyParserTest extends ApiTestCase { - /** @test */ + #[Test] public function returnsErrorWhenRequestBodyIsInvalidJson(): void { $resp = $this->callApiWithKey(self::METHOD_POST, '/short-urls', [ diff --git a/module/Rest/test-api/Middleware/CorsTest.php b/module/Rest/test-api/Middleware/CorsTest.php index b09e2b3b..8198a21c 100644 --- a/module/Rest/test-api/Middleware/CorsTest.php +++ b/module/Rest/test-api/Middleware/CorsTest.php @@ -5,11 +5,13 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Middleware; use GuzzleHttp\RequestOptions; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; class CorsTest extends ApiTestCase { - /** @test */ + #[Test] public function responseDoesNotIncludeCorsHeadersWhenOriginIsNotSent(): void { $resp = $this->callApiWithKey(self::METHOD_GET, '/short-urls'); @@ -21,10 +23,7 @@ class CorsTest extends ApiTestCase self::assertFalse($resp->hasHeader('Access-Control-Allow-Headers')); } - /** - * @test - * @dataProvider provideOrigins - */ + #[Test, DataProvider('provideOrigins')] public function responseIncludesCorsHeadersIfOriginIsSent( string $origin, string $endpoint, @@ -41,17 +40,14 @@ class CorsTest extends ApiTestCase self::assertFalse($resp->hasHeader('Access-Control-Allow-Headers')); } - public function provideOrigins(): iterable + public static function provideOrigins(): iterable { yield 'foo.com' => ['foo.com', '/short-urls', 200]; yield 'bar.io' => ['bar.io', '/foo/bar', 404]; yield 'baz.dev' => ['baz.dev', '/short-urls', 200]; } - /** - * @test - * @dataProvider providePreflightEndpoints - */ + #[Test, DataProvider('providePreflightEndpoints')] public function preflightRequestsIncludeExtraCorsHeaders(string $endpoint, string $expectedAllowedMethods): void { $allowedHeaders = 'Authorization'; @@ -69,7 +65,7 @@ class CorsTest extends ApiTestCase self::assertEquals($allowedHeaders, $resp->getHeaderLine('Access-Control-Allow-Headers')); } - public function providePreflightEndpoints(): iterable + public static function providePreflightEndpoints(): iterable { yield 'invalid route' => ['/foo/bar', 'GET,POST,PUT,PATCH,DELETE']; // TODO This won't work with multi-segment yield 'short URLs route' => ['/short-urls', 'GET,POST']; diff --git a/module/Rest/test-api/Middleware/ImplicitOptionsTest.php b/module/Rest/test-api/Middleware/ImplicitOptionsTest.php index f9f140c2..e885e599 100644 --- a/module/Rest/test-api/Middleware/ImplicitOptionsTest.php +++ b/module/Rest/test-api/Middleware/ImplicitOptionsTest.php @@ -4,13 +4,14 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Rest\Middleware; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; use function explode; class ImplicitOptionsTest extends ApiTestCase { - /** @test */ + #[Test] public function optionsRequestsReturnEmptyResponse(): void { $resp = $this->callApi(self::METHOD_OPTIONS, '/short-urls'); @@ -19,7 +20,7 @@ class ImplicitOptionsTest extends ApiTestCase self::assertEmpty((string) $resp->getBody()); } - /** @test */ + #[Test] public function optionsRequestsReturnAllowedMethodsForEndpoint(): void { $resp = $this->callApi(self::METHOD_OPTIONS, '/short-urls'); diff --git a/module/Rest/test-api/Utils/NotFoundUrlHelpersTrait.php b/module/Rest/test-api/Utils/NotFoundUrlHelpersTrait.php index 1c415208..9645f707 100644 --- a/module/Rest/test-api/Utils/NotFoundUrlHelpersTrait.php +++ b/module/Rest/test-api/Utils/NotFoundUrlHelpersTrait.php @@ -11,7 +11,7 @@ use function sprintf; trait NotFoundUrlHelpersTrait { - public function provideInvalidUrls(): iterable + public static function provideInvalidUrls(): iterable { yield 'invalid shortcode' => ['invalid', null, 'No URL found with short code "invalid"', 'valid_api_key']; yield 'invalid shortcode without domain' => [ diff --git a/module/Rest/test-db/ApiKey/Repository/ApiKeyRepositoryTest.php b/module/Rest/test-db/ApiKey/Repository/ApiKeyRepositoryTest.php index ae6ab0a0..86db9176 100644 --- a/module/Rest/test-db/ApiKey/Repository/ApiKeyRepositoryTest.php +++ b/module/Rest/test-db/ApiKey/Repository/ApiKeyRepositoryTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioDbTest\Shlink\Rest\ApiKey\Repository; +use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\Rest\ApiKey\Repository\ApiKeyRepository; use Shlinkio\Shlink\Rest\Entity\ApiKey; use Shlinkio\Shlink\TestUtils\DbTest\DatabaseTestCase; @@ -17,7 +18,7 @@ class ApiKeyRepositoryTest extends DatabaseTestCase $this->repo = $this->getEntityManager()->getRepository(ApiKey::class); } - /** @test */ + #[Test] public function initialApiKeyIsCreatedOnlyOfNoApiKeysExistYet(): void { self::assertCount(0, $this->repo->findAll()); diff --git a/module/Rest/test/Action/Domain/DomainRedirectsActionTest.php b/module/Rest/test/Action/Domain/DomainRedirectsActionTest.php index df5fed43..e203fe11 100644 --- a/module/Rest/test/Action/Domain/DomainRedirectsActionTest.php +++ b/module/Rest/test/Action/Domain/DomainRedirectsActionTest.php @@ -6,6 +6,8 @@ namespace ShlinkioTest\Shlink\Rest\Action\Domain; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Config\NotFoundRedirects; @@ -29,10 +31,7 @@ class DomainRedirectsActionTest extends TestCase $this->action = new DomainRedirectsAction($this->domainService); } - /** - * @test - * @dataProvider provideInvalidBodies - */ + #[Test, DataProvider('provideInvalidBodies')] public function invalidDataThrowsException(array $body): void { $request = ServerRequestFactory::fromGlobals()->withParsedBody($body); @@ -44,17 +43,14 @@ class DomainRedirectsActionTest extends TestCase $this->action->handle($request); } - public function provideInvalidBodies(): iterable + public static function provideInvalidBodies(): iterable { yield 'no domain' => [[]]; yield 'empty domain' => [['domain' => '']]; yield 'invalid domain' => [['domain' => '192.168.1.20']]; } - /** - * @test - * @dataProvider provideDomainsAndRedirects - */ + #[Test, DataProvider('provideDomainsAndRedirects')] public function domainIsFetchedAndUsedToGetItConfigured( Domain $domain, array $redirects, @@ -91,7 +87,7 @@ class DomainRedirectsActionTest extends TestCase self::assertEquals($expectedResult, $payload->jsonSerialize()); } - public function provideDomainsAndRedirects(): iterable + public static function provideDomainsAndRedirects(): iterable { yield 'full overwrite' => [Domain::withAuthority(''), [ DomainRedirectsInputFilter::BASE_URL_REDIRECT => 'foo', diff --git a/module/Rest/test/Action/Domain/ListDomainsActionTest.php b/module/Rest/test/Action/Domain/ListDomainsActionTest.php index ac31cd0e..41906539 100644 --- a/module/Rest/test/Action/Domain/ListDomainsActionTest.php +++ b/module/Rest/test/Action/Domain/ListDomainsActionTest.php @@ -6,6 +6,7 @@ namespace ShlinkioTest\Shlink\Rest\Action\Domain; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Config\NotFoundRedirects; @@ -29,7 +30,7 @@ class ListDomainsActionTest extends TestCase $this->action = new ListDomainsAction($this->domainService, $this->options); } - /** @test */ + #[Test] public function domainsAreProperlyListed(): void { $apiKey = ApiKey::create(); diff --git a/module/Rest/test/Action/Domain/Request/DomainRedirectsRequestTest.php b/module/Rest/test/Action/Domain/Request/DomainRedirectsRequestTest.php index 51509047..89b93b80 100644 --- a/module/Rest/test/Action/Domain/Request/DomainRedirectsRequestTest.php +++ b/module/Rest/test/Action/Domain/Request/DomainRedirectsRequestTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Rest\Action\Domain\Request; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Config\NotFoundRedirectConfigInterface; use Shlinkio\Shlink\Core\Exception\ValidationException; @@ -12,26 +14,20 @@ use Shlinkio\Shlink\Rest\Action\Domain\Request\DomainRedirectsRequest; class DomainRedirectsRequestTest extends TestCase { - /** - * @test - * @dataProvider provideInvalidData - */ + #[Test, DataProvider('provideInvalidData')] public function throwsExceptionWhenCreatingWithInvalidData(array $data): void { $this->expectException(ValidationException::class); DomainRedirectsRequest::fromRawData($data); } - public function provideInvalidData(): iterable + public static function provideInvalidData(): iterable { yield 'missing domain' => [[]]; yield 'invalid domain' => [['domain' => 'foo:bar:baz']]; } - /** - * @test - * @dataProvider provideValidData - */ + #[Test, DataProvider('provideValidData')] public function isProperlyCastToNotFoundRedirects( array $data, ?NotFoundRedirectConfigInterface $defaults, @@ -49,7 +45,7 @@ class DomainRedirectsRequestTest extends TestCase self::assertEquals($expectedInvalidShortUrlRedirect, $notFound->invalidShortUrlRedirect); } - public function provideValidData(): iterable + public static function provideValidData(): iterable { yield 'no values' => [['domain' => 'foo'], null, 'foo', null, null, null]; yield 'some values' => [['domain' => 'foo', 'regular404Redirect' => 'bar'], null, 'foo', null, 'bar', null]; diff --git a/module/Rest/test/Action/HealthActionTest.php b/module/Rest/test/Action/HealthActionTest.php index 4ce00578..59075646 100644 --- a/module/Rest/test/Action/HealthActionTest.php +++ b/module/Rest/test/Action/HealthActionTest.php @@ -11,6 +11,7 @@ use Doctrine\ORM\EntityManagerInterface; use Exception; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequest; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Options\AppOptions; @@ -34,7 +35,7 @@ class HealthActionTest extends TestCase $this->action = new HealthAction($em, new AppOptions(version: '1.2.3')); } - /** @test */ + #[Test] public function passResponseIsReturnedWhenDummyQuerySucceeds(): void { $this->conn->expects($this->once())->method('executeQuery')->willReturn($this->createMock(Result::class)); @@ -53,7 +54,7 @@ class HealthActionTest extends TestCase self::assertEquals('application/health+json', $resp->getHeaderLine('Content-type')); } - /** @test */ + #[Test] public function failResponseIsReturnedWhenDummyQueryThrowsException(): void { $this->conn->expects($this->once())->method('executeQuery')->willThrowException(new Exception()); diff --git a/module/Rest/test/Action/MercureInfoActionTest.php b/module/Rest/test/Action/MercureInfoActionTest.php index ada836c1..ce4ad04f 100644 --- a/module/Rest/test/Action/MercureInfoActionTest.php +++ b/module/Rest/test/Action/MercureInfoActionTest.php @@ -7,6 +7,8 @@ namespace ShlinkioTest\Shlink\Rest\Action; use Cake\Chronos\Chronos; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Common\Mercure\JwtProviderInterface; @@ -22,10 +24,7 @@ class MercureInfoActionTest extends TestCase $this->provider = $this->createMock(JwtProviderInterface::class); } - /** - * @test - * @dataProvider provideNoHostConfigs - */ + #[Test, DataProvider('provideNoHostConfigs')] public function throwsExceptionWhenConfigDoesNotHavePublicHost(array $mercureConfig): void { $this->provider->expects($this->never())->method('buildSubscriptionToken'); @@ -37,7 +36,7 @@ class MercureInfoActionTest extends TestCase $action->handle(ServerRequestFactory::fromGlobals()); } - public function provideNoHostConfigs(): iterable + public static function provideNoHostConfigs(): iterable { yield 'host not defined' => [[]]; yield 'host is null' => [['public_hub_url' => null]]; @@ -49,10 +48,7 @@ class MercureInfoActionTest extends TestCase yield 'days defined' => [['public_hub_url' => 'http://foobar.com', 'jwt_days_duration' => 20]]; } - /** - * @test - * @dataProvider provideDays - */ + #[Test, DataProvider('provideDays')] public function returnsExpectedInfoWhenEverythingIsOk(?int $days): void { $this->provider->expects($this->once())->method('buildSubscriptionToken')->willReturn('abc.123'); @@ -76,7 +72,7 @@ class MercureInfoActionTest extends TestCase ); } - public function provideDays(): iterable + public static function provideDays(): iterable { yield 'days not defined' => [null]; yield 'days defined' => [10]; diff --git a/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php index 15ce5389..acaf8df0 100644 --- a/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php @@ -8,6 +8,8 @@ use Cake\Chronos\Chronos; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequest; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Common\Rest\DataTransformerInterface; @@ -33,7 +35,7 @@ class CreateShortUrlActionTest extends TestCase $this->action = new CreateShortUrlAction($this->urlShortener, $this->transformer, new UrlShortenerOptions()); } - /** @test */ + #[Test] public function properShortcodeConversionReturnsData(): void { $apiKey = ApiKey::create(); @@ -66,10 +68,7 @@ class CreateShortUrlActionTest extends TestCase self::assertEquals('stringified_short_url', $payload['shortUrl']); } - /** - * @test - * @dataProvider provideInvalidDomains - */ + #[Test, DataProvider('provideInvalidDomains')] public function anInvalidDomainReturnsError(string $domain): void { $this->urlShortener->expects($this->never())->method('shorten'); @@ -85,7 +84,7 @@ class CreateShortUrlActionTest extends TestCase $this->action->handle($request); } - public function provideInvalidDomains(): iterable + public static function provideInvalidDomains(): iterable { yield ['localhost:80000']; yield ['127.0.0.1']; diff --git a/module/Rest/test/Action/ShortUrl/DeleteShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/DeleteShortUrlActionTest.php index d68e3608..f8411f47 100644 --- a/module/Rest/test/Action/ShortUrl/DeleteShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/DeleteShortUrlActionTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Rest\Action\ShortUrl; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\ShortUrl\DeleteShortUrlServiceInterface; @@ -22,7 +23,7 @@ class DeleteShortUrlActionTest extends TestCase $this->action = new DeleteShortUrlAction($this->service); } - /** @test */ + #[Test] public function emptyResponseIsReturnedIfProperlyDeleted(): void { $apiKey = ApiKey::create(); diff --git a/module/Rest/test/Action/ShortUrl/EditShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/EditShortUrlActionTest.php index ac788fa7..dd7a0e14 100644 --- a/module/Rest/test/Action/ShortUrl/EditShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/EditShortUrlActionTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Rest\Action\ShortUrl; use Laminas\Diactoros\ServerRequest; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\ValidationException; @@ -28,7 +29,7 @@ class EditShortUrlActionTest extends TestCase )); } - /** @test */ + #[Test] public function invalidDataThrowsError(): void { $request = (new ServerRequest())->withParsedBody([ @@ -41,7 +42,7 @@ class EditShortUrlActionTest extends TestCase $this->action->handle($request); } - /** @test */ + #[Test] public function correctShortCodeReturnsSuccess(): void { $request = (new ServerRequest())->withAttribute('shortCode', 'abc123') diff --git a/module/Rest/test/Action/ShortUrl/ListShortUrlsActionTest.php b/module/Rest/test/Action/ShortUrl/ListShortUrlsActionTest.php index 329c9717..d372d692 100644 --- a/module/Rest/test/Action/ShortUrl/ListShortUrlsActionTest.php +++ b/module/Rest/test/Action/ShortUrl/ListShortUrlsActionTest.php @@ -8,6 +8,8 @@ use Cake\Chronos\Chronos; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequestFactory; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Common\Paginator\Paginator; @@ -35,10 +37,7 @@ class ListShortUrlsActionTest extends TestCase )); } - /** - * @test - * @dataProvider provideFilteringData - */ + #[Test, DataProvider('provideFilteringData')] public function properListReturnsSuccessResponse( array $query, int $expectedPage, @@ -70,7 +69,7 @@ class ListShortUrlsActionTest extends TestCase self::assertEquals(200, $response->getStatusCode()); } - public function provideFilteringData(): iterable + public static function provideFilteringData(): iterable { yield [[], 1, null, [], null]; yield [['page' => 10], 10, null, [], null]; diff --git a/module/Rest/test/Action/ShortUrl/ResolveShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/ResolveShortUrlActionTest.php index c7d6fd26..0576fd52 100644 --- a/module/Rest/test/Action/ShortUrl/ResolveShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/ResolveShortUrlActionTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Rest\Action\ShortUrl; use Laminas\Diactoros\ServerRequest; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; @@ -28,7 +29,7 @@ class ResolveShortUrlActionTest extends TestCase )); } - /** @test */ + #[Test] public function correctShortCodeReturnsSuccess(): void { $shortCode = 'abc123'; diff --git a/module/Rest/test/Action/ShortUrl/SingleStepCreateShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/SingleStepCreateShortUrlActionTest.php index 42c185c9..d343a3cd 100644 --- a/module/Rest/test/Action/ShortUrl/SingleStepCreateShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/SingleStepCreateShortUrlActionTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Rest\Action\ShortUrl; use Laminas\Diactoros\ServerRequest; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Common\Rest\DataTransformerInterface; @@ -33,7 +34,7 @@ class SingleStepCreateShortUrlActionTest extends TestCase ); } - /** @test */ + #[Test] public function properDataIsPassedWhenGeneratingShortCode(): void { $apiKey = ApiKey::create(); diff --git a/module/Rest/test/Action/Tag/DeleteTagsActionTest.php b/module/Rest/test/Action/Tag/DeleteTagsActionTest.php index 63d30c4b..5d036097 100644 --- a/module/Rest/test/Action/Tag/DeleteTagsActionTest.php +++ b/module/Rest/test/Action/Tag/DeleteTagsActionTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Rest\Action\Tag; use Laminas\Diactoros\ServerRequest; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Tag\TagServiceInterface; @@ -22,10 +24,7 @@ class DeleteTagsActionTest extends TestCase $this->action = new DeleteTagsAction($this->tagService); } - /** - * @test - * @dataProvider provideTags - */ + #[Test, DataProvider('provideTags')] public function processDelegatesIntoService(?array $tags): void { $request = (new ServerRequest()) @@ -41,7 +40,7 @@ class DeleteTagsActionTest extends TestCase self::assertEquals(204, $response->getStatusCode()); } - public function provideTags(): iterable + public static function provideTags(): iterable { yield 'three tags' => [['foo', 'bar', 'baz']]; yield 'two tags' => [['some', 'thing']]; diff --git a/module/Rest/test/Action/Tag/ListTagsActionTest.php b/module/Rest/test/Action/Tag/ListTagsActionTest.php index dc4c2c06..447e8331 100644 --- a/module/Rest/test/Action/Tag/ListTagsActionTest.php +++ b/module/Rest/test/Action/Tag/ListTagsActionTest.php @@ -7,6 +7,8 @@ namespace ShlinkioTest\Shlink\Rest\Action\Tag; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequestFactory; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; @@ -30,10 +32,7 @@ class ListTagsActionTest extends TestCase $this->action = new ListTagsAction($this->tagService); } - /** - * @test - * @dataProvider provideNoStatsQueries - */ + #[Test, DataProvider('provideNoStatsQueries')] public function returnsBaseDataWhenStatsAreNotRequested(array $query): void { $tags = [new Tag('foo'), new Tag('bar')]; @@ -61,14 +60,14 @@ class ListTagsActionTest extends TestCase ], $payload); } - public function provideNoStatsQueries(): iterable + public static function provideNoStatsQueries(): iterable { yield 'no query' => [[]]; yield 'withStats is false' => [['withStats' => 'withStats']]; yield 'withStats is something else' => [['withStats' => 'foo']]; } - /** @test */ + #[Test] public function returnsStatsWhenRequested(): void { $stats = [ diff --git a/module/Rest/test/Action/Tag/TagsStatsActionTest.php b/module/Rest/test/Action/Tag/TagsStatsActionTest.php index 0694e7bf..e1664f6f 100644 --- a/module/Rest/test/Action/Tag/TagsStatsActionTest.php +++ b/module/Rest/test/Action/Tag/TagsStatsActionTest.php @@ -7,6 +7,7 @@ namespace ShlinkioTest\Shlink\Rest\Action\Tag; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequestFactory; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; @@ -29,7 +30,7 @@ class TagsStatsActionTest extends TestCase $this->action = new TagsStatsAction($this->tagService); } - /** @test */ + #[Test] public function returnsTagsStatsWhenRequested(): void { $stats = [ diff --git a/module/Rest/test/Action/Tag/UpdateTagActionTest.php b/module/Rest/test/Action/Tag/UpdateTagActionTest.php index d08d00e2..73575baf 100644 --- a/module/Rest/test/Action/Tag/UpdateTagActionTest.php +++ b/module/Rest/test/Action/Tag/UpdateTagActionTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Rest\Action\Tag; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; @@ -26,10 +28,7 @@ class UpdateTagActionTest extends TestCase $this->action = new UpdateTagAction($this->tagService); } - /** - * @test - * @dataProvider provideParams - */ + #[Test, DataProvider('provideParams')] public function whenInvalidParamsAreProvidedAnErrorIsReturned(array $bodyParams): void { $request = $this->requestWithApiKey()->withParsedBody($bodyParams); @@ -39,14 +38,14 @@ class UpdateTagActionTest extends TestCase $this->action->handle($request); } - public function provideParams(): iterable + public static function provideParams(): iterable { yield 'old name only' => [['oldName' => 'foo']]; yield 'new name only' => [['newName' => 'foo']]; yield 'no params' => [[]]; } - /** @test */ + #[Test] public function correctInvocationRenamesTag(): void { $request = $this->requestWithApiKey()->withParsedBody([ diff --git a/module/Rest/test/Action/Visit/DomainVisitsActionTest.php b/module/Rest/test/Action/Visit/DomainVisitsActionTest.php index e4b714e4..a6d64bd2 100644 --- a/module/Rest/test/Action/Visit/DomainVisitsActionTest.php +++ b/module/Rest/test/Action/Visit/DomainVisitsActionTest.php @@ -6,6 +6,8 @@ namespace ShlinkioTest\Shlink\Rest\Action\Visit; use Laminas\Diactoros\ServerRequestFactory; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Common\Paginator\Paginator; @@ -25,10 +27,7 @@ class DomainVisitsActionTest extends TestCase $this->action = new DomainVisitsAction($this->visitsHelper, 'the_default.com'); } - /** - * @test - * @dataProvider provideDomainAuthorities - */ + #[Test, DataProvider('provideDomainAuthorities')] public function providingCorrectDomainReturnsVisits(string $providedDomain, string $expectedDomain): void { $apiKey = ApiKey::create(); @@ -46,7 +45,7 @@ class DomainVisitsActionTest extends TestCase self::assertEquals(200, $response->getStatusCode()); } - public function provideDomainAuthorities(): iterable + public static function provideDomainAuthorities(): iterable { yield 'no default domain' => ['foo.com', 'foo.com']; yield 'default domain' => ['the_default.com', 'DEFAULT']; diff --git a/module/Rest/test/Action/Visit/GlobalVisitsActionTest.php b/module/Rest/test/Action/Visit/GlobalVisitsActionTest.php index bd078eaa..e3be1b7c 100644 --- a/module/Rest/test/Action/Visit/GlobalVisitsActionTest.php +++ b/module/Rest/test/Action/Visit/GlobalVisitsActionTest.php @@ -6,6 +6,7 @@ namespace ShlinkioTest\Shlink\Rest\Action\Visit; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Visit\Model\VisitsStats; @@ -24,7 +25,7 @@ class GlobalVisitsActionTest extends TestCase $this->action = new GlobalVisitsAction($this->helper); } - /** @test */ + #[Test] public function statsAreReturnedFromHelper(): void { $apiKey = ApiKey::create(); diff --git a/module/Rest/test/Action/Visit/NonOrphanVisitsActionTest.php b/module/Rest/test/Action/Visit/NonOrphanVisitsActionTest.php index 9065d318..b98c9cb7 100644 --- a/module/Rest/test/Action/Visit/NonOrphanVisitsActionTest.php +++ b/module/Rest/test/Action/Visit/NonOrphanVisitsActionTest.php @@ -7,6 +7,7 @@ namespace ShlinkioTest\Shlink\Rest\Action\Visit; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequestFactory; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Common\Paginator\Paginator; @@ -26,7 +27,7 @@ class NonOrphanVisitsActionTest extends TestCase $this->action = new NonOrphanVisitsAction($this->visitsHelper); } - /** @test */ + #[Test] public function requestIsHandled(): void { $apiKey = ApiKey::create(); diff --git a/module/Rest/test/Action/Visit/OrphanVisitsActionTest.php b/module/Rest/test/Action/Visit/OrphanVisitsActionTest.php index 6facfb1c..f4a22caa 100644 --- a/module/Rest/test/Action/Visit/OrphanVisitsActionTest.php +++ b/module/Rest/test/Action/Visit/OrphanVisitsActionTest.php @@ -7,6 +7,7 @@ namespace ShlinkioTest\Shlink\Rest\Action\Visit; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequestFactory; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Common\Paginator\Paginator; @@ -33,7 +34,7 @@ class OrphanVisitsActionTest extends TestCase $this->action = new OrphanVisitsAction($this->visitsHelper, $this->orphanVisitTransformer); } - /** @test */ + #[Test] public function requestIsHandled(): void { $visitor = Visitor::emptyInstance(); diff --git a/module/Rest/test/Action/Visit/ShortUrlVisitsActionTest.php b/module/Rest/test/Action/Visit/ShortUrlVisitsActionTest.php index b9c92d6c..9130284d 100644 --- a/module/Rest/test/Action/Visit/ShortUrlVisitsActionTest.php +++ b/module/Rest/test/Action/Visit/ShortUrlVisitsActionTest.php @@ -7,6 +7,7 @@ namespace ShlinkioTest\Shlink\Rest\Action\Visit; use Cake\Chronos\Chronos; use Laminas\Diactoros\ServerRequestFactory; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; @@ -29,7 +30,7 @@ class ShortUrlVisitsActionTest extends TestCase $this->action = new ShortUrlVisitsAction($this->visitsHelper); } - /** @test */ + #[Test] public function providingCorrectShortCodeReturnsVisits(): void { $shortCode = 'abc123'; @@ -43,7 +44,7 @@ class ShortUrlVisitsActionTest extends TestCase self::assertEquals(200, $response->getStatusCode()); } - /** @test */ + #[Test] public function paramsAreReadFromQuery(): void { $shortCode = 'abc123'; diff --git a/module/Rest/test/Action/Visit/TagVisitsActionTest.php b/module/Rest/test/Action/Visit/TagVisitsActionTest.php index 1d5b9447..873ac058 100644 --- a/module/Rest/test/Action/Visit/TagVisitsActionTest.php +++ b/module/Rest/test/Action/Visit/TagVisitsActionTest.php @@ -6,6 +6,7 @@ namespace ShlinkioTest\Shlink\Rest\Action\Visit; use Laminas\Diactoros\ServerRequestFactory; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Common\Paginator\Paginator; @@ -25,7 +26,7 @@ class TagVisitsActionTest extends TestCase $this->action = new TagVisitsAction($this->visitsHelper); } - /** @test */ + #[Test] public function providingCorrectTagReturnsVisits(): void { $tag = 'foo'; diff --git a/module/Rest/test/ApiKey/InitialApiKeyDelegatorTest.php b/module/Rest/test/ApiKey/InitialApiKeyDelegatorTest.php index cf32ba10..9b6edff6 100644 --- a/module/Rest/test/ApiKey/InitialApiKeyDelegatorTest.php +++ b/module/Rest/test/ApiKey/InitialApiKeyDelegatorTest.php @@ -7,6 +7,8 @@ namespace ShlinkioTest\Shlink\Rest\ApiKey; use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManagerInterface; use Mezzio\Application; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; @@ -25,10 +27,7 @@ class InitialApiKeyDelegatorTest extends TestCase $this->container = $this->createMock(ContainerInterface::class); } - /** - * @test - * @dataProvider provideConfigs - */ + #[Test, DataProvider('provideConfigs')] public function apiKeyIsInitializedWhenAppropriate(array $config, int $expectedCalls): void { $app = $this->createMock(Application::class); @@ -48,7 +47,7 @@ class InitialApiKeyDelegatorTest extends TestCase self::assertSame($result, $app); } - public function provideConfigs(): iterable + public static function provideConfigs(): iterable { yield 'no api key' => [[], 0]; yield 'null api key' => [['initial_api_key' => null], 0]; diff --git a/module/Rest/test/ApiKey/Model/RoleDefinitionTest.php b/module/Rest/test/ApiKey/Model/RoleDefinitionTest.php index ac513959..ca3746fe 100644 --- a/module/Rest/test/ApiKey/Model/RoleDefinitionTest.php +++ b/module/Rest/test/ApiKey/Model/RoleDefinitionTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Rest\ApiKey\Model; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Domain\Entity\Domain; use Shlinkio\Shlink\Rest\ApiKey\Model\RoleDefinition; @@ -11,7 +12,7 @@ use Shlinkio\Shlink\Rest\ApiKey\Role; class RoleDefinitionTest extends TestCase { - /** @test */ + #[Test] public function forAuthoredShortUrlsCreatesRoleDefinitionAsExpected(): void { $definition = RoleDefinition::forAuthoredShortUrls(); @@ -20,7 +21,7 @@ class RoleDefinitionTest extends TestCase self::assertEquals([], $definition->meta); } - /** @test */ + #[Test] public function forDomainCreatesRoleDefinitionAsExpected(): void { $domain = Domain::withAuthority('foo.com'); diff --git a/module/Rest/test/ApiKey/RoleTest.php b/module/Rest/test/ApiKey/RoleTest.php index 715b89b8..b572630b 100644 --- a/module/Rest/test/ApiKey/RoleTest.php +++ b/module/Rest/test/ApiKey/RoleTest.php @@ -6,6 +6,8 @@ namespace ShlinkioTest\Shlink\Rest\ApiKey; use Happyr\DoctrineSpecification\Spec; use Happyr\DoctrineSpecification\Specification\Specification; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\ShortUrl\Spec\BelongsToApiKey; use Shlinkio\Shlink\Core\ShortUrl\Spec\BelongsToApiKeyInlined; @@ -17,16 +19,13 @@ use Shlinkio\Shlink\Rest\Entity\ApiKeyRole; class RoleTest extends TestCase { - /** - * @test - * @dataProvider provideRoles - */ + #[Test, DataProvider('provideRoles')] public function returnsExpectedSpec(ApiKeyRole $apiKeyRole, Specification $expected): void { self::assertEquals($expected, Role::toSpec($apiKeyRole)); } - public function provideRoles(): iterable + public static function provideRoles(): iterable { $apiKey = ApiKey::create(); @@ -40,16 +39,13 @@ class RoleTest extends TestCase ]; } - /** - * @test - * @dataProvider provideInlinedRoles - */ + #[Test, DataProvider('provideInlinedRoles')] public function returnsExpectedInlinedSpec(ApiKeyRole $apiKeyRole, Specification $expected): void { self::assertEquals($expected, Role::toInlinedSpec($apiKeyRole)); } - public function provideInlinedRoles(): iterable + public static function provideInlinedRoles(): iterable { $apiKey = ApiKey::create(); @@ -63,48 +59,39 @@ class RoleTest extends TestCase ]; } - /** - * @test - * @dataProvider provideMetasWithDomainId - */ + #[Test, DataProvider('provideMetasWithDomainId')] public function getsExpectedDomainIdFromMeta(array $meta, string $expectedDomainId): void { self::assertEquals($expectedDomainId, Role::domainIdFromMeta($meta)); } - public function provideMetasWithDomainId(): iterable + public static function provideMetasWithDomainId(): iterable { yield 'empty meta' => [[], '-1']; yield 'meta without domain_id' => [['foo' => 'bar'], '-1']; yield 'meta with domain_id' => [['domain_id' => '123'], '123']; } - /** - * @test - * @dataProvider provideMetasWithAuthority - */ + #[Test, DataProvider('provideMetasWithAuthority')] public function getsExpectedAuthorityFromMeta(array $meta, string $expectedAuthority): void { self::assertEquals($expectedAuthority, Role::domainAuthorityFromMeta($meta)); } - public function provideMetasWithAuthority(): iterable + public static function provideMetasWithAuthority(): iterable { yield 'empty meta' => [[], '']; yield 'meta without authority' => [['foo' => 'bar'], '']; yield 'meta with authority' => [['authority' => 'example.com'], 'example.com']; } - /** - * @test - * @dataProvider provideRoleNames - */ + #[Test, DataProvider('provideRoleNames')] public function getsExpectedRoleFriendlyName(Role $role, string $expectedFriendlyName): void { self::assertEquals($expectedFriendlyName, $role->toFriendlyName()); } - public function provideRoleNames(): iterable + public static function provideRoleNames(): iterable { yield Role::AUTHORED_SHORT_URLS->value => [Role::AUTHORED_SHORT_URLS, 'Author only']; yield Role::DOMAIN_SPECIFIC->value => [Role::DOMAIN_SPECIFIC, 'Domain only']; diff --git a/module/Rest/test/ConfigProviderTest.php b/module/Rest/test/ConfigProviderTest.php index 1f7044f9..ee729eb5 100644 --- a/module/Rest/test/ConfigProviderTest.php +++ b/module/Rest/test/ConfigProviderTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Rest; use Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Rest\ConfigProvider; @@ -17,7 +19,7 @@ class ConfigProviderTest extends TestCase $this->configProvider = new ConfigProvider(); } - /** @test */ + #[Test] public function properConfigIsReturned(): void { $config = ($this->configProvider)(); @@ -30,16 +32,13 @@ class ConfigProviderTest extends TestCase self::assertArrayHasKey(ConfigAbstractFactory::class, $config); } - /** - * @test - * @dataProvider provideRoutesConfig - */ + #[Test, DataProvider('provideRoutesConfig')] public function routesAreProperlyPrefixed(array $routes, array $expected): void { self::assertEquals($expected, ConfigProvider::applyRoutesPrefix($routes)); } - public function provideRoutesConfig(): iterable + public static function provideRoutesConfig(): iterable { yield 'health action present' => [ [ diff --git a/module/Rest/test/Exception/BackwardsCompatibleProblemDetailsExceptionTest.php b/module/Rest/test/Exception/BackwardsCompatibleProblemDetailsExceptionTest.php index c63cee71..e51a5ac1 100644 --- a/module/Rest/test/Exception/BackwardsCompatibleProblemDetailsExceptionTest.php +++ b/module/Rest/test/Exception/BackwardsCompatibleProblemDetailsExceptionTest.php @@ -6,6 +6,8 @@ namespace ShlinkioTest\Shlink\Rest\Exception; use Exception; use Mezzio\ProblemDetails\Exception\ProblemDetailsExceptionInterface; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Core\Exception\DeleteShortUrlException; use Shlinkio\Shlink\Core\Exception\DomainNotFoundException; @@ -23,10 +25,7 @@ use Shlinkio\Shlink\Rest\Exception\VerifyAuthenticationException; class BackwardsCompatibleProblemDetailsExceptionTest extends TestCase { - /** - * @test - * @dataProvider provideTypes - */ + #[Test, DataProvider('provideTypes')] public function typeIsRemappedOnWrappedException( string $wrappedType, string $expectedType, @@ -94,7 +93,7 @@ class BackwardsCompatibleProblemDetailsExceptionTest extends TestCase } } - public function provideTypes(): iterable + public static function provideTypes(): iterable { yield ['foo', 'foo', true]; yield ['bar', 'bar', true]; diff --git a/module/Rest/test/Exception/MissingAuthenticationExceptionTest.php b/module/Rest/test/Exception/MissingAuthenticationExceptionTest.php index ab79ba2f..d3b7aab0 100644 --- a/module/Rest/test/Exception/MissingAuthenticationExceptionTest.php +++ b/module/Rest/test/Exception/MissingAuthenticationExceptionTest.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Rest\Exception; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Rest\Exception\MissingAuthenticationException; @@ -12,10 +14,7 @@ use function sprintf; class MissingAuthenticationExceptionTest extends TestCase { - /** - * @test - * @dataProvider provideExpectedHeaders - */ + #[Test, DataProvider('provideExpectedHeaders')] public function exceptionIsProperlyCreatedFromExpectedHeaders(array $expectedHeaders): void { $expectedMessage = sprintf( @@ -31,7 +30,7 @@ class MissingAuthenticationExceptionTest extends TestCase self::assertEquals(['expectedHeaders' => $expectedHeaders], $e->getAdditionalData()); } - public function provideExpectedHeaders(): iterable + public static function provideExpectedHeaders(): iterable { yield [['foo', 'bar']]; yield [['something']]; @@ -39,10 +38,7 @@ class MissingAuthenticationExceptionTest extends TestCase yield [['foo', 'bar', 'baz']]; } - /** - * @test - * @dataProvider provideExpectedParam - */ + #[Test, DataProvider('provideExpectedParam')] public function exceptionIsProperlyCreatedFromExpectedQueryParam(string $param): void { $expectedMessage = sprintf('Expected authentication to be provided in "%s" query param', $param); @@ -55,7 +51,7 @@ class MissingAuthenticationExceptionTest extends TestCase self::assertEquals(['param' => $param], $e->getAdditionalData()); } - public function provideExpectedParam(): iterable + public static function provideExpectedParam(): iterable { yield ['foo']; yield ['bar']; diff --git a/module/Rest/test/Exception/VerifyAuthenticationExceptionTest.php b/module/Rest/test/Exception/VerifyAuthenticationExceptionTest.php index 3221041d..3307c28d 100644 --- a/module/Rest/test/Exception/VerifyAuthenticationExceptionTest.php +++ b/module/Rest/test/Exception/VerifyAuthenticationExceptionTest.php @@ -4,12 +4,13 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Rest\Exception; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Rest\Exception\VerifyAuthenticationException; class VerifyAuthenticationExceptionTest extends TestCase { - /** @test */ + #[Test] public function createsExpectedExceptionForInvalidApiKey(): void { $e = VerifyAuthenticationException::forInvalidApiKey(); diff --git a/module/Rest/test/Middleware/AuthenticationMiddlewareTest.php b/module/Rest/test/Middleware/AuthenticationMiddlewareTest.php index 62ca5aef..99a8b3e6 100644 --- a/module/Rest/test/Middleware/AuthenticationMiddlewareTest.php +++ b/module/Rest/test/Middleware/AuthenticationMiddlewareTest.php @@ -10,6 +10,8 @@ use Laminas\Diactoros\ServerRequest; use Laminas\Diactoros\ServerRequestFactory; use Mezzio\Router\Route; use Mezzio\Router\RouteResult; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; @@ -42,10 +44,7 @@ class AuthenticationMiddlewareTest extends TestCase $this->handler = $this->createMock(RequestHandlerInterface::class); } - /** - * @test - * @dataProvider provideRequestsWithoutAuth - */ + #[Test, DataProvider('provideRequestsWithoutAuth')] public function someSituationsFallbackToNextMiddleware(ServerRequestInterface $request): void { $this->handler->expects($this->once())->method('handle')->with($request)->willReturn(new Response()); @@ -54,9 +53,9 @@ class AuthenticationMiddlewareTest extends TestCase $this->middleware->process($request, $this->handler); } - public function provideRequestsWithoutAuth(): iterable + public static function provideRequestsWithoutAuth(): iterable { - $dummyMiddleware = $this->getDummyMiddleware(); + $dummyMiddleware = self::getDummyMiddleware(); yield 'no route result' => [new ServerRequest()]; yield 'failure route result' => [(new ServerRequest())->withAttribute( @@ -75,10 +74,7 @@ class AuthenticationMiddlewareTest extends TestCase )->withMethod(RequestMethodInterface::METHOD_OPTIONS)]; } - /** - * @test - * @dataProvider provideRequestsWithoutApiKey - */ + #[Test, DataProvider('provideRequestsWithoutApiKey')] public function throwsExceptionWhenNoApiKeyIsProvided( ServerRequestInterface $request, string $expectedMessage, @@ -91,11 +87,11 @@ class AuthenticationMiddlewareTest extends TestCase $this->middleware->process($request, $this->handler); } - public function provideRequestsWithoutApiKey(): iterable + public static function provideRequestsWithoutApiKey(): iterable { $baseRequest = fn (string $routeName) => ServerRequestFactory::fromGlobals()->withAttribute( RouteResult::class, - RouteResult::fromRoute(new Route($routeName, $this->getDummyMiddleware())), // @phpstan-ignore-line + RouteResult::fromRoute(new Route($routeName, self::getDummyMiddleware())), // @phpstan-ignore-line ); $apiKeyMessage = 'Expected one of the following authentication headers, ["X-Api-Key"], but none were provided'; $queryMessage = 'Expected authentication to be provided in "apiKey" query param'; @@ -109,14 +105,14 @@ class AuthenticationMiddlewareTest extends TestCase ]; } - /** @test */ + #[Test] public function throwsExceptionWhenProvidedApiKeyIsInvalid(): void { $apiKey = 'abc123'; $request = ServerRequestFactory::fromGlobals() ->withAttribute( RouteResult::class, - RouteResult::fromRoute(new Route('bar', $this->getDummyMiddleware()), []), + RouteResult::fromRoute(new Route('bar', self::getDummyMiddleware()), []), ) ->withHeader('X-Api-Key', $apiKey); @@ -130,7 +126,7 @@ class AuthenticationMiddlewareTest extends TestCase $this->middleware->process($request, $this->handler); } - /** @test */ + #[Test] public function validApiKeyFallsBackToNextMiddleware(): void { $apiKey = ApiKey::create(); @@ -138,7 +134,7 @@ class AuthenticationMiddlewareTest extends TestCase $request = ServerRequestFactory::fromGlobals() ->withAttribute( RouteResult::class, - RouteResult::fromRoute(new Route('bar', $this->getDummyMiddleware()), []), + RouteResult::fromRoute(new Route('bar', self::getDummyMiddleware()), []), ) ->withHeader('X-Api-Key', $key); @@ -152,7 +148,7 @@ class AuthenticationMiddlewareTest extends TestCase $this->middleware->process($request, $this->handler); } - private function getDummyMiddleware(): MiddlewareInterface + private static function getDummyMiddleware(): MiddlewareInterface { return middleware(fn () => new Response\EmptyResponse()); } diff --git a/module/Rest/test/Middleware/BodyParserMiddlewareTest.php b/module/Rest/test/Middleware/BodyParserMiddlewareTest.php index 429a35ea..fd0d8b7f 100644 --- a/module/Rest/test/Middleware/BodyParserMiddlewareTest.php +++ b/module/Rest/test/Middleware/BodyParserMiddlewareTest.php @@ -8,6 +8,8 @@ use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequest; use Laminas\Diactoros\Stream; use PHPUnit\Framework\Assert; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; @@ -24,10 +26,7 @@ class BodyParserMiddlewareTest extends TestCase $this->middleware = new BodyParserMiddleware(); } - /** - * @test - * @dataProvider provideIgnoredRequestMethods - */ + #[Test, DataProvider('provideIgnoredRequestMethods')] public function requestsFromOtherMethodsJustFallbackToNextMiddleware(string $method): void { $request = $this->createMock(ServerRequestInterface::class); @@ -37,14 +36,14 @@ class BodyParserMiddlewareTest extends TestCase $this->assertHandlingRequestJustFallsBackToNext($request); } - public function provideIgnoredRequestMethods(): iterable + public static function provideIgnoredRequestMethods(): iterable { yield 'GET' => ['GET']; yield 'HEAD' => ['HEAD']; yield 'OPTIONS' => ['OPTIONS']; } - /** @test */ + #[Test] public function requestsWithNonEmptyBodyJustFallbackToNextMiddleware(): void { $request = $this->createMock(ServerRequestInterface::class); @@ -64,7 +63,7 @@ class BodyParserMiddlewareTest extends TestCase $this->middleware->process($request, $nextHandler); } - /** @test */ + #[Test] public function jsonRequestsAreJsonDecoded(): void { $body = new Stream('php://temp', 'wr'); @@ -86,7 +85,7 @@ class BodyParserMiddlewareTest extends TestCase $this->middleware->process($request, $handler); } - /** @test */ + #[Test] public function invalidBodyResultsInException(): void { $body = new Stream('php://temp', 'wr'); diff --git a/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php b/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php index de87f34f..100b146e 100644 --- a/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php +++ b/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php @@ -6,6 +6,8 @@ namespace ShlinkioTest\Shlink\Rest\Middleware; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequest; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Server\RequestHandlerInterface; @@ -22,7 +24,7 @@ class CrossDomainMiddlewareTest extends TestCase $this->handler = $this->createMock(RequestHandlerInterface::class); } - /** @test */ + #[Test] public function nonCrossDomainRequestsAreNotAffected(): void { $originalResponse = (new Response())->withStatus(404); @@ -39,7 +41,7 @@ class CrossDomainMiddlewareTest extends TestCase self::assertArrayNotHasKey('Access-Control-Allow-Headers', $headers); } - /** @test */ + #[Test] public function anyRequestIncludesTheAllowAccessHeader(): void { $originalResponse = new Response(); @@ -56,7 +58,7 @@ class CrossDomainMiddlewareTest extends TestCase self::assertArrayNotHasKey('Access-Control-Allow-Headers', $headers); } - /** @test */ + #[Test] public function optionsRequestIncludesMoreHeaders(): void { $originalResponse = new Response(); @@ -78,10 +80,7 @@ class CrossDomainMiddlewareTest extends TestCase self::assertEquals(204, $response->getStatusCode()); } - /** - * @test - * @dataProvider provideRouteResults - */ + #[Test, DataProvider('provideRouteResults')] public function optionsRequestParsesRouteMatchToDetermineAllowedMethods( ?string $allowHeader, string $expectedAllowedMethods, @@ -100,17 +99,14 @@ class CrossDomainMiddlewareTest extends TestCase self::assertEquals(204, $response->getStatusCode()); } - public function provideRouteResults(): iterable + public static function provideRouteResults(): iterable { yield 'no allow header in response' => [null, 'GET,POST,PUT,PATCH,DELETE']; yield 'allow header in response' => ['POST,GET', 'POST,GET']; yield 'also allow header in response' => ['DELETE,PATCH,PUT', 'DELETE,PATCH,PUT']; } - /** - * @test - * @dataProvider provideMethods - */ + #[Test, DataProvider('provideMethods')] public function expectedStatusCodeIsReturnDependingOnRequestMethod( string $method, int $status, @@ -126,7 +122,7 @@ class CrossDomainMiddlewareTest extends TestCase self::assertEquals($expectedStatus, $response->getStatusCode()); } - public function provideMethods(): iterable + public static function provideMethods(): iterable { yield 'POST 200' => ['POST', 200, 200]; yield 'POST 400' => ['POST', 400, 400]; diff --git a/module/Rest/test/Middleware/EmptyResponseImplicitOptionsMiddlewareFactoryTest.php b/module/Rest/test/Middleware/EmptyResponseImplicitOptionsMiddlewareFactoryTest.php index b2093461..74c06cd5 100644 --- a/module/Rest/test/Middleware/EmptyResponseImplicitOptionsMiddlewareFactoryTest.php +++ b/module/Rest/test/Middleware/EmptyResponseImplicitOptionsMiddlewareFactoryTest.php @@ -6,6 +6,7 @@ namespace ShlinkioTest\Shlink\Rest\Middleware; use Laminas\Diactoros\Response\EmptyResponse; use Mezzio\Router\Middleware\ImplicitOptionsMiddleware; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ResponseFactoryInterface; use ReflectionObject; @@ -20,14 +21,14 @@ class EmptyResponseImplicitOptionsMiddlewareFactoryTest extends TestCase $this->factory = new EmptyResponseImplicitOptionsMiddlewareFactory(); } - /** @test */ + #[Test] public function serviceIsCreated(): void { $instance = ($this->factory)(); self::assertInstanceOf(ImplicitOptionsMiddleware::class, $instance); } - /** @test */ + #[Test] public function responsePrototypeIsEmptyResponse(): void { $instance = ($this->factory)(); diff --git a/module/Rest/test/Middleware/ErrorHandler/BackwardsCompatibleProblemDetailsHandlerTest.php b/module/Rest/test/Middleware/ErrorHandler/BackwardsCompatibleProblemDetailsHandlerTest.php index 40ba6965..78862980 100644 --- a/module/Rest/test/Middleware/ErrorHandler/BackwardsCompatibleProblemDetailsHandlerTest.php +++ b/module/Rest/test/Middleware/ErrorHandler/BackwardsCompatibleProblemDetailsHandlerTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Rest\Middleware\ErrorHandler; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; @@ -24,9 +26,8 @@ class BackwardsCompatibleProblemDetailsHandlerTest extends TestCase /** * @param class-string $expectedException - * @test - * @dataProvider provideExceptions */ + #[Test, DataProvider('provideExceptions')] public function expectedExceptionIsThrownBasedOnTheRequestVersion( ServerRequestInterface $request, Throwable $thrownException, @@ -40,7 +41,7 @@ class BackwardsCompatibleProblemDetailsHandlerTest extends TestCase $this->handler->process($request, $handler); } - public function provideExceptions(): iterable + public static function provideExceptions(): iterable { $baseRequest = ServerRequestFactory::fromGlobals(); diff --git a/module/Rest/test/Middleware/Mercure/NotConfiguredMercureErrorHandlerTest.php b/module/Rest/test/Middleware/Mercure/NotConfiguredMercureErrorHandlerTest.php index 4f576d7d..c1732db0 100644 --- a/module/Rest/test/Middleware/Mercure/NotConfiguredMercureErrorHandlerTest.php +++ b/module/Rest/test/Middleware/Mercure/NotConfiguredMercureErrorHandlerTest.php @@ -7,6 +7,7 @@ namespace ShlinkioTest\Shlink\Rest\Middleware\Mercure; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequestFactory; use Mezzio\ProblemDetails\ProblemDetailsResponseFactory; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Server\RequestHandlerInterface; @@ -29,7 +30,7 @@ class NotConfiguredMercureErrorHandlerTest extends TestCase $this->handler = $this->createMock(RequestHandlerInterface::class); } - /** @test */ + #[Test] public function requestHandlerIsInvokedWhenNotErrorOccurs(): void { $req = ServerRequestFactory::fromGlobals(); @@ -40,7 +41,7 @@ class NotConfiguredMercureErrorHandlerTest extends TestCase $this->middleware->process($req, $this->handler); } - /** @test */ + #[Test] public function exceptionIsParsedToResponse(): void { $req = ServerRequestFactory::fromGlobals(); diff --git a/module/Rest/test/Middleware/ShortUrl/CreateShortUrlContentNegotiationMiddlewareTest.php b/module/Rest/test/Middleware/ShortUrl/CreateShortUrlContentNegotiationMiddlewareTest.php index adfaf43e..c847027c 100644 --- a/module/Rest/test/Middleware/ShortUrl/CreateShortUrlContentNegotiationMiddlewareTest.php +++ b/module/Rest/test/Middleware/ShortUrl/CreateShortUrlContentNegotiationMiddlewareTest.php @@ -7,6 +7,8 @@ namespace ShlinkioTest\Shlink\Rest\Middleware\ShortUrl; use Laminas\Diactoros\Response; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequest; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; @@ -24,7 +26,7 @@ class CreateShortUrlContentNegotiationMiddlewareTest extends TestCase $this->requestHandler = $this->createMock(RequestHandlerInterface::class); } - /** @test */ + #[Test] public function whenNoJsonResponseIsReturnedNoFurtherOperationsArePerformed(): void { $expectedResp = new Response(); @@ -37,11 +39,7 @@ class CreateShortUrlContentNegotiationMiddlewareTest extends TestCase self::assertSame($expectedResp, $resp); } - /** - * @test - * @dataProvider provideData - * @param array $query - */ + #[Test, DataProvider('provideData')] public function properResponseIsReturned(?string $accept, array $query, string $expectedContentType): void { $request = (new ServerRequest())->withQueryParams($query); @@ -58,7 +56,7 @@ class CreateShortUrlContentNegotiationMiddlewareTest extends TestCase self::assertEquals($expectedContentType, $response->getHeaderLine('Content-type')); } - public function provideData(): iterable + public static function provideData(): iterable { yield [null, [], 'application/json']; yield [null, ['format' => 'json'], 'application/json']; @@ -70,11 +68,7 @@ class CreateShortUrlContentNegotiationMiddlewareTest extends TestCase yield ['application/json', ['format' => 'txt'], 'text/plain']; } - /** - * @test - * @dataProvider provideTextBodies - * @param array $json - */ + #[Test, DataProvider('provideTextBodies')] public function properBodyIsReturnedInPlainTextResponses(array $json, string $expectedBody): void { $request = (new ServerRequest())->withQueryParams(['format' => 'txt']); @@ -88,7 +82,7 @@ class CreateShortUrlContentNegotiationMiddlewareTest extends TestCase self::assertEquals($expectedBody, (string) $response->getBody()); } - public function provideTextBodies(): iterable + public static function provideTextBodies(): iterable { yield 'shortUrl key' => [['shortUrl' => 'foobar'], 'foobar']; yield 'error key' => [['error' => 'FOO_BAR'], 'FOO_BAR']; diff --git a/module/Rest/test/Middleware/ShortUrl/DefaultShortCodesLengthMiddlewareTest.php b/module/Rest/test/Middleware/ShortUrl/DefaultShortCodesLengthMiddlewareTest.php index d8fb3092..e6b0c6ec 100644 --- a/module/Rest/test/Middleware/ShortUrl/DefaultShortCodesLengthMiddlewareTest.php +++ b/module/Rest/test/Middleware/ShortUrl/DefaultShortCodesLengthMiddlewareTest.php @@ -7,6 +7,8 @@ namespace ShlinkioTest\Shlink\Rest\Middleware\ShortUrl; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequestFactory; use PHPUnit\Framework\Assert; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; @@ -25,10 +27,7 @@ class DefaultShortCodesLengthMiddlewareTest extends TestCase $this->middleware = new DefaultShortCodesLengthMiddleware(8); } - /** - * @test - * @dataProvider provideBodies - */ + #[Test, DataProvider('provideBodies')] public function defaultValueIsInjectedInBodyWhenNotProvided(array $body, int $expectedLength): void { $request = ServerRequestFactory::fromGlobals()->withParsedBody($body); @@ -45,7 +44,7 @@ class DefaultShortCodesLengthMiddlewareTest extends TestCase $this->middleware->process($request, $this->handler); } - public function provideBodies(): iterable + public static function provideBodies(): iterable { yield 'value provided' => [[ShortUrlInputFilter::SHORT_CODE_LENGTH => 6], 6]; yield 'value not provided' => [[], 8]; diff --git a/module/Rest/test/Middleware/ShortUrl/DropDefaultDomainFromRequestMiddlewareTest.php b/module/Rest/test/Middleware/ShortUrl/DropDefaultDomainFromRequestMiddlewareTest.php index cc3ff21c..e9fceea5 100644 --- a/module/Rest/test/Middleware/ShortUrl/DropDefaultDomainFromRequestMiddlewareTest.php +++ b/module/Rest/test/Middleware/ShortUrl/DropDefaultDomainFromRequestMiddlewareTest.php @@ -7,6 +7,8 @@ namespace ShlinkioTest\Shlink\Rest\Middleware\ShortUrl; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequestFactory; use PHPUnit\Framework\Assert; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; @@ -24,10 +26,7 @@ class DropDefaultDomainFromRequestMiddlewareTest extends TestCase $this->middleware = new DropDefaultDomainFromRequestMiddleware('s.test'); } - /** - * @test - * @dataProvider provideQueryParams - */ + #[Test, DataProvider('provideQueryParams')] public function domainIsDroppedWhenDefaultOneIsProvided(array $providedPayload, array $expectedPayload): void { $req = ServerRequestFactory::fromGlobals()->withQueryParams($providedPayload)->withParsedBody($providedPayload); @@ -43,7 +42,7 @@ class DropDefaultDomainFromRequestMiddlewareTest extends TestCase $this->middleware->process($req, $this->next); } - public function provideQueryParams(): iterable + public static function provideQueryParams(): iterable { yield [[], []]; yield [['foo' => 'bar'], ['foo' => 'bar']]; diff --git a/module/Rest/test/Middleware/ShortUrl/OverrideDomainMiddlewareTest.php b/module/Rest/test/Middleware/ShortUrl/OverrideDomainMiddlewareTest.php index f91e9818..4c578bfb 100644 --- a/module/Rest/test/Middleware/ShortUrl/OverrideDomainMiddlewareTest.php +++ b/module/Rest/test/Middleware/ShortUrl/OverrideDomainMiddlewareTest.php @@ -7,6 +7,8 @@ namespace ShlinkioTest\Shlink\Rest\Middleware\ShortUrl; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequestFactory; use PHPUnit\Framework\Assert; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; @@ -34,7 +36,7 @@ class OverrideDomainMiddlewareTest extends TestCase $this->middleware = new OverrideDomainMiddleware($this->domainService); } - /** @test */ + #[Test] public function nextMiddlewareIsCalledWhenApiKeyDoesNotHaveProperRole(): void { $request = $this->requestWithApiKey(); @@ -48,10 +50,7 @@ class OverrideDomainMiddlewareTest extends TestCase self::assertSame($response, $result); } - /** - * @test - * @dataProvider provideBodies - */ + #[Test, DataProvider('provideBodies')] public function overwritesRequestBodyWhenMethodIsPost(Domain $domain, array $body, array $expectedBody): void { $request = $this->requestWithApiKey()->withMethod('POST')->withParsedBody($body); @@ -70,7 +69,7 @@ class OverrideDomainMiddlewareTest extends TestCase $this->middleware->process($request, $this->handler); } - public function provideBodies(): iterable + public static function provideBodies(): iterable { yield 'no domain provided' => [ Domain::withAuthority('foo.com'), @@ -94,10 +93,7 @@ class OverrideDomainMiddlewareTest extends TestCase ]; } - /** - * @test - * @dataProvider provideMethods - */ + #[Test, DataProvider('provideMethods')] public function setsRequestAttributeWhenMethodIsNotPost(string $method): void { $domain = Domain::withAuthority('something.com'); @@ -117,7 +113,7 @@ class OverrideDomainMiddlewareTest extends TestCase $this->middleware->process($request, $this->handler); } - public function provideMethods(): iterable + public static function provideMethods(): iterable { yield 'GET' => ['GET']; yield 'PUT' => ['PUT']; diff --git a/module/Rest/test/Service/ApiKeyServiceTest.php b/module/Rest/test/Service/ApiKeyServiceTest.php index a592313d..325713be 100644 --- a/module/Rest/test/Service/ApiKeyServiceTest.php +++ b/module/Rest/test/Service/ApiKeyServiceTest.php @@ -7,6 +7,8 @@ namespace ShlinkioTest\Shlink\Rest\Service; use Cake\Chronos\Chronos; use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityRepository; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Common\Exception\InvalidArgumentException; @@ -30,10 +32,9 @@ class ApiKeyServiceTest extends TestCase } /** - * @test - * @dataProvider provideCreationDate * @param RoleDefinition[] $roles */ + #[Test, DataProvider('provideCreationDate')] public function apiKeyIsProperlyCreated(?Chronos $date, ?string $name, array $roles): void { $this->em->expects($this->once())->method('flush'); @@ -48,7 +49,7 @@ class ApiKeyServiceTest extends TestCase } } - public function provideCreationDate(): iterable + public static function provideCreationDate(): iterable { $domain = Domain::withAuthority(''); $domain->setId('123'); @@ -64,10 +65,7 @@ class ApiKeyServiceTest extends TestCase yield 'empty name' => [null, '', []]; } - /** - * @test - * @dataProvider provideInvalidApiKeys - */ + #[Test, DataProvider('provideInvalidApiKeys')] public function checkReturnsFalseForInvalidApiKeys(?ApiKey $invalidKey): void { $this->repo->expects($this->once())->method('findOneBy')->with(['key' => '12345'])->willReturn($invalidKey); @@ -79,14 +77,14 @@ class ApiKeyServiceTest extends TestCase self::assertSame($invalidKey, $result->apiKey); } - public function provideInvalidApiKeys(): iterable + public static function provideInvalidApiKeys(): iterable { yield 'non-existent api key' => [null]; yield 'disabled api key' => [ApiKey::create()->disable()]; yield 'expired api key' => [ApiKey::fromMeta(ApiKeyMeta::withExpirationDate(Chronos::now()->subDay()))]; } - /** @test */ + #[Test] public function checkReturnsTrueWhenConditionsAreFavorable(): void { $apiKey = ApiKey::create(); @@ -100,7 +98,7 @@ class ApiKeyServiceTest extends TestCase self::assertSame($apiKey, $result->apiKey); } - /** @test */ + #[Test] public function disableThrowsExceptionWhenNoApiKeyIsFound(): void { $this->repo->expects($this->once())->method('findOneBy')->with(['key' => '12345'])->willReturn(null); @@ -111,7 +109,7 @@ class ApiKeyServiceTest extends TestCase $this->service->disable('12345'); } - /** @test */ + #[Test] public function disableReturnsDisabledApiKeyWhenFound(): void { $key = ApiKey::create(); @@ -125,7 +123,7 @@ class ApiKeyServiceTest extends TestCase self::assertSame($key, $returnedKey); } - /** @test */ + #[Test] public function listFindsAllApiKeys(): void { $expectedApiKeys = [ApiKey::create(), ApiKey::create(), ApiKey::create()]; @@ -138,7 +136,7 @@ class ApiKeyServiceTest extends TestCase self::assertEquals($expectedApiKeys, $result); } - /** @test */ + #[Test] public function listEnabledFindsOnlyEnabledApiKeys(): void { $expectedApiKeys = [ApiKey::create(), ApiKey::create(), ApiKey::create()]; diff --git a/phpunit-api.xml b/phpunit-api.xml index 6dd527de..62ba2179 100644 --- a/phpunit-api.xml +++ b/phpunit-api.xml @@ -4,6 +4,7 @@ xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" bootstrap="./config/test/bootstrap_api_tests.php" colors="true" + cacheDirectory="build/.phpunit/api-tests.cache" > @@ -11,7 +12,7 @@ - + ./module/Core/src ./module/Rest/src diff --git a/phpunit-cli.xml b/phpunit-cli.xml index 49ba781e..1a129b78 100644 --- a/phpunit-cli.xml +++ b/phpunit-cli.xml @@ -4,6 +4,7 @@ xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" bootstrap="./config/test/bootstrap_cli_tests.php" colors="true" + cacheDirectory="build/.phpunit/cli-tests.cache" > @@ -11,7 +12,7 @@ - + ./module/CLI/src ./module/Core/src diff --git a/phpunit-db.xml b/phpunit-db.xml index b2dd8008..0d2f4dd8 100644 --- a/phpunit-db.xml +++ b/phpunit-db.xml @@ -4,6 +4,7 @@ xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" bootstrap="./config/test/bootstrap_db_tests.php" colors="true" + cacheDirectory="build/.phpunit/db-tests.cache" > @@ -11,7 +12,7 @@ - + ./module/*/src/Repository ./module/*/src/**/Repository diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 29c60b6b..29116d0d 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -4,6 +4,7 @@ xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" bootstrap="./vendor/autoload.php" colors="true" + cacheDirectory="build/.phpunit/unit-tests.cache" > @@ -17,7 +18,7 @@ - + ./module/*/src