From e65c925ca3cca9a4f10133e243f07aaa47624e47 Mon Sep 17 00:00:00 2001 From: maxbeckers Date: Fri, 6 Jan 2023 14:04:33 +0100 Subject: [PATCH 01/20] [Console] fix clear of section with question --- Output/ConsoleSectionOutput.php | 12 ++++++++- Style/SymfonyStyle.php | 6 +++++ Tests/Style/SymfonyStyleTest.php | 42 ++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/Output/ConsoleSectionOutput.php b/Output/ConsoleSectionOutput.php index 7978a922c..c813c811c 100644 --- a/Output/ConsoleSectionOutput.php +++ b/Output/ConsoleSectionOutput.php @@ -115,7 +115,8 @@ public function addContent(string $input, bool $newline = true): int // re-add the line break (that has been removed in the above `explode()` for // - every line that is not the last line // - if $newline is required, also add it to the last line - if ($i < $count || $newline) { + // - if it's not new line, but input ending with `\PHP_EOL` + if ($i < $count || $newline || str_ends_with($input, \PHP_EOL)) { $lineContent .= \PHP_EOL; } @@ -149,6 +150,15 @@ public function addContent(string $input, bool $newline = true): int return $linesAdded; } + /** + * @internal + */ + public function addNewLineOfInputSubmit() + { + $this->content[] = \PHP_EOL; + ++$this->lines; + } + protected function doWrite(string $message, bool $newline) { if (!$this->isDecorated()) { diff --git a/Style/SymfonyStyle.php b/Style/SymfonyStyle.php index 997f86279..8fd6f849f 100644 --- a/Style/SymfonyStyle.php +++ b/Style/SymfonyStyle.php @@ -23,6 +23,7 @@ use Symfony\Component\Console\Helper\TableSeparator; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\ConsoleSectionOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\TrimmedBufferOutput; use Symfony\Component\Console\Question\ChoiceQuestion; @@ -298,6 +299,11 @@ public function askQuestion(Question $question): mixed $answer = $this->questionHelper->ask($this->input, $this, $question); if ($this->input->isInteractive()) { + if ($this->output instanceof ConsoleSectionOutput) { + // add the new line of the `return` to submit the input to ConsoleSectionOutput, because ConsoleSectionOutput is holding all it's lines. + // this is relevant when a `ConsoleSectionOutput::clear` is called. + $this->output->addNewLineOfInputSubmit(); + } $this->newLine(); $this->bufferedOutput->write("\n"); } diff --git a/Tests/Style/SymfonyStyleTest.php b/Tests/Style/SymfonyStyleTest.php index 74c240340..98748d15d 100644 --- a/Tests/Style/SymfonyStyleTest.php +++ b/Tests/Style/SymfonyStyleTest.php @@ -16,11 +16,13 @@ use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Input\Input; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\ConsoleSectionOutput; use Symfony\Component\Console\Output\NullOutput; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Output\StreamOutput; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Tester\CommandTester; @@ -181,4 +183,44 @@ public function testMemoryConsumption() $this->assertSame(0, memory_get_usage() - $start); } + + public function testAskAndClearExpectFullSectionCleared() + { + $answer = 'Answer'; + $inputStream = fopen('php://memory', 'r+'); + fwrite($inputStream, $answer.\PHP_EOL); + rewind($inputStream); + $input = $this->createMock(Input::class); + $sections = []; + $output = new ConsoleSectionOutput(fopen('php://memory', 'r+', false), $sections, StreamOutput::VERBOSITY_NORMAL, true, new OutputFormatter()); + $input + ->method('isInteractive') + ->willReturn(true); + $input + ->method('getStream') + ->willReturn($inputStream); + + $style = new SymfonyStyle($input, $output); + + $style->writeln('start'); + $style->write('foo'); + $style->writeln(' and bar'); + $givenAnswer = $style->ask('Dummy question?'); + $style->write('foo2'.\PHP_EOL); + $output->write('bar2'); + $output->clear(); + + rewind($output->getStream()); + $this->assertEquals($answer, $givenAnswer); + $this->assertEquals( + 'start'.\PHP_EOL. // write start + 'foo'.\PHP_EOL. // write foo + "\x1b[1A\x1b[0Jfoo and bar".\PHP_EOL. // complete line + \PHP_EOL.\PHP_EOL." \033[32mDummy question?\033[39m:".\PHP_EOL.' > '.\PHP_EOL.\PHP_EOL.\PHP_EOL. // question + 'foo2'.\PHP_EOL.\PHP_EOL. // write foo2 + 'bar2'.\PHP_EOL. // write bar + "\033[12A\033[0J", // clear 12 lines (11 output lines and one from the answer input return) + stream_get_contents($output->getStream()) + ); + } } From fd78f92db30810d1de85a88d8d2b5ef802d898f2 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 24 Jan 2023 15:02:24 +0100 Subject: [PATCH 02/20] Update license years (last time) --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 008370457..0138f8f07 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2023 Fabien Potencier +Copyright (c) 2004-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 8ae1b6025612cfffb8b4e8d4afedcc5d9cb6d0f3 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Sun, 5 Feb 2023 10:12:16 +0100 Subject: [PATCH 03/20] [Tests] Migrate data providers to static ones --- Tests/Descriptor/AbstractDescriptorTest.php | 26 ++++++++++----------- Tests/Descriptor/JsonDescriptorTest.php | 2 +- Tests/Descriptor/MarkdownDescriptorTest.php | 10 ++++---- Tests/Descriptor/TextDescriptorTest.php | 10 ++++---- Tests/Descriptor/XmlDescriptorTest.php | 2 +- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Tests/Descriptor/AbstractDescriptorTest.php b/Tests/Descriptor/AbstractDescriptorTest.php index 97199fb34..55150c3a6 100644 --- a/Tests/Descriptor/AbstractDescriptorTest.php +++ b/Tests/Descriptor/AbstractDescriptorTest.php @@ -51,40 +51,40 @@ public function testDescribeApplication(Application $application, $expectedDescr $this->assertDescription($expectedDescription, $application); } - public function getDescribeInputArgumentTestData() + public static function getDescribeInputArgumentTestData() { - return $this->getDescriptionTestData(ObjectsProvider::getInputArguments()); + return static::getDescriptionTestData(ObjectsProvider::getInputArguments()); } - public function getDescribeInputOptionTestData() + public static function getDescribeInputOptionTestData() { - return $this->getDescriptionTestData(ObjectsProvider::getInputOptions()); + return static::getDescriptionTestData(ObjectsProvider::getInputOptions()); } - public function getDescribeInputDefinitionTestData() + public static function getDescribeInputDefinitionTestData() { - return $this->getDescriptionTestData(ObjectsProvider::getInputDefinitions()); + return static::getDescriptionTestData(ObjectsProvider::getInputDefinitions()); } - public function getDescribeCommandTestData() + public static function getDescribeCommandTestData() { - return $this->getDescriptionTestData(ObjectsProvider::getCommands()); + return static::getDescriptionTestData(ObjectsProvider::getCommands()); } - public function getDescribeApplicationTestData() + public static function getDescribeApplicationTestData() { - return $this->getDescriptionTestData(ObjectsProvider::getApplications()); + return static::getDescriptionTestData(ObjectsProvider::getApplications()); } abstract protected function getDescriptor(); - abstract protected function getFormat(); + abstract protected static function getFormat(); - protected function getDescriptionTestData(array $objects) + protected static function getDescriptionTestData(array $objects) { $data = []; foreach ($objects as $name => $object) { - $description = file_get_contents(sprintf('%s/../Fixtures/%s.%s', __DIR__, $name, $this->getFormat())); + $description = file_get_contents(sprintf('%s/../Fixtures/%s.%s', __DIR__, $name, static::getFormat())); $data[] = [$object, $description]; } diff --git a/Tests/Descriptor/JsonDescriptorTest.php b/Tests/Descriptor/JsonDescriptorTest.php index 60ef02977..1fbc2e90b 100644 --- a/Tests/Descriptor/JsonDescriptorTest.php +++ b/Tests/Descriptor/JsonDescriptorTest.php @@ -20,7 +20,7 @@ protected function getDescriptor() return new JsonDescriptor(); } - protected function getFormat() + protected static function getFormat() { return 'json'; } diff --git a/Tests/Descriptor/MarkdownDescriptorTest.php b/Tests/Descriptor/MarkdownDescriptorTest.php index a8f11cb4a..5067e4c51 100644 --- a/Tests/Descriptor/MarkdownDescriptorTest.php +++ b/Tests/Descriptor/MarkdownDescriptorTest.php @@ -17,17 +17,17 @@ class MarkdownDescriptorTest extends AbstractDescriptorTest { - public function getDescribeCommandTestData() + public static function getDescribeCommandTestData() { - return $this->getDescriptionTestData(array_merge( + return self::getDescriptionTestData(array_merge( ObjectsProvider::getCommands(), ['command_mbstring' => new DescriptorCommandMbString()] )); } - public function getDescribeApplicationTestData() + public static function getDescribeApplicationTestData() { - return $this->getDescriptionTestData(array_merge( + return self::getDescriptionTestData(array_merge( ObjectsProvider::getApplications(), ['application_mbstring' => new DescriptorApplicationMbString()] )); @@ -38,7 +38,7 @@ protected function getDescriptor() return new MarkdownDescriptor(); } - protected function getFormat() + protected static function getFormat() { return 'md'; } diff --git a/Tests/Descriptor/TextDescriptorTest.php b/Tests/Descriptor/TextDescriptorTest.php index 26bbd907a..c0e5942e9 100644 --- a/Tests/Descriptor/TextDescriptorTest.php +++ b/Tests/Descriptor/TextDescriptorTest.php @@ -18,17 +18,17 @@ class TextDescriptorTest extends AbstractDescriptorTest { - public function getDescribeCommandTestData() + public static function getDescribeCommandTestData() { - return $this->getDescriptionTestData(array_merge( + return self::getDescriptionTestData(array_merge( ObjectsProvider::getCommands(), ['command_mbstring' => new DescriptorCommandMbString()] )); } - public function getDescribeApplicationTestData() + public static function getDescribeApplicationTestData() { - return $this->getDescriptionTestData(array_merge( + return self::getDescriptionTestData(array_merge( ObjectsProvider::getApplications(), ['application_mbstring' => new DescriptorApplicationMbString()] )); @@ -46,7 +46,7 @@ protected function getDescriptor() return new TextDescriptor(); } - protected function getFormat() + protected static function getFormat() { return 'txt'; } diff --git a/Tests/Descriptor/XmlDescriptorTest.php b/Tests/Descriptor/XmlDescriptorTest.php index 59a5d1ed8..d50ac12dd 100644 --- a/Tests/Descriptor/XmlDescriptorTest.php +++ b/Tests/Descriptor/XmlDescriptorTest.php @@ -20,7 +20,7 @@ protected function getDescriptor() return new XmlDescriptor(); } - protected function getFormat() + protected static function getFormat() { return 'xml'; } From 4b81c203691eeebd4d47f74b904ebaf251d514d8 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 7 Feb 2023 10:31:13 +0100 Subject: [PATCH 04/20] minor #49253 [PHPUnit 10] Use `TestCase` suffix for abstract tests in `/Tests/` (OskarStark) This PR was merged into the 6.3 branch. Discussion ---------- [PHPUnit 10] Use `TestCase` suffix for abstract tests in `/Tests/` | Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | no | New feature? | no | Deprecations? | no | Tickets | Refs https://github.com/symfony/symfony/pull/49233 | License | MIT | Doc PR | n/a Replaces #49234 Using `Test` suffix is deprecated since PHPUnit 10 Spotted in * https://github.com/symfony/symfony/pull/49233 Commits ------- cb3db968e4 [PHPUnit 10] Use `TestCase` suffix for abstract tests in `/Tests/` --- ...bstractDescriptorTest.php => AbstractDescriptorTestCase.php} | 2 +- Tests/Descriptor/JsonDescriptorTest.php | 2 +- Tests/Descriptor/MarkdownDescriptorTest.php | 2 +- Tests/Descriptor/TextDescriptorTest.php | 2 +- Tests/Descriptor/XmlDescriptorTest.php | 2 +- ...uestionHelperTest.php => AbstractQuestionHelperTestCase.php} | 2 +- Tests/Helper/QuestionHelperTest.php | 2 +- Tests/Helper/SymfonyQuestionHelperTest.php | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) rename Tests/Descriptor/{AbstractDescriptorTest.php => AbstractDescriptorTestCase.php} (98%) rename Tests/Helper/{AbstractQuestionHelperTest.php => AbstractQuestionHelperTestCase.php} (93%) diff --git a/Tests/Descriptor/AbstractDescriptorTest.php b/Tests/Descriptor/AbstractDescriptorTestCase.php similarity index 98% rename from Tests/Descriptor/AbstractDescriptorTest.php rename to Tests/Descriptor/AbstractDescriptorTestCase.php index 55150c3a6..6e0caab54 100644 --- a/Tests/Descriptor/AbstractDescriptorTest.php +++ b/Tests/Descriptor/AbstractDescriptorTestCase.php @@ -19,7 +19,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\BufferedOutput; -abstract class AbstractDescriptorTest extends TestCase +abstract class AbstractDescriptorTestCase extends TestCase { /** @dataProvider getDescribeInputArgumentTestData */ public function testDescribeInputArgument(InputArgument $argument, $expectedDescription) diff --git a/Tests/Descriptor/JsonDescriptorTest.php b/Tests/Descriptor/JsonDescriptorTest.php index 1fbc2e90b..648476dc4 100644 --- a/Tests/Descriptor/JsonDescriptorTest.php +++ b/Tests/Descriptor/JsonDescriptorTest.php @@ -13,7 +13,7 @@ use Symfony\Component\Console\Descriptor\JsonDescriptor; -class JsonDescriptorTest extends AbstractDescriptorTest +class JsonDescriptorTest extends AbstractDescriptorTestCase { protected function getDescriptor() { diff --git a/Tests/Descriptor/MarkdownDescriptorTest.php b/Tests/Descriptor/MarkdownDescriptorTest.php index 5067e4c51..295c7acea 100644 --- a/Tests/Descriptor/MarkdownDescriptorTest.php +++ b/Tests/Descriptor/MarkdownDescriptorTest.php @@ -15,7 +15,7 @@ use Symfony\Component\Console\Tests\Fixtures\DescriptorApplicationMbString; use Symfony\Component\Console\Tests\Fixtures\DescriptorCommandMbString; -class MarkdownDescriptorTest extends AbstractDescriptorTest +class MarkdownDescriptorTest extends AbstractDescriptorTestCase { public static function getDescribeCommandTestData() { diff --git a/Tests/Descriptor/TextDescriptorTest.php b/Tests/Descriptor/TextDescriptorTest.php index c0e5942e9..c576ac2d7 100644 --- a/Tests/Descriptor/TextDescriptorTest.php +++ b/Tests/Descriptor/TextDescriptorTest.php @@ -16,7 +16,7 @@ use Symfony\Component\Console\Tests\Fixtures\DescriptorApplicationMbString; use Symfony\Component\Console\Tests\Fixtures\DescriptorCommandMbString; -class TextDescriptorTest extends AbstractDescriptorTest +class TextDescriptorTest extends AbstractDescriptorTestCase { public static function getDescribeCommandTestData() { diff --git a/Tests/Descriptor/XmlDescriptorTest.php b/Tests/Descriptor/XmlDescriptorTest.php index d50ac12dd..98f92991a 100644 --- a/Tests/Descriptor/XmlDescriptorTest.php +++ b/Tests/Descriptor/XmlDescriptorTest.php @@ -13,7 +13,7 @@ use Symfony\Component\Console\Descriptor\XmlDescriptor; -class XmlDescriptorTest extends AbstractDescriptorTest +class XmlDescriptorTest extends AbstractDescriptorTestCase { protected function getDescriptor() { diff --git a/Tests/Helper/AbstractQuestionHelperTest.php b/Tests/Helper/AbstractQuestionHelperTestCase.php similarity index 93% rename from Tests/Helper/AbstractQuestionHelperTest.php rename to Tests/Helper/AbstractQuestionHelperTestCase.php index 3da121624..66f45c27f 100644 --- a/Tests/Helper/AbstractQuestionHelperTest.php +++ b/Tests/Helper/AbstractQuestionHelperTestCase.php @@ -14,7 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Input\StreamableInputInterface; -abstract class AbstractQuestionHelperTest extends TestCase +abstract class AbstractQuestionHelperTestCase extends TestCase { protected function createStreamableInputInterfaceMock($stream = null, $interactive = true) { diff --git a/Tests/Helper/QuestionHelperTest.php b/Tests/Helper/QuestionHelperTest.php index 1297b92f9..d9aef3365 100644 --- a/Tests/Helper/QuestionHelperTest.php +++ b/Tests/Helper/QuestionHelperTest.php @@ -30,7 +30,7 @@ /** * @group tty */ -class QuestionHelperTest extends AbstractQuestionHelperTest +class QuestionHelperTest extends AbstractQuestionHelperTestCase { public function testAskChoice() { diff --git a/Tests/Helper/SymfonyQuestionHelperTest.php b/Tests/Helper/SymfonyQuestionHelperTest.php index 72c3f879f..c6a5bf88a 100644 --- a/Tests/Helper/SymfonyQuestionHelperTest.php +++ b/Tests/Helper/SymfonyQuestionHelperTest.php @@ -23,7 +23,7 @@ /** * @group tty */ -class SymfonyQuestionHelperTest extends AbstractQuestionHelperTest +class SymfonyQuestionHelperTest extends AbstractQuestionHelperTestCase { public function testAskChoice() { From 0b4af1468a8833e902816aeec3a043277db356e0 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Wed, 14 Dec 2022 15:42:16 +0100 Subject: [PATCH 05/20] Migrate to `static` data providers using `rector/rector` --- Tests/ApplicationTest.php | 6 +++--- Tests/CI/GithubActionReporterTest.php | 2 +- Tests/Command/CommandTest.php | 4 ++-- Tests/Command/CompleteCommandTest.php | 6 +++--- Tests/Command/DumpCompletionCommandTest.php | 2 +- Tests/Command/HelpCommandTest.php | 2 +- Tests/Command/ListCommandTest.php | 2 +- Tests/Completion/CompletionInputTest.php | 6 +++--- .../AddConsoleCommandPassTest.php | 2 +- Tests/Descriptor/ApplicationDescriptionTest.php | 2 +- Tests/Formatter/OutputFormatterTest.php | 4 ++-- Tests/Helper/DumperNativeFallbackTest.php | 2 +- Tests/Helper/DumperTest.php | 2 +- Tests/Helper/HelperTest.php | 4 ++-- Tests/Helper/ProcessHelperTest.php | 2 +- Tests/Helper/ProgressBarTest.php | 2 +- Tests/Helper/ProgressIndicatorTest.php | 2 +- Tests/Helper/QuestionHelperTest.php | 10 +++++----- Tests/Helper/TableTest.php | 6 +++--- Tests/Input/ArgvInputTest.php | 10 +++++----- Tests/Input/ArrayInputTest.php | 4 ++-- Tests/Input/InputDefinitionTest.php | 2 +- Tests/Input/StringInputTest.php | 2 +- Tests/Logger/ConsoleLoggerTest.php | 4 ++-- Tests/Output/OutputTest.php | 4 ++-- Tests/Question/ChoiceQuestionTest.php | 4 ++-- Tests/Question/ConfirmationQuestionTest.php | 2 +- Tests/Question/QuestionTest.php | 12 ++++++------ Tests/Style/SymfonyStyleTest.php | 4 ++-- Tests/Tester/Constraint/CommandIsSuccessfulTest.php | 2 +- 30 files changed, 59 insertions(+), 59 deletions(-) diff --git a/Tests/ApplicationTest.php b/Tests/ApplicationTest.php index d438c3fc9..4e4c032b8 100644 --- a/Tests/ApplicationTest.php +++ b/Tests/ApplicationTest.php @@ -431,7 +431,7 @@ public function testFindWithAmbiguousAbbreviations($abbreviation, $expectedExcep $application->find($abbreviation); } - public function provideAmbiguousAbbreviations() + public static function provideAmbiguousAbbreviations() { return [ ['f', 'Command "f" is not defined.'], @@ -547,7 +547,7 @@ public function testDontRunAlternativeCommandName() $this->assertStringContainsString('Do you want to run "foo" instead? (yes/no) [no]:', $display); } - public function provideInvalidCommandNamesSingle() + public static function provideInvalidCommandNamesSingle() { return [ ['foo3:barr'], @@ -1239,7 +1239,7 @@ public function testAddingAlreadySetDefinitionElementData($def) $application->run($input, $output); } - public function getAddingAlreadySetDefinitionElementData() + public static function getAddingAlreadySetDefinitionElementData() { return [ [new InputArgument('command', InputArgument::REQUIRED)], diff --git a/Tests/CI/GithubActionReporterTest.php b/Tests/CI/GithubActionReporterTest.php index 6ef190f16..23f7a3bd9 100644 --- a/Tests/CI/GithubActionReporterTest.php +++ b/Tests/CI/GithubActionReporterTest.php @@ -43,7 +43,7 @@ public function testAnnotationsFormat(string $type, string $message, string $fil self::assertSame($expected.\PHP_EOL, $buffer->fetch()); } - public function annotationsFormatProvider(): iterable + public static function annotationsFormatProvider(): iterable { yield 'warning' => ['warning', 'A warning', null, null, null, '::warning::A warning']; yield 'error' => ['error', 'An error', null, null, null, '::error::An error']; diff --git a/Tests/Command/CommandTest.php b/Tests/Command/CommandTest.php index 81d4b9bba..63a5ea853 100644 --- a/Tests/Command/CommandTest.php +++ b/Tests/Command/CommandTest.php @@ -124,7 +124,7 @@ public function testInvalidCommandNames($name) $command->setName($name); } - public function provideInvalidCommandNames() + public static function provideInvalidCommandNames() { return [ [''], @@ -338,7 +338,7 @@ public function testSetCode() $this->assertEquals('interact called'.\PHP_EOL.'from the code...'.\PHP_EOL, $tester->getDisplay()); } - public function getSetCodeBindToClosureTests() + public static function getSetCodeBindToClosureTests() { return [ [true, 'not bound to the command'], diff --git a/Tests/Command/CompleteCommandTest.php b/Tests/Command/CompleteCommandTest.php index e6c74a736..30b22c967 100644 --- a/Tests/Command/CompleteCommandTest.php +++ b/Tests/Command/CompleteCommandTest.php @@ -81,7 +81,7 @@ public function testInputAndCurrentOptionValidation(array $input, ?string $excep } } - public function provideInputAndCurrentOptionValues() + public static function provideInputAndCurrentOptionValues() { yield [[], 'The "--current" option must be set and it must be an integer']; yield [['--current' => 'a'], 'The "--current" option must be set and it must be an integer']; @@ -100,7 +100,7 @@ public function testCompleteCommandName(array $input, array $suggestions) $this->assertEquals(implode("\n", $suggestions).\PHP_EOL, $this->tester->getDisplay()); } - public function provideCompleteCommandNameInputs() + public static function provideCompleteCommandNameInputs() { yield 'empty' => [['bin/console'], ['help', 'list', 'completion', 'hello', 'ahoy']]; yield 'partial' => [['bin/console', 'he'], ['help', 'list', 'completion', 'hello', 'ahoy']]; @@ -117,7 +117,7 @@ public function testCompleteCommandInputDefinition(array $input, array $suggesti $this->assertEquals(implode("\n", $suggestions).\PHP_EOL, $this->tester->getDisplay()); } - public function provideCompleteCommandInputDefinitionInputs() + public static function provideCompleteCommandInputDefinitionInputs() { yield 'definition' => [['bin/console', 'hello', '-'], ['--help', '--quiet', '--verbose', '--version', '--ansi', '--no-ansi', '--no-interaction']]; yield 'custom' => [['bin/console', 'hello'], ['Fabien', 'Robin', 'Wouter']]; diff --git a/Tests/Command/DumpCompletionCommandTest.php b/Tests/Command/DumpCompletionCommandTest.php index 21df42873..8d0fb4553 100644 --- a/Tests/Command/DumpCompletionCommandTest.php +++ b/Tests/Command/DumpCompletionCommandTest.php @@ -28,7 +28,7 @@ public function testComplete(array $input, array $expectedSuggestions) $this->assertSame($expectedSuggestions, $suggestions); } - public function provideCompletionSuggestions() + public static function provideCompletionSuggestions() { yield 'shell' => [ [''], diff --git a/Tests/Command/HelpCommandTest.php b/Tests/Command/HelpCommandTest.php index 0e8a7f4f7..d61c912fc 100644 --- a/Tests/Command/HelpCommandTest.php +++ b/Tests/Command/HelpCommandTest.php @@ -83,7 +83,7 @@ public function testComplete(array $input, array $expectedSuggestions) $this->assertSame($expectedSuggestions, $suggestions); } - public function provideCompletionSuggestions() + public static function provideCompletionSuggestions() { yield 'option --format' => [ ['--format', ''], diff --git a/Tests/Command/ListCommandTest.php b/Tests/Command/ListCommandTest.php index 0f78cf7ee..7ed9d3d5d 100644 --- a/Tests/Command/ListCommandTest.php +++ b/Tests/Command/ListCommandTest.php @@ -127,7 +127,7 @@ public function testComplete(array $input, array $expectedSuggestions) $this->assertSame($expectedSuggestions, $suggestions); } - public function provideCompletionSuggestions() + public static function provideCompletionSuggestions() { yield 'option --format' => [ ['--format', ''], diff --git a/Tests/Completion/CompletionInputTest.php b/Tests/Completion/CompletionInputTest.php index ee370076c..d98da682c 100644 --- a/Tests/Completion/CompletionInputTest.php +++ b/Tests/Completion/CompletionInputTest.php @@ -39,7 +39,7 @@ public function testBind(CompletionInput $input, string $expectedType, ?string $ $this->assertEquals($expectedValue, $input->getCompletionValue(), 'Unexpected value'); } - public function provideBindData() + public static function provideBindData() { // option names yield 'optname-minimal-input' => [CompletionInput::fromTokens(['bin/console', '-'], 1), CompletionInput::TYPE_OPTION_NAME, null, '-']; @@ -90,7 +90,7 @@ public function testBindWithLastArrayArgument(CompletionInput $input, ?string $e $this->assertEquals($expectedValue, $input->getCompletionValue(), 'Unexpected value'); } - public function provideBindWithLastArrayArgumentData() + public static function provideBindWithLastArrayArgumentData() { yield [CompletionInput::fromTokens(['bin/console'], 1), null]; yield [CompletionInput::fromTokens(['bin/console', 'symfony', 'sensiolabs'], 3), null]; @@ -124,7 +124,7 @@ public function testFromString($inputStr, array $expectedTokens) $this->assertEquals($expectedTokens, $tokensProperty->getValue($input)); } - public function provideFromStringData() + public static function provideFromStringData() { yield ['bin/console cache:clear', ['bin/console', 'cache:clear']]; yield ['bin/console --env prod', ['bin/console', '--env', 'prod']]; diff --git a/Tests/DependencyInjection/AddConsoleCommandPassTest.php b/Tests/DependencyInjection/AddConsoleCommandPassTest.php index eec4eff43..1556617fb 100644 --- a/Tests/DependencyInjection/AddConsoleCommandPassTest.php +++ b/Tests/DependencyInjection/AddConsoleCommandPassTest.php @@ -112,7 +112,7 @@ public function testProcessFallsBackToDefaultName() $this->assertSame(['new-name' => 'with-default-name'], $container->getDefinition('console.command_loader')->getArgument(1)); } - public function visibilityProvider() + public static function visibilityProvider() { return [ [true], diff --git a/Tests/Descriptor/ApplicationDescriptionTest.php b/Tests/Descriptor/ApplicationDescriptionTest.php index da64dca00..989521ebb 100644 --- a/Tests/Descriptor/ApplicationDescriptionTest.php +++ b/Tests/Descriptor/ApplicationDescriptionTest.php @@ -31,7 +31,7 @@ public function testGetNamespaces(array $expected, array $names) $this->assertSame($expected, array_keys((new ApplicationDescription($application))->getNamespaces())); } - public function getNamespacesProvider() + public static function getNamespacesProvider() { return [ [['_global'], ['foobar']], diff --git a/Tests/Formatter/OutputFormatterTest.php b/Tests/Formatter/OutputFormatterTest.php index c6d2184e9..84eb8d87f 100644 --- a/Tests/Formatter/OutputFormatterTest.php +++ b/Tests/Formatter/OutputFormatterTest.php @@ -185,7 +185,7 @@ public function testInlineStyleOptions(string $tag, string $expected = null, str } } - public function provideInlineStyleOptionsCases() + public static function provideInlineStyleOptionsCases() { return [ [''], @@ -258,7 +258,7 @@ public function testNotDecoratedFormatter(string $input, string $expectedNonDeco } } - public function provideDecoratedAndNonDecoratedOutput() + public static function provideDecoratedAndNonDecoratedOutput() { return [ ['some error', 'some error', "\033[37;41msome error\033[39;49m"], diff --git a/Tests/Helper/DumperNativeFallbackTest.php b/Tests/Helper/DumperNativeFallbackTest.php index 906d322b6..1b37e4e93 100644 --- a/Tests/Helper/DumperNativeFallbackTest.php +++ b/Tests/Helper/DumperNativeFallbackTest.php @@ -42,7 +42,7 @@ public function testInvoke($variable, $primitiveString) $this->assertSame($primitiveString, $dumper($variable)); } - public function provideVariables() + public static function provideVariables() { return [ [null, 'null'], diff --git a/Tests/Helper/DumperTest.php b/Tests/Helper/DumperTest.php index e491422b0..0a30c6ec3 100644 --- a/Tests/Helper/DumperTest.php +++ b/Tests/Helper/DumperTest.php @@ -45,7 +45,7 @@ public function testInvoke($variable) $this->assertDumpMatchesFormat($dumper($variable), $variable); } - public function provideVariables() + public static function provideVariables() { return [ [null], diff --git a/Tests/Helper/HelperTest.php b/Tests/Helper/HelperTest.php index b8c891087..9f59aa2ff 100644 --- a/Tests/Helper/HelperTest.php +++ b/Tests/Helper/HelperTest.php @@ -17,7 +17,7 @@ class HelperTest extends TestCase { - public function formatTimeProvider() + public static function formatTimeProvider() { return [ [0, '< 1 sec'], @@ -43,7 +43,7 @@ public function formatTimeProvider() ]; } - public function decoratedTextProvider() + public static function decoratedTextProvider() { return [ ['abc', 'abc'], diff --git a/Tests/Helper/ProcessHelperTest.php b/Tests/Helper/ProcessHelperTest.php index e2880f22f..b4d7b0bbc 100644 --- a/Tests/Helper/ProcessHelperTest.php +++ b/Tests/Helper/ProcessHelperTest.php @@ -49,7 +49,7 @@ public function testPassedCallbackIsExecuted() $this->assertTrue($executed); } - public function provideCommandsAndOutput() + public static function provideCommandsAndOutput() { $successOutputVerbose = <<<'EOT' RUN php -r "echo 42;" diff --git a/Tests/Helper/ProgressBarTest.php b/Tests/Helper/ProgressBarTest.php index c9b9c9d53..a0c6ee129 100644 --- a/Tests/Helper/ProgressBarTest.php +++ b/Tests/Helper/ProgressBarTest.php @@ -954,7 +954,7 @@ public function testFormatsWithoutMax($format) /** * Provides each defined format. */ - public function provideFormat(): array + public static function provideFormat(): array { return [ ['normal'], diff --git a/Tests/Helper/ProgressIndicatorTest.php b/Tests/Helper/ProgressIndicatorTest.php index cd97d406e..ffb3472ec 100644 --- a/Tests/Helper/ProgressIndicatorTest.php +++ b/Tests/Helper/ProgressIndicatorTest.php @@ -158,7 +158,7 @@ public function testFormats($format) /** * Provides each defined format. */ - public function provideFormat(): array + public static function provideFormat(): array { return [ ['normal'], diff --git a/Tests/Helper/QuestionHelperTest.php b/Tests/Helper/QuestionHelperTest.php index d9aef3365..9761e8f97 100644 --- a/Tests/Helper/QuestionHelperTest.php +++ b/Tests/Helper/QuestionHelperTest.php @@ -340,7 +340,7 @@ public function testAskWithAutocompleteWithExactMatch() $this->assertSame('b', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); } - public function getInputs() + public static function getInputs() { return [ ['$'], // 1 byte character @@ -536,7 +536,7 @@ public function testAskConfirmation($question, $expected, $default = true) $this->assertEquals($expected, $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question), 'confirmation question should '.($expected ? 'pass' : 'cancel')); } - public function getAskConfirmationData() + public static function getAskConfirmationData() { return [ ['', true], @@ -612,7 +612,7 @@ public function testSelectChoiceFromSimpleChoices($providedAnswer, $expectedValu $this->assertSame($expectedValue, $answer); } - public function simpleAnswerProvider() + public static function simpleAnswerProvider() { return [ [0, 'My environment 1'], @@ -647,7 +647,7 @@ public function testSpecialCharacterChoiceFromMultipleChoiceList($providedAnswer $this->assertSame($expectedValue, $answer); } - public function specialCharacterInMultipleChoice() + public static function specialCharacterInMultipleChoice() { return [ ['.', ['.']], @@ -697,7 +697,7 @@ public function testAmbiguousChoiceFromChoicelist() $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("My environment\n")), $this->createOutputInterface(), $question); } - public function answerProvider() + public static function answerProvider() { return [ ['env_1', 'env_1'], diff --git a/Tests/Helper/TableTest.php b/Tests/Helper/TableTest.php index 2d70bd271..d10289c66 100644 --- a/Tests/Helper/TableTest.php +++ b/Tests/Helper/TableTest.php @@ -88,7 +88,7 @@ public function testRenderAddRowsOneByOne($headers, $rows, $style, $expected, $d $this->assertEquals($expected, $this->getOutputContent($output)); } - public function renderProvider() + public static function renderProvider() { $books = [ ['99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'], @@ -1268,7 +1268,7 @@ public function testSetTitle($headerTitle, $footerTitle, $style, $expected) $this->assertEquals($expected, $this->getOutputContent($output)); } - public function renderSetTitle() + public static function renderSetTitle() { return [ [ @@ -1481,7 +1481,7 @@ public function testBoxedStyleWithColspan() $this->assertSame($expected, $this->getOutputContent($output)); } - public function provideRenderHorizontalTests() + public static function provideRenderHorizontalTests() { $headers = ['foo', 'bar', 'baz']; $rows = [['one', 'two', 'tree'], ['1', '2', '3']]; diff --git a/Tests/Input/ArgvInputTest.php b/Tests/Input/ArgvInputTest.php index 233333270..b5289fa01 100644 --- a/Tests/Input/ArgvInputTest.php +++ b/Tests/Input/ArgvInputTest.php @@ -61,7 +61,7 @@ public function testParseOptionsNegatable($input, $options, $expectedOptions, $m $this->assertEquals($expectedOptions, $input->getOptions(), $message); } - public function provideOptions() + public static function provideOptions() { return [ [ @@ -187,7 +187,7 @@ public function provideOptions() ]; } - public function provideNegatableOptions() + public static function provideNegatableOptions() { return [ [ @@ -259,7 +259,7 @@ public function testInvalidInputNegatable($argv, $definition, $expectedException $input->bind($definition); } - public function provideInvalidInput() + public static function provideInvalidInput() { return [ [ @@ -330,7 +330,7 @@ public function provideInvalidInput() ]; } - public function provideInvalidNegatableInput() + public static function provideInvalidNegatableInput() { return [ [ @@ -516,7 +516,7 @@ public function testGetParameterOptionEqualSign($argv, $key, $default, $onlyPara $this->assertEquals($expected, $input->getParameterOption($key, $default, $onlyParams), '->getParameterOption() returns the expected value'); } - public function provideGetParameterOptionValues() + public static function provideGetParameterOptionValues() { return [ [['app/console', 'foo:bar'], '-e', 'default', false, 'default'], diff --git a/Tests/Input/ArrayInputTest.php b/Tests/Input/ArrayInputTest.php index 5777c44b7..733322490 100644 --- a/Tests/Input/ArrayInputTest.php +++ b/Tests/Input/ArrayInputTest.php @@ -74,7 +74,7 @@ public function testParseOptions($input, $options, $expectedOptions, $message) $this->assertEquals($expectedOptions, $input->getOptions(), $message); } - public function provideOptions() + public static function provideOptions() { return [ [ @@ -133,7 +133,7 @@ public function testParseInvalidInput($parameters, $definition, $expectedExcepti new ArrayInput($parameters, $definition); } - public function provideInvalidInput() + public static function provideInvalidInput() { return [ [ diff --git a/Tests/Input/InputDefinitionTest.php b/Tests/Input/InputDefinitionTest.php index 11c6ae165..39157af8f 100644 --- a/Tests/Input/InputDefinitionTest.php +++ b/Tests/Input/InputDefinitionTest.php @@ -367,7 +367,7 @@ public function testGetSynopsis(InputDefinition $definition, $expectedSynopsis, $this->assertEquals($expectedSynopsis, $definition->getSynopsis(), $message ? '->getSynopsis() '.$message : ''); } - public function getGetSynopsisData() + public static function getGetSynopsisData() { return [ [new InputDefinition([new InputOption('foo')]), '[--foo]', 'puts optional options in square brackets'], diff --git a/Tests/Input/StringInputTest.php b/Tests/Input/StringInputTest.php index 2bd40dec9..c55256c03 100644 --- a/Tests/Input/StringInputTest.php +++ b/Tests/Input/StringInputTest.php @@ -43,7 +43,7 @@ public function testInputOptionWithGivenString() $this->assertEquals('bar', $input->getOption('foo')); } - public function getTokenizeData() + public static function getTokenizeData() { return [ ['', [], '->tokenize() parses an empty string'], diff --git a/Tests/Logger/ConsoleLoggerTest.php b/Tests/Logger/ConsoleLoggerTest.php index 3585bde63..4a96ddb15 100644 --- a/Tests/Logger/ConsoleLoggerTest.php +++ b/Tests/Logger/ConsoleLoggerTest.php @@ -69,7 +69,7 @@ public function testOutputMapping($logLevel, $outputVerbosity, $isOutput, $addVe $this->assertEquals($isOutput ? "[$logLevel] foo bar".\PHP_EOL : '', $logs); } - public function provideOutputMappingParams() + public static function provideOutputMappingParams() { $quietMap = [LogLevel::EMERGENCY => OutputInterface::VERBOSITY_QUIET]; @@ -123,7 +123,7 @@ public function testLogsAtAllLevels($level, $message) $this->assertEquals($expected, $this->getLogs()); } - public function provideLevelsAndMessages() + public static function provideLevelsAndMessages() { return [ LogLevel::EMERGENCY => [LogLevel::EMERGENCY, 'message of level emergency with context: {user}'], diff --git a/Tests/Output/OutputTest.php b/Tests/Output/OutputTest.php index 330064973..f337c4ddd 100644 --- a/Tests/Output/OutputTest.php +++ b/Tests/Output/OutputTest.php @@ -104,7 +104,7 @@ public function testWriteRawMessage($message, $type, $expectedOutput) $this->assertEquals($expectedOutput, $output->output); } - public function provideWriteArguments() + public static function provideWriteArguments() { return [ ['foo', Output::OUTPUT_RAW, "foo\n"], @@ -161,7 +161,7 @@ public function testWriteWithVerbosityOption($verbosity, $expected, $msg) $this->assertEquals($expected, $output->output, $msg); } - public function verbosityProvider() + public static function verbosityProvider() { return [ [Output::VERBOSITY_QUIET, '2', '->write() in QUIET mode only outputs when an explicit QUIET verbosity is passed'], diff --git a/Tests/Question/ChoiceQuestionTest.php b/Tests/Question/ChoiceQuestionTest.php index a7a2dfba4..d8b1f10ec 100644 --- a/Tests/Question/ChoiceQuestionTest.php +++ b/Tests/Question/ChoiceQuestionTest.php @@ -39,7 +39,7 @@ public function testSelectUseCases($multiSelect, $answers, $expected, $message, } } - public function selectUseCases() + public static function selectUseCases() { return [ [ @@ -119,7 +119,7 @@ public function testSelectAssociativeChoices($providedAnswer, $expectedValue) $this->assertSame($expectedValue, $question->getValidator()($providedAnswer)); } - public function selectAssociativeChoicesProvider() + public static function selectAssociativeChoicesProvider() { return [ 'select "0" choice by key' => ['0', '0'], diff --git a/Tests/Question/ConfirmationQuestionTest.php b/Tests/Question/ConfirmationQuestionTest.php index 83899772a..44f4c870b 100644 --- a/Tests/Question/ConfirmationQuestionTest.php +++ b/Tests/Question/ConfirmationQuestionTest.php @@ -30,7 +30,7 @@ public function testDefaultRegexUsecases($default, $answers, $expected, $message } } - public function normalizerUsecases() + public static function normalizerUsecases() { return [ [ diff --git a/Tests/Question/QuestionTest.php b/Tests/Question/QuestionTest.php index 55e9d58d4..e6b6fbee0 100644 --- a/Tests/Question/QuestionTest.php +++ b/Tests/Question/QuestionTest.php @@ -24,7 +24,7 @@ protected function setUp(): void $this->question = new Question('Test question'); } - public function providerTrueFalse() + public static function providerTrueFalse() { return [[true], [false]]; } @@ -104,7 +104,7 @@ public function testIsHiddenFallbackDefault() self::assertTrue($this->question->isHiddenFallback()); } - public function providerGetSetAutocompleterValues() + public static function providerGetSetAutocompleterValues() { return [ 'array' => [ @@ -135,7 +135,7 @@ public function testGetSetAutocompleterValues($values, $expectValues) ); } - public function providerSetAutocompleterValuesInvalid() + public static function providerSetAutocompleterValuesInvalid() { return [ ['Potato'], @@ -229,7 +229,7 @@ function (string $input): array { return []; } $this->assertNull($exception); } - public function providerGetSetValidator() + public static function providerGetSetValidator() { return [ [function ($input) { return $input; }], @@ -251,7 +251,7 @@ public function testGetValidatorDefault() self::assertNull($this->question->getValidator()); } - public function providerGetSetMaxAttempts() + public static function providerGetSetMaxAttempts() { return [[1], [5], [null]]; } @@ -265,7 +265,7 @@ public function testGetSetMaxAttempts($attempts) self::assertSame($attempts, $this->question->getMaxAttempts()); } - public function providerSetMaxAttemptsInvalid() + public static function providerSetMaxAttemptsInvalid() { return [[0], [-1]]; } diff --git a/Tests/Style/SymfonyStyleTest.php b/Tests/Style/SymfonyStyleTest.php index 74c240340..2edbcdfab 100644 --- a/Tests/Style/SymfonyStyleTest.php +++ b/Tests/Style/SymfonyStyleTest.php @@ -69,14 +69,14 @@ public function testInteractiveOutputs($inputCommandFilepath, $outputFilepath) $this->assertStringEqualsFile($outputFilepath, $this->tester->getDisplay(true)); } - public function inputInteractiveCommandToOutputFilesProvider() + public static function inputInteractiveCommandToOutputFilesProvider() { $baseDir = __DIR__.'/../Fixtures/Style/SymfonyStyle'; return array_map(null, glob($baseDir.'/command/interactive_command_*.php'), glob($baseDir.'/output/interactive_output_*.txt')); } - public function inputCommandToOutputFilesProvider() + public static function inputCommandToOutputFilesProvider() { $baseDir = __DIR__.'/../Fixtures/Style/SymfonyStyle'; diff --git a/Tests/Tester/Constraint/CommandIsSuccessfulTest.php b/Tests/Tester/Constraint/CommandIsSuccessfulTest.php index 2de8ac345..7a2b4c719 100644 --- a/Tests/Tester/Constraint/CommandIsSuccessfulTest.php +++ b/Tests/Tester/Constraint/CommandIsSuccessfulTest.php @@ -47,7 +47,7 @@ public function testUnsuccessfulCommand(string $expectedException, int $exitCode $this->fail(); } - public function providesUnsuccessful(): iterable + public static function providesUnsuccessful(): iterable { yield 'Failed' => ['Command failed.', Command::FAILURE]; yield 'Invalid' => ['Command was invalid.', Command::INVALID]; From bc04b7a3c23fd36e4b165afe7947b3d00989677b Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 14 Feb 2023 15:04:49 +0100 Subject: [PATCH 06/20] use proper methods to assert exception messages contain certain strings --- Tests/Style/SymfonyStyleTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Style/SymfonyStyleTest.php b/Tests/Style/SymfonyStyleTest.php index 2edbcdfab..621767bf7 100644 --- a/Tests/Style/SymfonyStyleTest.php +++ b/Tests/Style/SymfonyStyleTest.php @@ -151,7 +151,7 @@ public function testCreateTableWithoutConsoleOutput() $style = new SymfonyStyle($input, $output); $this->expectException(RuntimeException::class); - $this->expectDeprecationMessage('Output should be an instance of "Symfony\Component\Console\Output\ConsoleSectionOutput"'); + $this->expectExceptionMessage('Output should be an instance of "Symfony\Component\Console\Output\ConsoleSectionOutput"'); $style->createTable()->appendRow(['row']); } From a39ab00a8597cb0cab22dd4fb0ad24e1b6ca2a9a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 16 Feb 2023 10:33:00 +0100 Subject: [PATCH 07/20] CS fix --- Command/Command.php | 8 ++++---- Tester/TesterTrait.php | 8 ++++---- Tests/ApplicationTest.php | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Command/Command.php b/Command/Command.php index e0593e17a..cfa18361e 100644 --- a/Command/Command.php +++ b/Command/Command.php @@ -429,9 +429,9 @@ public function getNativeDefinition() * @param int|null $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL * @param mixed $default The default value (for InputArgument::OPTIONAL mode only) * - * @throws InvalidArgumentException When argument mode is not valid - * * @return $this + * + * @throws InvalidArgumentException When argument mode is not valid */ public function addArgument(string $name, int $mode = null, string $description = '', $default = null) { @@ -450,9 +450,9 @@ public function addArgument(string $name, int $mode = null, string $description * @param int|null $mode The option mode: One of the InputOption::VALUE_* constants * @param mixed $default The default value (must be null for InputOption::VALUE_NONE) * - * @throws InvalidArgumentException If option mode is invalid or incompatible - * * @return $this + * + * @throws InvalidArgumentException If option mode is invalid or incompatible */ public function addOption(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null) { diff --git a/Tester/TesterTrait.php b/Tester/TesterTrait.php index 40bc58177..f454bbf9d 100644 --- a/Tester/TesterTrait.php +++ b/Tester/TesterTrait.php @@ -35,9 +35,9 @@ trait TesterTrait /** * Gets the display returned by the last execution of the command or application. * - * @throws \RuntimeException If it's called before the execute method - * * @return string + * + * @throws \RuntimeException If it's called before the execute method */ public function getDisplay(bool $normalize = false) { @@ -103,9 +103,9 @@ public function getOutput() /** * Gets the status code returned by the last execution of the command or application. * - * @throws \RuntimeException If it's called before the execute method - * * @return int + * + * @throws \RuntimeException If it's called before the execute method */ public function getStatusCode() { diff --git a/Tests/ApplicationTest.php b/Tests/ApplicationTest.php index 4e4c032b8..b331c665b 100644 --- a/Tests/ApplicationTest.php +++ b/Tests/ApplicationTest.php @@ -2118,7 +2118,7 @@ public function __construct(bool $emitsSignal = true) protected function execute(InputInterface $input, OutputInterface $output): int { if ($this->emitsSignal) { - posix_kill(posix_getpid(), SIGUSR1); + posix_kill(posix_getpid(), \SIGUSR1); } for ($i = 0; $i < $this->loop; ++$i) { From 0a3c3710f10b7ea6ed31f4bd3f1fbea380603718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Sat, 25 Feb 2023 10:00:28 -0500 Subject: [PATCH 08/20] [Console] Fix fatal error when accessing Application::signalRegistry without pcntl --- Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application.php b/Application.php index d4ec1be09..41548a3e9 100644 --- a/Application.php +++ b/Application.php @@ -87,7 +87,7 @@ class Application implements ResetInterface private string $defaultCommand; private bool $singleCommand = false; private bool $initialized = false; - private SignalRegistry $signalRegistry; + private ?SignalRegistry $signalRegistry = null; private array $signalsToDispatchEvent = []; public function __construct(string $name = 'UNKNOWN', string $version = 'UNKNOWN') From c77433ddc6cdc689caf48065d9ea22ca0853fbd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Fri, 24 Feb 2023 13:02:50 -0500 Subject: [PATCH 09/20] [Console] Fix ApplicationTest::testSetSignalsToDispatchEvent() when ran alone --- Tests/ApplicationTest.php | 43 +++++++++++++++---- ...on.dont_run_alternative_namespace_name.txt | 8 ++++ 2 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 Tests/Fixtures/application.dont_run_alternative_namespace_name.txt diff --git a/Tests/ApplicationTest.php b/Tests/ApplicationTest.php index b331c665b..698a9679b 100644 --- a/Tests/ApplicationTest.php +++ b/Tests/ApplicationTest.php @@ -64,6 +64,16 @@ protected function tearDown(): void putenv('SHELL_VERBOSITY'); unset($_ENV['SHELL_VERBOSITY']); unset($_SERVER['SHELL_VERBOSITY']); + + if (\function_exists('pcntl_signal')) { + // We reset all signals to their default value to avoid side effects + for ($i = 1; $i <= 15; ++$i) { + if (9 === $i) { + continue; + } + pcntl_signal($i, SIG_DFL); + } + } } public static function setUpBeforeClass(): void @@ -508,15 +518,7 @@ public function testDontRunAlternativeNamespaceName() $application->setAutoExit(false); $tester = new ApplicationTester($application); $tester->run(['command' => 'foos:bar1'], ['decorated' => false]); - $this->assertSame(' - - There are no commands defined in the "foos" namespace. - - Did you mean this? - foo - - -', $tester->getDisplay(true)); + $this->assertStringEqualsFile(self::$fixturesPath.'/application.dont_run_alternative_namespace_name.txt', $tester->getDisplay(true)); } public function testCanRunAlternativeCommandName() @@ -1956,15 +1958,38 @@ public function testSetSignalsToDispatchEvent() $dispatcher = new EventDispatcher(); $dispatcher->addSubscriber($subscriber); + // Since there is no signal handler, and by default PHP will stop even + // on SIGUSR1, we need to register a blank handler to avoid the process + // being stopped. + $blankHandlerSignaled = false; + pcntl_signal(\SIGUSR1, function () use (&$blankHandlerSignaled) { + $blankHandlerSignaled = true; + }); + $application = $this->createSignalableApplication($command, $dispatcher); $application->setSignalsToDispatchEvent(\SIGUSR2); $this->assertSame(0, $application->run(new ArrayInput(['signal']))); $this->assertFalse($subscriber->signaled); + $this->assertTrue($blankHandlerSignaled); + + // We reset the blank handler to false to make sure it is called again + $blankHandlerSignaled = false; + + $application = $this->createSignalableApplication($command, $dispatcher); + $application->setSignalsToDispatchEvent(\SIGUSR1); + $this->assertSame(1, $application->run(new ArrayInput(['signal']))); + $this->assertTrue($subscriber->signaled); + $this->assertTrue($blankHandlerSignaled); + + // And now we test without the blank handler + $blankHandlerSignaled = false; + pcntl_signal(\SIGUSR1, SIG_DFL); $application = $this->createSignalableApplication($command, $dispatcher); $application->setSignalsToDispatchEvent(\SIGUSR1); $this->assertSame(1, $application->run(new ArrayInput(['signal']))); $this->assertTrue($subscriber->signaled); + $this->assertFalse($blankHandlerSignaled); } public function testSignalableCommandInterfaceWithoutSignals() diff --git a/Tests/Fixtures/application.dont_run_alternative_namespace_name.txt b/Tests/Fixtures/application.dont_run_alternative_namespace_name.txt new file mode 100644 index 000000000..430edde20 --- /dev/null +++ b/Tests/Fixtures/application.dont_run_alternative_namespace_name.txt @@ -0,0 +1,8 @@ + + + There are no commands defined in the "foos" namespace. + + Did you mean this? + foo + + From bbfc3e4f30e24c15246c73c4c397b0a0b161427c Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Mon, 6 Mar 2023 21:48:01 +0100 Subject: [PATCH 10/20] [Tests] Replace `setMethods()` by `onlyMethods()` and `addMethods()` --- Tests/ApplicationTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Tests/ApplicationTest.php b/Tests/ApplicationTest.php index 698a9679b..d06abcb8c 100644 --- a/Tests/ApplicationTest.php +++ b/Tests/ApplicationTest.php @@ -716,7 +716,7 @@ public function testFindAlternativesOutput() public function testFindNamespaceDoesNotFailOnDeepSimilarNamespaces() { - $application = $this->getMockBuilder(Application::class)->setMethods(['getNamespaces'])->getMock(); + $application = $this->getMockBuilder(Application::class)->onlyMethods(['getNamespaces'])->getMock(); $application->expects($this->once()) ->method('getNamespaces') ->willReturn(['foo:sublong', 'bar:sub']); @@ -876,7 +876,7 @@ public function testRenderExceptionEscapesLines() public function testRenderExceptionLineBreaks() { - $application = $this->getMockBuilder(Application::class)->setMethods(['getTerminalWidth'])->getMock(); + $application = $this->getMockBuilder(Application::class)->addMethods(['getTerminalWidth'])->getMock(); $application->setAutoExit(false); $application->expects($this->any()) ->method('getTerminalWidth') @@ -1103,7 +1103,7 @@ public function testRunReturnsIntegerExitCode() { $exception = new \Exception('', 4); - $application = $this->getMockBuilder(Application::class)->setMethods(['doRun'])->getMock(); + $application = $this->getMockBuilder(Application::class)->onlyMethods(['doRun'])->getMock(); $application->setAutoExit(false); $application->expects($this->once()) ->method('doRun') @@ -1142,7 +1142,7 @@ public function testRunReturnsExitCodeOneForExceptionCodeZero() { $exception = new \Exception('', 0); - $application = $this->getMockBuilder(Application::class)->setMethods(['doRun'])->getMock(); + $application = $this->getMockBuilder(Application::class)->onlyMethods(['doRun'])->getMock(); $application->setAutoExit(false); $application->expects($this->once()) ->method('doRun') @@ -1185,7 +1185,7 @@ public function testRunReturnsExitCodeOneForNegativeExceptionCode($exceptionCode { $exception = new \Exception('', $exceptionCode); - $application = $this->getMockBuilder(Application::class)->setMethods(['doRun'])->getMock(); + $application = $this->getMockBuilder(Application::class)->onlyMethods(['doRun'])->getMock(); $application->setAutoExit(false); $application->expects($this->once()) ->method('doRun') From 7ec6e8b49aa2be157b783eb793c979f8cdaa69d7 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 14 Mar 2023 15:59:20 +0100 Subject: [PATCH 11/20] Fix some Composer keywords --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 9a565068c..4fa4964a1 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "symfony/console", "type": "library", "description": "Eases the creation of beautiful and testable command line interfaces", - "keywords": ["console", "cli", "command line", "terminal"], + "keywords": ["console", "cli", "command-line", "terminal"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ From 3cd51fd2e6c461ca678f84d419461281bd87a0a8 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 3 Feb 2023 10:25:44 +0100 Subject: [PATCH 12/20] [VarDumper] Disable links for IntelliJ platform --- Formatter/OutputFormatterStyle.php | 3 +- Tests/Formatter/OutputFormatterTest.php | 45 +++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/Formatter/OutputFormatterStyle.php b/Formatter/OutputFormatterStyle.php index 0fb36ac63..8370ba058 100644 --- a/Formatter/OutputFormatterStyle.php +++ b/Formatter/OutputFormatterStyle.php @@ -96,7 +96,8 @@ public function apply(string $text) { if (null === $this->handlesHrefGracefully) { $this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') - && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100); + && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100) + && !isset($_SERVER['IDEA_INITIAL_DIRECTORY']); } if (null !== $this->href && $this->handlesHrefGracefully) { diff --git a/Tests/Formatter/OutputFormatterTest.php b/Tests/Formatter/OutputFormatterTest.php index 84eb8d87f..203f5a3ca 100644 --- a/Tests/Formatter/OutputFormatterTest.php +++ b/Tests/Formatter/OutputFormatterTest.php @@ -245,8 +245,14 @@ public function testFormatterHasStyles() /** * @dataProvider provideDecoratedAndNonDecoratedOutput */ - public function testNotDecoratedFormatter(string $input, string $expectedNonDecoratedOutput, string $expectedDecoratedOutput, string $terminalEmulator = 'foo') - { + public function testNotDecoratedFormatterOnJediTermEmulator( + string $input, + string $expectedNonDecoratedOutput, + string $expectedDecoratedOutput, + bool $shouldBeJediTerm = false + ) { + $terminalEmulator = $shouldBeJediTerm ? 'JetBrains-JediTerm' : 'Unknown'; + $prevTerminalEmulator = getenv('TERMINAL_EMULATOR'); putenv('TERMINAL_EMULATOR='.$terminalEmulator); @@ -258,6 +264,39 @@ public function testNotDecoratedFormatter(string $input, string $expectedNonDeco } } + /** + * @dataProvider provideDecoratedAndNonDecoratedOutput + */ + public function testNotDecoratedFormatterOnIDEALikeEnvironment( + string $input, + string $expectedNonDecoratedOutput, + string $expectedDecoratedOutput, + bool $expectsIDEALikeTerminal = false + ) { + // Backup previous env variable + $previousValue = $_SERVER['IDEA_INITIAL_DIRECTORY'] ?? null; + $hasPreviousValue = \array_key_exists('IDEA_INITIAL_DIRECTORY', $_SERVER); + + if ($expectsIDEALikeTerminal) { + $_SERVER['IDEA_INITIAL_DIRECTORY'] = __DIR__; + } elseif ($hasPreviousValue) { + // Forcibly remove the variable because the test runner may contain it + unset($_SERVER['IDEA_INITIAL_DIRECTORY']); + } + + try { + $this->assertEquals($expectedDecoratedOutput, (new OutputFormatter(true))->format($input)); + $this->assertEquals($expectedNonDecoratedOutput, (new OutputFormatter(false))->format($input)); + } finally { + // Rollback previous env state + if ($hasPreviousValue) { + $_SERVER['IDEA_INITIAL_DIRECTORY'] = $previousValue; + } else { + unset($_SERVER['IDEA_INITIAL_DIRECTORY']); + } + } + } + public static function provideDecoratedAndNonDecoratedOutput() { return [ @@ -268,7 +307,7 @@ public static function provideDecoratedAndNonDecoratedOutput() ['some text with inline style', 'some text with inline style', "\033[31msome text with inline style\033[39m"], ['some URL', 'some URL', "\033]8;;idea://open/?file=/path/SomeFile.php&line=12\033\\some URL\033]8;;\033\\"], ['>some URL with \', 'some URL with ', "\033]8;;https://example.com/\033\\some URL with \033]8;;\033\\"], - ['some URL', 'some URL', 'some URL', 'JetBrains-JediTerm'], + ['some URL', 'some URL', 'some URL', true], ]; } From 85e2e03506797cbec86d2cc4c1dbd67993076cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Wed, 22 Mar 2023 11:10:23 +0100 Subject: [PATCH 13/20] [Console] Add missing ZSH mention in DumpCompletionCommand help --- Command/DumpCompletionCommand.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Command/DumpCompletionCommand.php b/Command/DumpCompletionCommand.php index 1ad1c0e7b..6a322c929 100644 --- a/Command/DumpCompletionCommand.php +++ b/Command/DumpCompletionCommand.php @@ -52,10 +52,12 @@ protected function configure() default => ['~/.bashrc', "/etc/bash_completion.d/$commandName"], }; + $supportedShells = implode(', ', $this->getSupportedShells()); + $this ->setHelp(<<%command.name% command dumps the shell completion script required -to use shell autocompletion (currently, bash and fish completion is supported). +to use shell autocompletion (currently, {$supportedShells} completion are supported). Static installation ------------------- From 3105944c52330eb286938ba481ff33fa7be15c3b Mon Sep 17 00:00:00 2001 From: aleksandr-shevchenko Date: Mon, 10 Apr 2023 14:08:12 +0400 Subject: [PATCH 14/20] [Console] Restoring the ability to output unicode text to the Win10 console Restoring the ability to output unicode text to the Win10 console after corrupting the console on line 224 --- Terminal.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Terminal.php b/Terminal.php index 08c53535b..24cef5340 100644 --- a/Terminal.php +++ b/Terminal.php @@ -157,6 +157,8 @@ private static function readFromProcess(string $command): ?string 2 => ['pipe', 'w'], ]; + $cp = \function_exists('sapi_windows_cp_set') ? sapi_windows_cp_get() : 0; + $process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true]); if (!\is_resource($process)) { return null; @@ -167,6 +169,10 @@ private static function readFromProcess(string $command): ?string fclose($pipes[2]); proc_close($process); + if ($cp) { + sapi_windows_cp_set($cp); + } + return $info; } } From 79e7e16e187a107e79dd67a531207d2eb9420444 Mon Sep 17 00:00:00 2001 From: cay89 Date: Thu, 5 Jan 2023 13:43:03 +0100 Subject: [PATCH 15/20] [Console] Fix computing column width containing multibyte chars --- Helper/Table.php | 2 +- Tests/Helper/TableTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Helper/Table.php b/Helper/Table.php index 3f2d99145..5c3447ab3 100644 --- a/Helper/Table.php +++ b/Helper/Table.php @@ -805,7 +805,7 @@ private function calculateColumnsWidth(iterable $groups) $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell); $textLength = Helper::width($textContent); if ($textLength > 0) { - $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan())); + $contentColumns = mb_str_split($textContent, ceil($textLength / $cell->getColspan())); foreach ($contentColumns as $position => $content) { $row[$i + $position] = $content; } diff --git a/Tests/Helper/TableTest.php b/Tests/Helper/TableTest.php index 2d70bd271..53001d428 100644 --- a/Tests/Helper/TableTest.php +++ b/Tests/Helper/TableTest.php @@ -316,7 +316,7 @@ public function renderProvider() ], new TableSeparator(), [ - new TableCell('Cupiditate dicta atque porro, tempora exercitationem modi animi nulla nemo vel nihil!', ['colspan' => 3]), + new TableCell('Cupìdĭtâte díctá âtquè pôrrò, tèmpórà exercitátìónèm mòdí ânìmí núllà nèmò vèl níhìl!', ['colspan' => 3]), ], ], 'default', @@ -333,7 +333,7 @@ public function renderProvider() | 9971-5-0210-0 | A Tale of | | | Two Cities | +-------------------------------+-------------------------------+-----------------------------+ -| Cupiditate dicta atque porro, tempora exercitationem modi animi nulla nemo vel nihil! | +| Cupìdĭtâte díctá âtquè pôrrò, tèmpórà exercitátìónèm mòdí ânìmí núllà nèmò vèl níhìl! | +-------------------------------+-------------------------------+-----------------------------+ TABLE From 15ac6602ed2c1a7de1848748e04dbd5f4dc84d11 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Fri, 21 Apr 2023 19:34:39 +0200 Subject: [PATCH 16/20] Fix the usage of the zsh completion through the fpath discovery Zsh completion files registered through the fpath discovery mecanism have 2 requirements: - the file name must have a `_` prefix - the file must start with a `#compdef` comment describing the registration for that file. The file can then either execute the completion logic directly or call `compdef` to register a function for completion. Keeping the second approach allows to use the same generated script for the global use case than for a sourced configuration script. --- Command/DumpCompletionCommand.php | 2 +- Resources/completion.zsh | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Command/DumpCompletionCommand.php b/Command/DumpCompletionCommand.php index 6a322c929..caf3bd15b 100644 --- a/Command/DumpCompletionCommand.php +++ b/Command/DumpCompletionCommand.php @@ -48,7 +48,7 @@ protected function configure() $shell = $this->guessShell(); [$rcFile, $completionFile] = match ($shell) { 'fish' => ['~/.config/fish/config.fish', "/etc/fish/completions/$commandName.fish"], - 'zsh' => ['~/.zshrc', '$fpath[1]/'.$commandName], + 'zsh' => ['~/.zshrc', '$fpath[1]/_'.$commandName], default => ['~/.bashrc', "/etc/bash_completion.d/$commandName"], }; diff --git a/Resources/completion.zsh b/Resources/completion.zsh index 97a9e88cd..ff76fe5fa 100644 --- a/Resources/completion.zsh +++ b/Resources/completion.zsh @@ -1,3 +1,5 @@ +#compdef {{ COMMAND_NAME }} + # This file is part of the Symfony package. # # (c) Fabien Potencier From 930de4346ba192c482661d700bf5b9a05620eeb2 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Fri, 21 Apr 2023 20:01:19 +0200 Subject: [PATCH 17/20] Fix the list of supported shells for completions in a phar Using glob inside a phar does not work (it does not find anything). Using a DirectoryIterator on the other hand works with phars. This allows this command to compute the list of supported shells properly when used inside a phar. --- Command/DumpCompletionCommand.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Command/DumpCompletionCommand.php b/Command/DumpCompletionCommand.php index 518d606a0..6f809e2f1 100644 --- a/Command/DumpCompletionCommand.php +++ b/Command/DumpCompletionCommand.php @@ -132,8 +132,14 @@ private function tailDebugLog(string $commandName, OutputInterface $output): voi */ private function getSupportedShells(): array { - return array_map(function ($f) { - return pathinfo($f, \PATHINFO_EXTENSION); - }, glob(__DIR__.'/../Resources/completion.*')); + $shells = []; + + foreach (new \DirectoryIterator(__DIR__.'/../Resources/') as $file) { + if (str_starts_with($file->getBasename(), 'completion.') && $file->isFile()) { + $shells[] = $file->getExtension(); + } + } + + return $shells; } } From 90f21e27d0d88ce38720556dd164d4a1e4c3934c Mon Sep 17 00:00:00 2001 From: Dane Powell Date: Mon, 24 Apr 2023 11:47:29 -0700 Subject: [PATCH 18/20] trim(): Argument #1 () must be of type string, bool given --- Terminal.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Terminal.php b/Terminal.php index 24cef5340..04653d3bd 100644 --- a/Terminal.php +++ b/Terminal.php @@ -77,7 +77,8 @@ public static function hasSttyAvailable(): bool private static function initDimensions() { if ('\\' === \DIRECTORY_SEPARATOR) { - if (preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim(getenv('ANSICON')), $matches)) { + $ansicon = getenv('ANSICON'); + if (false !== $ansicon && preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim($ansicon), $matches)) { // extract [w, H] from "wxh (WxH)" // or [w, h] from "wxh" self::$width = (int) $matches[1]; From 8dd035ba2940121e2474cf559cd3b2404f532313 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 28 Apr 2023 15:32:52 +0200 Subject: [PATCH 19/20] Fix merge --- Command/DumpCompletionCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Command/DumpCompletionCommand.php b/Command/DumpCompletionCommand.php index 02a403714..5570ab329 100644 --- a/Command/DumpCompletionCommand.php +++ b/Command/DumpCompletionCommand.php @@ -143,7 +143,7 @@ private function tailDebugLog(string $commandName, OutputInterface $output): voi */ private function getSupportedShells(): array { - if (null !== $this->supportedShells) { + if (isset($this->supportedShells)) { return $this->supportedShells; } From 12288d9f4500f84a4d02254d4aa968b15488476f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 28 Apr 2023 15:37:34 +0200 Subject: [PATCH 20/20] Fix merge --- Command/DumpCompletionCommand.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Command/DumpCompletionCommand.php b/Command/DumpCompletionCommand.php index 5570ab329..10280f73a 100644 --- a/Command/DumpCompletionCommand.php +++ b/Command/DumpCompletionCommand.php @@ -154,6 +154,7 @@ private function getSupportedShells(): array $shells[] = $file->getExtension(); } } + sort($shells); return $this->supportedShells = $shells; }