diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 042ca75b..b59fc892 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -4,12 +4,8 @@ on: pull_request: push: branches: - - '1.x' - '2.x' -env: - SYMFONY_PHPUNIT_DIR: "$HOME/symfony-bridge/.phpunit" - jobs: tests: name: "PHP ${{ matrix.php }} ${{ matrix.mode }}" @@ -22,7 +18,9 @@ jobs: include: - php: '8.1' composer: 2.1.x + phpunit: 10 - php: '8.2' + phpunit: 11 - php: '8.3' - php: '8.4' - php: '8.5' @@ -50,14 +48,18 @@ jobs: - name: "Install dependencies" run: | + if [[ -n "${{ matrix.phpunit }}" ]]; then + composer r --dev --no-update phpunit/phpunit:^${{ matrix.phpunit }} --ansi + fi + if [[ "${{ matrix.phpunit }}" = 10 ]]; then + sed -i 's/ *ignoreIndirectDeprecations="true"//g' phpunit.xml.dist + fi + if [[ "${{ matrix.mode }}" = low-deps ]]; then composer u --prefer-lowest --prefer-stable --ansi - composer u symfony/phpunit-bridge else composer u --ansi fi - - name: "Install PHPUnit" - run: vendor/bin/simple-phpunit install - - - run: vendor/bin/simple-phpunit + - name: "Run tests" + run: vendor/bin/phpunit diff --git a/.gitignore b/.gitignore index 3fe6fc29..ee04b8c2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ /vendor/ /build/ -.phpunit.result.cache +/.phpunit.cache .php_cs.cache composer.lock diff --git a/composer.json b/composer.json index 8fdc1b5c..e5edc984 100644 --- a/composer.json +++ b/composer.json @@ -16,9 +16,9 @@ }, "require-dev": { "composer/composer": "^2.1", + "phpunit/phpunit": "^12.4", "symfony/dotenv": "^6.4|^7.4|^8.0", "symfony/filesystem": "^6.4|^7.4|^8.0", - "symfony/phpunit-bridge": "^6.4|^7.4|^8.0", "symfony/process": "^6.4|^7.4|^8.0" }, "conflict": { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index b8fe65db..940d994c 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,10 +1,10 @@ - - + + ./src/ - + ./tests @@ -12,7 +12,5 @@ - - diff --git a/src/Configurator/DockerComposeConfigurator.php b/src/Configurator/DockerComposeConfigurator.php index 5314aa7f..e1f07c33 100644 --- a/src/Configurator/DockerComposeConfigurator.php +++ b/src/Configurator/DockerComposeConfigurator.php @@ -275,7 +275,9 @@ private function configureDockerCompose(Recipe $recipe, array $config, bool $upd } // Keep end in memory (check break line on previous line) - $endAt[$node] = !$i || '' !== trim($lines[$i - 1]) ? $i : $i - 1; + if (null !== $node) { + $endAt[$node] = !$i || '' !== trim($lines[$i - 1]) ? $i : $i - 1; + } $node = $matches[1]; if (!isset($nodesLines[$node])) { $nodesLines[$node] = []; @@ -285,7 +287,9 @@ private function configureDockerCompose(Recipe $recipe, array $config, bool $upd $startAt[$node] = $i + 1; } } - $endAt[$node] = \count($lines) + 1; + if (null !== $node) { + $endAt[$node] = \count($lines) + 1; + } foreach ($extra as $key => $value) { if (isset($endAt[$key])) { diff --git a/tests/Command/DumpEnvCommandTest.php b/tests/Command/DumpEnvCommandTest.php index c7756a64..13fa0531 100644 --- a/tests/Command/DumpEnvCommandTest.php +++ b/tests/Command/DumpEnvCommandTest.php @@ -13,6 +13,8 @@ use Composer\Config; use Composer\Console\Application; +use PHPUnit\Framework\Attributes\BackupGlobals; +use PHPUnit\Framework\Attributes\RunInSeparateProcess; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Flex\Command\DumpEnvCommand; @@ -82,9 +84,7 @@ public function testEmptyOptionMustIgnoreContent() unlink($envLocal); } - /** - * @backupGlobals enabled - */ + #[BackupGlobals(true)] public function testEnvCanBeReferenced() { @mkdir(FLEX_TEST_DIR); @@ -164,9 +164,7 @@ public function testDoesNotRequireToSpecifyEnvArgumentWhenLocalFileIsPresent() unlink($envLocalPhp); } - /** - * @runInSeparateProcess - */ + #[RunInSeparateProcess] public function testLoadLocalEnvWhenTestEnvIsNotEqual() { @mkdir(FLEX_TEST_DIR); diff --git a/tests/Command/UpdateRecipesCommandTest.php b/tests/Command/UpdateRecipesCommandTest.php index 87d63493..f4bf1247 100644 --- a/tests/Command/UpdateRecipesCommandTest.php +++ b/tests/Command/UpdateRecipesCommandTest.php @@ -52,12 +52,6 @@ protected function tearDown(): void $filesystem->remove(FLEX_TEST_DIR); } - /** - * Skip 7.1, simply because there isn't a newer recipe version available - * that we can easily use to assert. - * - * @requires PHP >= 7.2 - */ public function testCommandUpdatesRecipe() { @mkdir(FLEX_TEST_DIR); diff --git a/tests/Configurator/AddLinesConfiguratorTest.php b/tests/Configurator/AddLinesConfiguratorTest.php index 03602b16..7b567f7f 100644 --- a/tests/Configurator/AddLinesConfiguratorTest.php +++ b/tests/Configurator/AddLinesConfiguratorTest.php @@ -16,6 +16,7 @@ use Composer\Package\Package; use Composer\Repository\InstalledRepositoryInterface; use Composer\Repository\RepositoryManager; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Filesystem\Filesystem; use Symfony\Flex\Configurator\AddLinesConfigurator; @@ -395,9 +396,7 @@ public function testLineProcessedIfRequiredPackageVersionIsRight() ); } - /** - * @dataProvider getUnconfigureTests - */ + #[DataProvider('getUnconfigureTests')] public function testUnconfigure(string $originalContents, string $value, string $expectedContents) { $this->saveFile('assets/app.js', $originalContents); @@ -434,7 +433,7 @@ public function testExpandTargetDirWhenUnconfiguring() ); } - public function getUnconfigureTests() + public static function getUnconfigureTests() { yield 'found_middle' => [ << $originalContents) { @@ -541,7 +538,7 @@ public function testUpdate(array $originalFiles, array $originalConfig, array $n } } - public function getUpdateTests() + public static function getUpdateTests() { $appJsOriginal = <<createMock(Composer::class), diff --git a/tests/Configurator/CopyDirectoryFromPackageConfiguratorTest.php b/tests/Configurator/CopyDirectoryFromPackageConfiguratorTest.php index 4dd9acd5..50671004 100644 --- a/tests/Configurator/CopyDirectoryFromPackageConfiguratorTest.php +++ b/tests/Configurator/CopyDirectoryFromPackageConfiguratorTest.php @@ -15,6 +15,7 @@ use Composer\Installer\InstallationManager; use Composer\IO\IOInterface; use Composer\Package\PackageInterface; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Flex\Configurator\CopyFromPackageConfigurator; use Symfony\Flex\Lock; @@ -57,9 +58,7 @@ public function testConfigureDirectory() } } - /** - * @dataProvider providerTestConfigureDirectoryWithExistingFiles - */ + #[DataProvider('providerTestConfigureDirectoryWithExistingFiles')] public function testConfigureDirectoryWithExistingFiles(bool $force, string $sourceFileContent, string $existingTargetFileContent, string $expectedFinalTargetFileContent) { if (!is_dir($this->sourceDirectory)) { @@ -93,7 +92,7 @@ public function testConfigureDirectoryWithExistingFiles(bool $force, string $sou } } - public function providerTestConfigureDirectoryWithExistingFiles(): array + public static function providerTestConfigureDirectoryWithExistingFiles(): array { return [ [true, 'NEW_CONTENT', 'OLD_CONTENT', 'NEW_CONTENT'], @@ -166,16 +165,16 @@ protected function setUp(): void $package = $this->getMockBuilder(PackageInterface::class)->getMock(); $this->recipe = $this->getMockBuilder(Recipe::class)->disableOriginalConstructor()->getMock(); - $this->recipe->expects($this->exactly(1))->method('getPackage')->willReturn($package); + $this->recipe->expects($this->once())->method('getPackage')->willReturn($package); $installationManager = $this->getMockBuilder(InstallationManager::class)->disableOriginalConstructor()->getMock(); - $installationManager->expects($this->exactly(1)) + $installationManager->expects($this->once()) ->method('getInstallPath') ->with($package) ->willReturn(FLEX_TEST_DIR) ; $this->composer = $this->getMockBuilder(Composer::class)->getMock(); - $this->composer->expects($this->exactly(1)) + $this->composer->expects($this->once()) ->method('getInstallationManager') ->willReturn($installationManager) ; diff --git a/tests/Configurator/CopyFromPackageConfiguratorTest.php b/tests/Configurator/CopyFromPackageConfiguratorTest.php index 5dbc0814..2f1d4f0c 100644 --- a/tests/Configurator/CopyFromPackageConfiguratorTest.php +++ b/tests/Configurator/CopyFromPackageConfiguratorTest.php @@ -39,7 +39,7 @@ public function testNoFilesCopied() mkdir($this->targetDirectory); } file_put_contents($this->targetFile, ''); - $this->io->expects($this->exactly(1))->method('writeError')->with([' Copying files from package']); + $this->io->expects($this->once())->method('writeError')->with([' Copying files from package']); $lock = $this->getMockBuilder(Lock::class)->disableOriginalConstructor()->getMock(); $this->createConfigurator()->configure($this->recipe, [$this->sourceFileRelativePath => $this->targetFileRelativePath], $lock); } @@ -139,7 +139,7 @@ public function testUnconfigure() public function testNoFilesRemoved() { $this->assertFileDoesNotExist($this->targetFile); - $this->io->expects($this->exactly(1))->method('writeError')->with([' Removing files from package']); + $this->io->expects($this->once())->method('writeError')->with([' Removing files from package']); $lock = $this->getMockBuilder(Lock::class)->disableOriginalConstructor()->getMock(); $this->createConfigurator()->unconfigure($this->recipe, [$this->sourceFileRelativePath => $this->targetFileRelativePath], $lock); } @@ -160,16 +160,16 @@ protected function setUp(): void $package = $this->getMockBuilder(PackageInterface::class)->getMock(); $this->recipe = $this->getMockBuilder(Recipe::class)->disableOriginalConstructor()->getMock(); - $this->recipe->expects($this->exactly(1))->method('getPackage')->willReturn($package); + $this->recipe->expects($this->once())->method('getPackage')->willReturn($package); $installationManager = $this->getMockBuilder(InstallationManager::class)->disableOriginalConstructor()->getMock(); - $installationManager->expects($this->exactly(1)) + $installationManager->expects($this->once()) ->method('getInstallPath') ->with($package) ->willReturn(FLEX_TEST_DIR) ; $this->composer = $this->getMockBuilder(Composer::class)->getMock(); - $this->composer->expects($this->exactly(1)) + $this->composer->expects($this->once()) ->method('getInstallationManager') ->willReturn($installationManager) ; diff --git a/tests/Configurator/CopyFromRecipeConfiguratorTest.php b/tests/Configurator/CopyFromRecipeConfiguratorTest.php index d5e50d49..2a26eb2c 100644 --- a/tests/Configurator/CopyFromRecipeConfiguratorTest.php +++ b/tests/Configurator/CopyFromRecipeConfiguratorTest.php @@ -37,7 +37,7 @@ public function testNoFilesCopied() @mkdir($this->targetDirectory, 0777, true); } file_put_contents($this->targetFile, ''); - $this->io->expects($this->exactly(1))->method('writeError')->with([' Copying files from recipe']); + $this->io->expects($this->once())->method('writeError')->with([' Copying files from recipe']); $lock = $this->getMockBuilder(Lock::class)->disableOriginalConstructor()->getMock(); $this->createConfigurator()->configure($this->recipe, [$this->sourceFileRelativePath => $this->targetFileRelativePath], $lock); } @@ -154,7 +154,7 @@ public function testUnconfigure() public function testNoFilesRemoved() { $this->assertFileDoesNotExist($this->targetFile); - $this->io->expects($this->exactly(1))->method('writeError')->with([' Removing files from recipe']); + $this->io->expects($this->once())->method('writeError')->with([' Removing files from recipe']); $lock = $this->getMockBuilder(Lock::class)->disableOriginalConstructor()->getMock(); $this->createConfigurator()->unconfigure($this->recipe, [$this->sourceFileRelativePath => $this->targetFileRelativePath], $lock); } diff --git a/tests/Configurator/DockerComposeConfiguratorTest.php b/tests/Configurator/DockerComposeConfiguratorTest.php index 77bb6fe7..88bab33b 100644 --- a/tests/Configurator/DockerComposeConfiguratorTest.php +++ b/tests/Configurator/DockerComposeConfiguratorTest.php @@ -14,6 +14,7 @@ use Composer\Composer; use Composer\IO\IOInterface; use Composer\Package\RootPackage; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Filesystem\Filesystem; use Symfony\Flex\Configurator\DockerComposeConfigurator; @@ -185,9 +186,7 @@ public static function dockerComposerFileProvider(): iterable yield ['docker-compose.yml']; } - /** - * @dataProvider dockerComposerFileProvider - */ + #[DataProvider('dockerComposerFileProvider')] public function testConfigure(string $fileName) { $dockerComposeFile = FLEX_TEST_DIR."/$fileName"; @@ -232,9 +231,7 @@ public function testNotConfiguredIfConfigSet() $this->assertFileDoesNotExist(FLEX_TEST_DIR.'/docker-compose.yaml'); } - /** - * @dataProvider getInteractiveDockerPreferenceTests - */ + #[DataProvider('getInteractiveDockerPreferenceTests')] public function testPreferenceAskedInteractively(string $userInput, bool $expectedIsConfigured, bool $expectedIsComposerJsonUpdated) { $composerJsonPath = FLEX_TEST_DIR.'/composer.json'; @@ -262,7 +259,7 @@ public function testPreferenceAskedInteractively(string $userInput, bool $expect } } - public function getInteractiveDockerPreferenceTests() + public static function getInteractiveDockerPreferenceTests() { yield 'yes_once' => ['y', true, false]; yield 'no_once' => ['n', false, false]; diff --git a/tests/FlexTest.php b/tests/FlexTest.php index 2e53f3ee..0d6dcc67 100644 --- a/tests/FlexTest.php +++ b/tests/FlexTest.php @@ -32,6 +32,7 @@ use Composer\Semver\Constraint\MatchAllConstraint; use Composer\Util\HttpDownloader; use Composer\Util\Loop; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Flex\Configurator; @@ -123,9 +124,7 @@ public function testActivateLoadsClasses() $this->assertTrue(class_exists(Response::class, false)); } - /** - * @dataProvider getPackagesForAutoDiscovery - */ + #[DataProvider('getPackagesForAutoDiscovery')] public function testBundlesAutoDiscovery(Package $package, array $expectedManifest) { $io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE); @@ -143,7 +142,7 @@ public function testBundlesAutoDiscovery(Package $package, array $expectedManife $flex->install($this->mockFlexEvent()); } - public function getPackagesForAutoDiscovery(): array + public static function getPackagesForAutoDiscovery(): array { $return = []; @@ -328,9 +327,7 @@ public function testInstallWithPackageJsonToSynchronizeSkipped() ); } - /** - * @dataProvider getDataForTestInstallWithoutPackageJsonToSynchronizeSkipped - */ + #[DataProvider('getDataForTestInstallWithoutPackageJsonToSynchronizeSkipped')] public function testInstallWithoutPackageJsonToSynchronizeSkipped(array $extra) { $io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE); @@ -345,7 +342,7 @@ public function testInstallWithoutPackageJsonToSynchronizeSkipped(array $extra) ); } - public function getDataForTestInstallWithoutPackageJsonToSynchronizeSkipped(): array + public static function getDataForTestInstallWithoutPackageJsonToSynchronizeSkipped(): array { return [ 'default_behavior' => [[]], diff --git a/tests/PackageFilterTest.php b/tests/PackageFilterTest.php index 0d076fff..a2ce976c 100644 --- a/tests/PackageFilterTest.php +++ b/tests/PackageFilterTest.php @@ -18,19 +18,18 @@ use Composer\Package\PackageInterface; use Composer\Package\RootPackage; use Composer\Package\RootPackageInterface; +use Composer\Plugin\PrePoolCreateEvent; use Composer\Semver\Constraint\Constraint; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresMethod; use PHPUnit\Framework\TestCase; use Symfony\Flex\Downloader; use Symfony\Flex\PackageFilter; -/** - * @requires function \Composer\Plugin\PrePoolCreateEvent::__construct - */ +#[RequiresMethod(PrePoolCreateEvent::class, '__construct')] class PackageFilterTest extends TestCase { - /** - * @dataProvider provideRemoveLegacyPackages - */ + #[DataProvider('provideRemoveLegacyPackages')] public function testRemoveLegacyPackages(array $expected, array $packages, string $symfonyRequire, array $versions, array $lockedPackages = []) { $downloader = $this->getMockBuilder('Symfony\Flex\Downloader')->disableOriginalConstructor()->getMock(); @@ -89,7 +88,7 @@ private function configToPackage(array $configs) return $packages; } - public function provideRemoveLegacyPackages() + public static function provideRemoveLegacyPackages() { $branchAlias = function ($versionAlias) { return [ diff --git a/tests/PackageJsonSynchronizerTest.php b/tests/PackageJsonSynchronizerTest.php index 702a3881..40976b63 100644 --- a/tests/PackageJsonSynchronizerTest.php +++ b/tests/PackageJsonSynchronizerTest.php @@ -326,14 +326,10 @@ public function testSynchronizeAssetMapperNewPackage() $entrypointPath = $this->tempDir.'/vendor/symfony/new-package/assets/entry.js'; $secondEntrypointPath = $this->tempDir.'/vendor/symfony/new-package/assets/entry2.js'; + $actualArguments = []; $this->scriptExecutor->expects($this->exactly(4)) ->method('execute') - ->withConsecutive( - ['symfony-cmd', 'importmap:require', ['@hotcake/foo@^1.9.0']], - ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]], - ['symfony-cmd', 'importmap:require', ['@symfony/new-package/entry.js', '--path='.$entrypointPath, '--entrypoint']], - ['symfony-cmd', 'importmap:require', ['@symfony/new-package/entry2.js', '--path='.$secondEntrypointPath, '--entrypoint']], - ); + ->willReturnCallback(function (...$arguments) use (&$actualArguments) { $actualArguments[] = $arguments; }); $this->synchronizer->synchronize([ [ @@ -391,6 +387,15 @@ public function testSynchronizeAssetMapperNewPackage() ], json_decode(file_get_contents($this->tempDir.'/assets/controllers.json'), true) ); + + $expectedArguments = [ + ['symfony-cmd', 'importmap:require', ['@hotcake/foo@^1.9.0']], + ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]], + ['symfony-cmd', 'importmap:require', ['@symfony/new-package/entry.js', '--path='.$entrypointPath, '--entrypoint']], + ['symfony-cmd', 'importmap:require', ['@symfony/new-package/entry2.js', '--path='.$secondEntrypointPath, '--entrypoint']], + ]; + + $this->assertSame($expectedArguments, $actualArguments); } public function testSynchronizeAssetMapperUpgradesPackageIfNeeded() @@ -407,14 +412,10 @@ public function testSynchronizeAssetMapperUpgradesPackageIfNeeded() $entrypointPath = $this->tempDir.'/vendor/symfony/new-package/assets/entry.js'; $secondEntrypointPath = $this->tempDir.'/vendor/symfony/new-package/assets/entry2.js'; + $actualArguments = []; $this->scriptExecutor->expects($this->exactly(4)) ->method('execute') - ->withConsecutive( - ['symfony-cmd', 'importmap:require', ['@hotcake/foo@^1.9.0']], - ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]], - ['symfony-cmd', 'importmap:require', ['@symfony/new-package/entry.js', '--path='.$entrypointPath, '--entrypoint']], - ['symfony-cmd', 'importmap:require', ['@symfony/new-package/entry2.js', '--path='.$secondEntrypointPath, '--entrypoint']] - ); + ->willReturnCallback(function (...$arguments) use (&$actualArguments) { $actualArguments[] = $arguments; }); $this->synchronizer->synchronize([ [ @@ -422,6 +423,15 @@ public function testSynchronizeAssetMapperUpgradesPackageIfNeeded() 'keywords' => ['symfony-ux'], ], ]); + + $expectedArguments = [ + ['symfony-cmd', 'importmap:require', ['@hotcake/foo@^1.9.0']], + ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]], + ['symfony-cmd', 'importmap:require', ['@symfony/new-package/entry.js', '--path='.$entrypointPath, '--entrypoint']], + ['symfony-cmd', 'importmap:require', ['@symfony/new-package/entry2.js', '--path='.$secondEntrypointPath, '--entrypoint']], + ]; + + $this->assertSame($expectedArguments, $actualArguments); } public function testSynchronizeAssetMapperSkipsUpgradeIfAlreadySatisfied() @@ -441,12 +451,10 @@ public function testSynchronizeAssetMapperSkipsUpgradeIfAlreadySatisfied() $fileModulePath = $this->tempDir.'/vendor/symfony/new-package/assets/dist/loader.js'; $entrypointPath = $this->tempDir.'/vendor/symfony/new-package/assets/entry.js'; + $actualArguments = []; $this->scriptExecutor->expects($this->exactly(2)) ->method('execute') - ->withConsecutive( - ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]], - ['symfony-cmd', 'importmap:require', ['@symfony/new-package/entry.js', '--path='.$entrypointPath, '--entrypoint']], - ); + ->willReturnCallback(function (...$arguments) use (&$actualArguments) { $actualArguments[] = $arguments; }); $this->synchronizer->synchronize([ [ @@ -454,6 +462,13 @@ public function testSynchronizeAssetMapperSkipsUpgradeIfAlreadySatisfied() 'keywords' => ['symfony-ux'], ], ]); + + $expectedArguments = [ + ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]], + ['symfony-cmd', 'importmap:require', ['@symfony/new-package/entry.js', '--path='.$entrypointPath, '--entrypoint']], + ]; + + $this->assertSame($expectedArguments, $actualArguments); } public function testExceptionWhenInvalidImportMapConstraint() diff --git a/tests/PackageResolverTest.php b/tests/PackageResolverTest.php index bb6507e1..9ec7135c 100644 --- a/tests/PackageResolverTest.php +++ b/tests/PackageResolverTest.php @@ -11,21 +11,20 @@ namespace Symfony\Flex\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Flex\Downloader; use Symfony\Flex\PackageResolver; class PackageResolverTest extends TestCase { - /** - * @dataProvider getPackages - */ + #[DataProvider('getPackages')] public function testResolve($packages, $resolved, bool $isRequire = false) { $this->assertEquals($resolved, $this->getResolver()->resolve($packages, $isRequire)); } - public function getPackages() + public static function getPackages() { return [ [ @@ -73,9 +72,7 @@ public function getPackages() ]; } - /** - * @dataProvider getWrongPackages - */ + #[DataProvider('getWrongPackages')] public function testResolveWithErrors($packages, $error) { $this->expectException(\UnexpectedValueException::class); @@ -83,7 +80,7 @@ public function testResolveWithErrors($packages, $error) $this->getResolver()->resolve($packages); } - public function getWrongPackages() + public static function getWrongPackages() { return [ [ diff --git a/tests/PathTest.php b/tests/PathTest.php index 2659ba1e..baeb95a2 100644 --- a/tests/PathTest.php +++ b/tests/PathTest.php @@ -11,6 +11,7 @@ namespace Symfony\Flex\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Flex\Path; @@ -23,9 +24,7 @@ public function testConcatenateOnWindows() $this->assertEquals('c:\\my-project/src/kernel.php', $path->concatenate(['c:\\my-project', 'src/', 'kernel.php'])); } - /** - * @dataProvider providePathsForConcatenation - */ + #[DataProvider('providePathsForConcatenation')] public function testConcatenate($part1, $part2, $expectedPath) { $path = new Path(''); @@ -35,7 +34,7 @@ public function testConcatenate($part1, $part2, $expectedPath) $this->assertEquals($expectedPath, $actualPath); } - public function providePathsForConcatenation() + public static function providePathsForConcatenation() { return [ [__DIR__, 'foo/bar.txt', __DIR__.'/foo/bar.txt'], diff --git a/tests/ScriptExecutorTest.php b/tests/ScriptExecutorTest.php index 1b641312..896c5cff 100644 --- a/tests/ScriptExecutorTest.php +++ b/tests/ScriptExecutorTest.php @@ -14,6 +14,7 @@ use Composer\Composer; use Composer\IO\NullIO; use Composer\Util\ProcessExecutor; +use PHPUnit\Framework\Attributes\BackupGlobals; use PHPUnit\Framework\TestCase; use Symfony\Component\Process\PhpExecutableFinder; use Symfony\Flex\Options; @@ -21,10 +22,8 @@ final class ScriptExecutorTest extends TestCase { - /** - * @backupGlobals enabled - */ - public function testMemoryLimit(): void + #[BackupGlobals(true)] + public function testMemoryLimit() { $command = './command.php'; $memoryLimit = '32M'; diff --git a/tests/SymfonyBundleTest.php b/tests/SymfonyBundleTest.php index 35788fce..5af36bae 100644 --- a/tests/SymfonyBundleTest.php +++ b/tests/SymfonyBundleTest.php @@ -12,14 +12,13 @@ namespace Symfony\Flex\Tests; use Composer\Package\Package; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Flex\SymfonyBundle; class SymfonyBundleTest extends TestCase { - /** - * @dataProvider getNamespaces - */ + #[DataProvider('getNamespaces')] public function testGetClassNamesForInstall($package, $autoload, $classes, $type = null) { $config = $this->getMockBuilder('Composer\Config')->getMock(); @@ -36,10 +35,8 @@ public function testGetClassNamesForInstall($package, $autoload, $classes, $type $this->assertSame($classes, $bundle->getClassNames()); } - public function getNamespaces() + public static function getNamespaces() { - $return = []; - $packages = FlexTest::getTestPackages(); foreach ($packages as $name => $info) { $packageData = [$name, $info['autoload'], $info['bundles']]; @@ -47,9 +44,7 @@ public function getNamespaces() $packageData[] = $info['type']; } - $return[] = $packageData; + yield $packageData; } - - return $return; } } diff --git a/tests/UnpackerTest.php b/tests/UnpackerTest.php index 785da05a..c7493cfb 100644 --- a/tests/UnpackerTest.php +++ b/tests/UnpackerTest.php @@ -29,7 +29,7 @@ class UnpackerTest extends TestCase * * - "real" package MUST be present ONLY in "require" section */ - public function testDoNotDuplicateEntry(): void + public function testDoNotDuplicateEntry() { // Setup project @@ -39,7 +39,7 @@ public function testDoNotDuplicateEntry(): void @unlink($composerJsonPath); file_put_contents($composerJsonPath, '{}'); - $originalEnvComposer = $_SERVER['COMPOSER']; + $originalEnvComposer = $_SERVER['COMPOSER'] ?? null; $_SERVER['COMPOSER'] = $composerJsonPath; // composer 2.1 and lower support putenv('COMPOSER='.$composerJsonPath); diff --git a/tests/Update/DiffHelperTest.php b/tests/Update/DiffHelperTest.php index ed97d675..1223a95d 100644 --- a/tests/Update/DiffHelperTest.php +++ b/tests/Update/DiffHelperTest.php @@ -11,14 +11,13 @@ namespace Symfony\Flex\Tests\Update; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Flex\Update\DiffHelper; class DiffHelperTest extends TestCase { - /** - * @dataProvider getRemoveFilesFromPatchTests - */ + #[DataProvider('getRemoveFilesFromPatchTests')] public function testRemoveFilesFromPatch(string $patch, array $filesToRemove, string $expectedPatch, array $expectedRemovedPatches) { $removedPatches = []; @@ -27,7 +26,7 @@ public function testRemoveFilesFromPatch(string $patch, array $filesToRemove, st $this->assertSame($expectedRemovedPatches, $removedPatches); } - public function getRemoveFilesFromPatchTests(): iterable + public static function getRemoveFilesFromPatchTests(): iterable { $patch = <<getFilesystem()->remove(FLEX_TEST_DIR); - $this->getFilesystem()->mkdir(FLEX_TEST_DIR); + self::getFilesystem()->remove(FLEX_TEST_DIR); + self::getFilesystem()->mkdir(FLEX_TEST_DIR); } - /** - * @dataProvider getGeneratePatchTests - */ + #[DataProvider('getGeneratePatchTests')] public function testGeneratePatch(array $originalFiles, array $newFiles, string $expectedPatch, array $expectedDeletedFiles = []) { - $this->getFilesystem()->remove(FLEX_TEST_DIR); - $this->getFilesystem()->mkdir(FLEX_TEST_DIR); + self::getFilesystem()->remove(FLEX_TEST_DIR); + self::getFilesystem()->mkdir(FLEX_TEST_DIR); // original files need to be present to avoid patcher thinking they were deleting and skipping patch foreach ($originalFiles as $file => $contents) { touch(FLEX_TEST_DIR.'/'.$file); @@ -80,7 +79,7 @@ public function testGeneratePatch(array $originalFiles, array $newFiles, string $this->assertSame($expectedBlobs, $actualShortenedBlobs); } - public function getGeneratePatchTests(): iterable + public static function getGeneratePatchTests(): iterable { yield 'updated_file' => [ ['file1.txt' => 'Original contents', 'file2.txt' => 'Original file2'], @@ -186,8 +185,8 @@ public function getGeneratePatchTests(): iterable public function testGeneratePatchOnDeletedFile() { // make sure the target directory is empty - $this->getFilesystem()->remove(FLEX_TEST_DIR); - $this->getFilesystem()->mkdir(FLEX_TEST_DIR); + self::getFilesystem()->remove(FLEX_TEST_DIR); + self::getFilesystem()->mkdir(FLEX_TEST_DIR); $patcher = new RecipePatcher(FLEX_TEST_DIR, $this->createMock(IOInterface::class), $this->createMock(Lock::class)); @@ -196,9 +195,7 @@ public function testGeneratePatchOnDeletedFile() $this->assertSame('', $patch->getPatch()); } - /** - * @dataProvider getApplyPatchTests - */ + #[DataProvider('provideApplyPatchCases')] public function testApplyPatch(array $filesCurrentlyInApp, RecipePatch $recipePatch, array $expectedFiles, bool $expectedConflicts) { (new Process(['git', 'init'], FLEX_TEST_DIR))->mustRun(); @@ -264,9 +261,12 @@ public function testApplyPatchFileOwnedByMultipleRecipes() $this->assertFalse($hadConflicts); } - /** - * @dataProvider getApplyPatchTests - */ + public static function provideApplyPatchCases(): iterable + { + yield from self::getApplyPatchTests(''); + } + + #[DataProvider('provideApplyPatchOnSubfolderCases')] public function testApplyPatchOnSubfolder(array $filesCurrentlyInApp, RecipePatch $recipePatch, array $expectedFiles, bool $expectedConflicts) { $mainProjectPath = FLEX_TEST_DIR; @@ -308,10 +308,14 @@ public function testApplyPatchOnSubfolder(array $filesCurrentlyInApp, RecipePatc $this->assertSame($expectedConflicts, $hadConflicts); } - public function getApplyPatchTests(string $testMethodName): iterable + public static function provideApplyPatchOnSubfolderCases(): iterable { - $projectRootPath = ('testApplyPatchOnSubfolder' === $testMethodName) ? 'ProjectA/' : ''; - $files = $this->getFilesForPatching($projectRootPath); + yield from self::getApplyPatchTests('ProjectA/'); + } + + public static function getApplyPatchTests(string $projectRootPath): iterable + { + $files = self::getFilesForPatching($projectRootPath); $dotEnvClean = $files['dot_env_clean']; $packageJsonConflict = $files['package_json_conflict']; $webpackEncoreAdded = $files['webpack_encore_added']; @@ -393,12 +397,10 @@ public function getApplyPatchTests(string $testMethodName): iterable ]; } - /** - * @dataProvider getIntegrationTests - */ + #[DataProvider('getIntegrationTests')] public function testIntegration(bool $useNullForMissingFiles) { - $files = $this->getFilesForPatching(); + $files = self::getFilesForPatching(); (new Process(['git', 'init'], FLEX_TEST_DIR))->mustRun(); (new Process(['git', 'config', 'user.name', 'Unit test'], FLEX_TEST_DIR))->mustRun(); (new Process(['git', 'config', 'user.email', ''], FLEX_TEST_DIR))->mustRun(); @@ -452,7 +454,7 @@ public function testIntegration(bool $useNullForMissingFiles) $this->assertFileDoesNotExist(FLEX_TEST_DIR.'/security.yaml'); } - public function getIntegrationTests(): iterable + public static function getIntegrationTests(): iterable { yield 'missing_files_set_to_null' => [true]; yield 'missing_files_not_in_array' => [false]; @@ -469,7 +471,7 @@ public function getIntegrationTests(): iterable * * original_recipe * * updated_recipe. */ - private function getFilesForPatching(string $projectPath = ''): array + private static function getFilesForPatching(string $projectPath = ''): array { $files = [ // .env @@ -614,18 +616,18 @@ private function getFilesForPatching(string $projectPath = ''): array foreach ($files as $key => $data) { $files[$key] = array_merge( $data, - $this->generatePatchData($projectPath.$data['filename'], $data['original_recipe'], $data['updated_recipe']) + self::generatePatchData($projectPath.$data['filename'], $data['original_recipe'], $data['updated_recipe']) ); } return $files; } - private function generatePatchData(string $filename, ?string $start, ?string $end): array + private static function generatePatchData(string $filename, ?string $start, ?string $end): array { $dir = sys_get_temp_dir().'/_flex_diff'; if (file_exists($dir)) { - $this->getFilesystem()->remove($dir); + self::getFilesystem()->remove($dir); } @mkdir($dir); (new Process(['git', 'init'], $dir))->mustRun(); @@ -667,12 +669,12 @@ private function generatePatchData(string $filename, ?string $start, ?string $en ]; } - private function getFilesystem(): Filesystem + private static function getFilesystem(): Filesystem { - if (null === $this->filesystem) { - $this->filesystem = new Filesystem(); + if (null === self::$filesystem) { + self::$filesystem = new Filesystem(); } - return $this->filesystem; + return self::$filesystem; } }