From ccd04bd7e26f2a4ecdd9527371af74e866624c4d Mon Sep 17 00:00:00 2001 From: Nicolas Joubert Date: Mon, 19 Oct 2026 16:01:34 +0200 Subject: [PATCH] #59 - Tests: detect the deprecations and boot a kernel with process-bundle - PHPUnit fails on deprecations (failOnDeprecation, details displayed), the silenced ones included (ignoreSuppressionOfDeprecations). The new tests/bootstrap.php enables the Symfony DebugClassLoader (@final, @internal, return types). - New functional test booting a kernel (FrameworkBundle, FlysystemBundle, process-bundle and this bundle): a local Flysystem storage is resolved, the three task codes resolve to FileFetchTask / ListContentTask / RemoveFileTask. The resolution of the task codes is skipped without TaskRegistry (cleverage/process-bundle < 5.4). - The exception handler of the ErrorHandler registered at boot is restored after each kernel test (not removed by the first Symfony 6.4 versions). - Require symfony/framework-bundle in dev. - TestKernel sets framework.property_info.with_constructor_extractor from Symfony 7.3 (not setting it is deprecated there); Rector does not remove this condition on the Symfony version (always true with the installed one). - league/flysystem-bundle ^3.2 in dev: 3.0 and 3.1 trigger return type deprecations (DebugClassLoader); the require stays ^3.0. Co-Authored-By: Claude Opus 5.5 (1M context) --- composer.json | 2 + phpunit.xml.dist | 8 ++- rector.php | 5 ++ tests/App/TestKernel.php | 114 ++++++++++++++++++++++++++++++++ tests/Functional/KernelTest.php | 87 ++++++++++++++++++++++++ tests/bootstrap.php | 19 ++++++ 6 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 tests/App/TestKernel.php create mode 100644 tests/Functional/KernelTest.php create mode 100644 tests/bootstrap.php diff --git a/composer.json b/composer.json index 26e7161..e85a533 100644 --- a/composer.json +++ b/composer.json @@ -64,6 +64,7 @@ }, "require-dev": { "friendsofphp/php-cs-fixer": "*", + "league/flysystem-bundle": "^3.2", "league/flysystem-local": "^3.0", "phpstan/extension-installer": "*", "phpstan/phpstan": "*", @@ -72,6 +73,7 @@ "rector/rector": "*", "roave/security-advisories": "dev-latest", "symfony/filesystem": "^6.4|^7.4|^8", + "symfony/framework-bundle": "^6.4|^7.4|^8", "symfony/test-pack": "^1.1" }, "config": { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 6bdb884..9e8b688 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,20 +1,22 @@ + failOnWarning="true" + failOnDeprecation="true" + displayDetailsOnTestsThatTriggerDeprecations="true"> tests - + src diff --git a/rector.php b/rector.php index a601b30..68fbff9 100644 --- a/rector.php +++ b/rector.php @@ -3,6 +3,7 @@ declare(strict_types=1); use Rector\Config\RectorConfig; +use Rector\DeadCode\Rector\If_\RemoveAlwaysTrueIfConditionRector; use Rector\Symfony\Set\SymfonySetList; use Rector\ValueObject\PhpVersion; @@ -20,4 +21,8 @@ ->withSets([ SymfonySetList::SYMFONY_CONSTRUCTOR_INJECTION, ]) + ->withSkip([ + // Conditions on the Symfony version: always true with the installed version only + RemoveAlwaysTrueIfConditionRector::class => [__DIR__.'/tests/App/TestKernel.php'], + ]) ; diff --git a/tests/App/TestKernel.php b/tests/App/TestKernel.php new file mode 100644 index 0000000..7a6396b --- /dev/null +++ b/tests/App/TestKernel.php @@ -0,0 +1,114 @@ +getRunDir().'/cache/'.$this->environment; + } + + public function getLogDir(): string + { + return $this->getRunDir().'/logs'; + } + + protected function configureContainer(ContainerConfigurator $container): void + { + $container->extension('framework', [ + 'secret' => 'test', + 'test' => true, + 'http_method_override' => false, + 'handle_all_throwables' => true, + 'php_errors' => ['log' => true], + 'validation' => ['email_validation_mode' => 'html5'], + ]); + if (Kernel::VERSION_ID >= 70300) { + // Not setting it is deprecated since Symfony 7.3: its default value changes in 8.0 + $container->extension('framework', ['property_info' => ['with_constructor_extractor' => true]]); + } + $directory = '%kernel.cache_dir%/storage'; + $container->extension('flysystem', [ + 'storages' => [ + // Configuration format of league/flysystem-bundle 3.5, the former one is deprecated there + 'test.storage' => method_exists(LocalAdapterDefinitionBuilder::class, 'addConfiguration') // @phpstan-ignore function.alreadyNarrowedType (false before 3.5) + ? ['local' => ['directory' => $directory]] + : ['adapter' => 'local', 'options' => ['directory' => $directory]], + ], + ]); + + // Tasks referenced by code (task: ): process-bundle 5.4 or later + if (class_exists(TaskRegistry::class)) { + $container->extension('clever_age_process', [ + 'configurations' => [ + 'test.flysystem' => [ + 'tasks' => [ + 'file_fetch' => [ + 'task' => 'flysystem_file_fetch', + 'options' => ['source_filesystem' => 'test.storage', 'destination_filesystem' => 'test.storage'], + ], + 'list_content' => [ + 'task' => 'flysystem_list_content', + 'options' => ['filesystem' => 'test.storage'], + ], + 'remove_file' => [ + 'task' => 'flysystem_remove_file', + 'options' => ['filesystem' => 'test.storage'], + ], + ], + ], + ], + ]); + $services = $container->services(); + $services->alias('test.task_registry', TaskRegistry::class)->public(); + $services->alias('test.process_configuration_registry', ProcessConfigurationRegistry::class)->public(); + } + } + + private function getRunDir(): string + { + return sys_get_temp_dir().'/flysystem_process_bundle_tests_'.getmypid(); + } +} diff --git a/tests/Functional/KernelTest.php b/tests/Functional/KernelTest.php new file mode 100644 index 0000000..ed73ffe --- /dev/null +++ b/tests/Functional/KernelTest.php @@ -0,0 +1,87 @@ +exceptionHandler = $this->getExceptionHandler(); + } + + protected function tearDown(): void + { + parent::tearDown(); + // The ErrorHandler registered when the kernel boots is not removed by the first Symfony 6.4 versions + if ($this->getExceptionHandler() !== $this->exceptionHandler) { + restore_exception_handler(); + } + } + + public function testTasksAndStorageAreRegistered(): void + { + $container = self::getContainer(); + + self::assertTrue($container->has(FileFetchTask::class)); + self::assertTrue($container->has(ListContentTask::class)); + self::assertTrue($container->has(RemoveFileTask::class)); + self::assertInstanceOf(FilesystemOperator::class, $container->get('test.storage')); + } + + public function testTasksAreResolvedByCode(): void + { + if (!class_exists(TaskRegistry::class)) { + self::markTestSkipped('The tasks are referenced by code since cleverage/process-bundle 5.4.'); + } + $processConfigurationRegistry = self::getContainer()->get('test.process_configuration_registry'); + self::assertInstanceOf(ProcessConfigurationRegistry::class, $processConfigurationRegistry); + $taskRegistry = self::getContainer()->get('test.task_registry'); + self::assertInstanceOf(TaskRegistry::class, $taskRegistry); + + $processConfiguration = $processConfigurationRegistry->getProcessConfiguration('test.flysystem'); + self::assertInstanceOf(FileFetchTask::class, $taskRegistry->getTask($processConfiguration->getTaskConfiguration('file_fetch'))); + self::assertInstanceOf(ListContentTask::class, $taskRegistry->getTask($processConfiguration->getTaskConfiguration('list_content'))); + self::assertInstanceOf(RemoveFileTask::class, $taskRegistry->getTask($processConfiguration->getTaskConfiguration('remove_file'))); + } + + private function getExceptionHandler(): mixed + { + $handler = set_exception_handler(null); + restore_exception_handler(); + + return $handler; + } + + protected static function getKernelClass(): string + { + return TestKernel::class; + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..2021424 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,19 @@ +