CompleteCommandTest.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Console\Tests\Command;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\Console\Application;
  13. use Symfony\Component\Console\Command\Command;
  14. use Symfony\Component\Console\Command\CompleteCommand;
  15. use Symfony\Component\Console\Completion\CompletionInput;
  16. use Symfony\Component\Console\Completion\CompletionSuggestions;
  17. use Symfony\Component\Console\Completion\Output\BashCompletionOutput;
  18. use Symfony\Component\Console\Input\InputArgument;
  19. use Symfony\Component\Console\Output\OutputInterface;
  20. use Symfony\Component\Console\Tester\CommandTester;
  21. class CompleteCommandTest extends TestCase
  22. {
  23. private $command;
  24. private $application;
  25. private $tester;
  26. protected function setUp(): void
  27. {
  28. $this->command = new CompleteCommand();
  29. $this->application = new Application();
  30. $this->application->add(new CompleteCommandTest_HelloCommand());
  31. $this->command->setApplication($this->application);
  32. $this->tester = new CommandTester($this->command);
  33. }
  34. public function testRequiredShellOption()
  35. {
  36. $this->expectExceptionMessage('The "--shell" option must be set.');
  37. $this->execute([]);
  38. }
  39. public function testUnsupportedShellOption()
  40. {
  41. $this->expectExceptionMessage('Shell completion is not supported for your shell: "unsupported" (supported: "bash").');
  42. $this->execute(['--shell' => 'unsupported']);
  43. }
  44. public function testAdditionalShellSupport()
  45. {
  46. $this->command = new CompleteCommand(['supported' => BashCompletionOutput::class]);
  47. $this->command->setApplication($this->application);
  48. $this->tester = new CommandTester($this->command);
  49. $this->execute(['--shell' => 'supported', '--current' => '1', '--input' => ['bin/console']]);
  50. // verify that the default set of shells is still supported
  51. $this->execute(['--shell' => 'bash', '--current' => '1', '--input' => ['bin/console']]);
  52. $this->assertTrue(true);
  53. }
  54. /**
  55. * @dataProvider provideInputAndCurrentOptionValues
  56. */
  57. public function testInputAndCurrentOptionValidation(array $input, ?string $exceptionMessage)
  58. {
  59. if ($exceptionMessage) {
  60. $this->expectExceptionMessage($exceptionMessage);
  61. }
  62. $this->execute($input + ['--shell' => 'bash']);
  63. if (!$exceptionMessage) {
  64. $this->tester->assertCommandIsSuccessful();
  65. }
  66. }
  67. public static function provideInputAndCurrentOptionValues()
  68. {
  69. yield [[], 'The "--current" option must be set and it must be an integer'];
  70. yield [['--current' => 'a'], 'The "--current" option must be set and it must be an integer'];
  71. yield [['--current' => '1', '--input' => ['bin/console']], null];
  72. yield [['--current' => '2', '--input' => ['bin/console']], 'Current index is invalid, it must be the number of input tokens or one more.'];
  73. yield [['--current' => '1', '--input' => ['bin/console', 'cache:clear']], null];
  74. yield [['--current' => '2', '--input' => ['bin/console', 'cache:clear']], null];
  75. }
  76. /**
  77. * @dataProvider provideCompleteCommandNameInputs
  78. */
  79. public function testCompleteCommandName(array $input, array $suggestions)
  80. {
  81. $this->execute(['--current' => '1', '--input' => $input]);
  82. $this->assertEquals(implode("\n", $suggestions).\PHP_EOL, $this->tester->getDisplay());
  83. }
  84. public static function provideCompleteCommandNameInputs()
  85. {
  86. yield 'empty' => [['bin/console'], ['help', 'list', 'completion', 'hello', 'ahoy']];
  87. yield 'partial' => [['bin/console', 'he'], ['help', 'list', 'completion', 'hello', 'ahoy']];
  88. yield 'complete-shortcut-name' => [['bin/console', 'hell'], ['hello', 'ahoy']];
  89. yield 'complete-aliases' => [['bin/console', 'ah'], ['hello', 'ahoy']];
  90. }
  91. /**
  92. * @dataProvider provideCompleteCommandInputDefinitionInputs
  93. */
  94. public function testCompleteCommandInputDefinition(array $input, array $suggestions)
  95. {
  96. $this->execute(['--current' => '2', '--input' => $input]);
  97. $this->assertEquals(implode("\n", $suggestions).\PHP_EOL, $this->tester->getDisplay());
  98. }
  99. public static function provideCompleteCommandInputDefinitionInputs()
  100. {
  101. yield 'definition' => [['bin/console', 'hello', '-'], ['--help', '--quiet', '--verbose', '--version', '--ansi', '--no-ansi', '--no-interaction']];
  102. yield 'custom' => [['bin/console', 'hello'], ['Fabien', 'Robin', 'Wouter']];
  103. yield 'definition-aliased' => [['bin/console', 'ahoy', '-'], ['--help', '--quiet', '--verbose', '--version', '--ansi', '--no-ansi', '--no-interaction']];
  104. yield 'custom-aliased' => [['bin/console', 'ahoy'], ['Fabien', 'Robin', 'Wouter']];
  105. }
  106. private function execute(array $input)
  107. {
  108. // run in verbose mode to assert exceptions
  109. $this->tester->execute($input ? ($input + ['--shell' => 'bash']) : $input, ['verbosity' => OutputInterface::VERBOSITY_DEBUG]);
  110. }
  111. }
  112. class CompleteCommandTest_HelloCommand extends Command
  113. {
  114. public function configure(): void
  115. {
  116. $this->setName('hello')
  117. ->setAliases(['ahoy'])
  118. ->addArgument('name', InputArgument::REQUIRED)
  119. ;
  120. }
  121. public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
  122. {
  123. if ($input->mustSuggestArgumentValuesFor('name')) {
  124. $suggestions->suggestValues(['Fabien', 'Robin', 'Wouter']);
  125. }
  126. }
  127. }