From c648f8f0a266b588b4ffb4e332c962cc716e2165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my?= Date: Wed, 25 Dec 2024 00:11:14 +0100 Subject: [PATCH] fix: Handle command defined with AsCommand php attribute --- src/TestCommand.php | 4 + tests/Fixture/FixtureAttributeCommand.php | 94 +++++++++++++++++++++++ tests/Fixture/Kernel.php | 4 + tests/FunctionalTest.php | 14 ++++ 4 files changed, 116 insertions(+) create mode 100644 tests/Fixture/FixtureAttributeCommand.php diff --git a/src/TestCommand.php b/src/TestCommand.php index 1c0823c..21078c5 100644 --- a/src/TestCommand.php +++ b/src/TestCommand.php @@ -13,6 +13,7 @@ use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Command\LazyCommand; use Symfony\Component\Console\Tester\CommandCompletionTester; use Zenstruck\Assert; use Zenstruck\Console\Test\Assert\CompletionExpectation; @@ -56,6 +57,9 @@ public static function for(Command $command): self public static function from(Application $application, string $cli): self { foreach ($application->all() as $commandObject) { + if (class_exists(LazyCommand::class) && $commandObject instanceof LazyCommand) { + $commandObject = $commandObject->getCommand(); + } if ($cli === $commandObject::class) { return self::for($commandObject); } diff --git a/tests/Fixture/FixtureAttributeCommand.php b/tests/Fixture/FixtureAttributeCommand.php new file mode 100644 index 0000000..fb691a6 --- /dev/null +++ b/tests/Fixture/FixtureAttributeCommand.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Zenstruck\Console\Test\Tests\Fixture; + +use Symfony\Component\Console\Attribute\AsCommand; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * @author Kevin Bond + */ +#[AsCommand( + name: 'fixture:command', + description: 'zenstruck/console-test command for tests' +)] +final class FixtureAttributeCommand extends Command +{ + protected function configure(): void + { + $this + ->addArgument('arg1', InputArgument::OPTIONAL) + ->addOption('opt1', null, InputOption::VALUE_NONE) + ->addOption('opt2', null, InputOption::VALUE_REQUIRED) + ->addOption('opt3', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY) + ->addOption('throw', null, InputOption::VALUE_NONE) + ->addOption('code', null, InputOption::VALUE_REQUIRED, '', 0) + ; + } + + /** + * @param ConsoleOutputInterface $output + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $errOutput = $output->getErrorOutput(); + + $output->writeln('Executing command...'); + $output->writeln("verbosity: {$output->getVerbosity()}"); + $output->writeln('decorated: '.($output->isDecorated() ? 'yes' : 'no')); + $errOutput->writeln('Error output.'); + + if ($input->getOption('throw')) { + throw new \RuntimeException('Exception thrown!'); + } + + if ($arg1 = $input->getArgument('arg1')) { + $output->writeln("arg1 value: {$arg1}"); + } + + if ($input->getOption('opt1')) { + $output->writeln('opt1 option set'); + } + + if ($opt2 = $input->getOption('opt2')) { + $output->writeln("opt2 value: {$opt2}"); + } + + foreach ($input->getOption('opt3') as $value) { + $output->writeln("opt3 value: {$value}"); + } + + (new SymfonyStyle($input, $output))->success('Long link: https://github.com/zenstruck/console-test/blob/997ee1f66743342ffd9cd00a77613ebfa2efd2b8/src/CommandResult.php'); + + $table = new Table($output->section()); + $table->addRow(['table row 1']); + $table->render(); + $table->appendRow(['table row 2']); + + return (int) $input->getOption('code'); + } + + protected function interact(InputInterface $input, OutputInterface $output): void + { + $value = $this->getHelper('question')->ask($input, $output, new Question('Arg1 value?')); + + $input->setArgument('arg1', $value); + } +} diff --git a/tests/Fixture/Kernel.php b/tests/Fixture/Kernel.php index fd358d3..0eb16cf 100644 --- a/tests/Fixture/Kernel.php +++ b/tests/Fixture/Kernel.php @@ -36,6 +36,10 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load ->setAutoconfigured(true) ->setAutowired(true) ; + $c->register(FixtureAttributeCommand::class) + ->setAutoconfigured(true) + ->setAutowired(true) + ; $c->register('logger', NullLogger::class); $c->loadFromExtension('framework', [ 'secret' => 'S3CRET', diff --git a/tests/FunctionalTest.php b/tests/FunctionalTest.php index 630c2bf..233f2de 100644 --- a/tests/FunctionalTest.php +++ b/tests/FunctionalTest.php @@ -17,6 +17,7 @@ use Symfony\Component\Console\Helper\OutputWrapper; use Zenstruck\Assert; use Zenstruck\Console\Test\InteractsWithConsole; +use Zenstruck\Console\Test\Tests\Fixture\FixtureAttributeCommand; use Zenstruck\Console\Test\Tests\Fixture\FixtureCommand; /** @@ -71,6 +72,19 @@ public function class_name_command_with_no_arguments(): void ; } + /** + * @test + */ + public function class_name_command_with_no_arguments_defined_with_attribute(): void + { + $this->executeConsoleCommand(FixtureAttributeCommand::class) + ->assertSuccessful() + ->assertOutputContains('Executing command') + ->assertOutputNotContains('arg1') + ->assertOutputNotContains('opt1') + ; + } + /** * @test */