1<?php 2 3namespace Symfony\Component\Console\Tests\Helper; 4 5use Symfony\Component\Console\Helper\FormatterHelper; 6use Symfony\Component\Console\Helper\HelperSet; 7use Symfony\Component\Console\Helper\SymfonyQuestionHelper; 8use Symfony\Component\Console\Output\StreamOutput; 9use Symfony\Component\Console\Question\ChoiceQuestion; 10use Symfony\Component\Console\Question\Question; 11 12/** 13 * @group tty 14 */ 15class SymfonyQuestionHelperTest extends AbstractQuestionHelperTest 16{ 17 public function testAskChoice() 18 { 19 $questionHelper = new SymfonyQuestionHelper(); 20 21 $helperSet = new HelperSet([new FormatterHelper()]); 22 $questionHelper->setHelperSet($helperSet); 23 24 $heroes = ['Superman', 'Batman', 'Spiderman']; 25 26 $inputStream = $this->getInputStream("\n1\n 1 \nFabien\n1\nFabien\n1\n0,2\n 0 , 2 \n\n\n"); 27 28 $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '2'); 29 $question->setMaxAttempts(1); 30 // first answer is an empty answer, we're supposed to receive the default value 31 $this->assertEquals('Spiderman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question)); 32 $this->assertOutputContains('What is your favorite superhero? [Spiderman]', $output); 33 34 $question = new ChoiceQuestion('What is your favorite superhero?', $heroes); 35 $question->setMaxAttempts(1); 36 $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); 37 $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); 38 39 $question = new ChoiceQuestion('What is your favorite superhero?', $heroes); 40 $question->setErrorMessage('Input "%s" is not a superhero!'); 41 $question->setMaxAttempts(2); 42 $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question)); 43 $this->assertOutputContains('Input "Fabien" is not a superhero!', $output); 44 45 try { 46 $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '1'); 47 $question->setMaxAttempts(1); 48 $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question); 49 $this->fail(); 50 } catch (\InvalidArgumentException $e) { 51 $this->assertEquals('Value "Fabien" is invalid', $e->getMessage()); 52 } 53 54 $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, null); 55 $question->setMaxAttempts(1); 56 $question->setMultiselect(true); 57 58 $this->assertEquals(['Batman'], $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); 59 $this->assertEquals(['Superman', 'Spiderman'], $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); 60 $this->assertEquals(['Superman', 'Spiderman'], $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); 61 62 $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '0,1'); 63 $question->setMaxAttempts(1); 64 $question->setMultiselect(true); 65 66 $this->assertEquals(['Superman', 'Batman'], $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question)); 67 $this->assertOutputContains('What is your favorite superhero? [Superman, Batman]', $output); 68 69 $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, ' 0 , 1 '); 70 $question->setMaxAttempts(1); 71 $question->setMultiselect(true); 72 73 $this->assertEquals(['Superman', 'Batman'], $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question)); 74 $this->assertOutputContains('What is your favorite superhero? [Superman, Batman]', $output); 75 } 76 77 public function testAskChoiceWithChoiceValueAsDefault() 78 { 79 $questionHelper = new SymfonyQuestionHelper(); 80 $helperSet = new HelperSet([new FormatterHelper()]); 81 $questionHelper->setHelperSet($helperSet); 82 $question = new ChoiceQuestion('What is your favorite superhero?', ['Superman', 'Batman', 'Spiderman'], 'Batman'); 83 $question->setMaxAttempts(1); 84 85 $this->assertSame('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($this->getInputStream("Batman\n")), $output = $this->createOutputInterface(), $question)); 86 $this->assertOutputContains('What is your favorite superhero? [Batman]', $output); 87 } 88 89 public function testAskReturnsNullIfValidatorAllowsIt() 90 { 91 $questionHelper = new SymfonyQuestionHelper(); 92 $question = new Question('What is your favorite superhero?'); 93 $question->setValidator(function ($value) { return $value; }); 94 $input = $this->createStreamableInputInterfaceMock($this->getInputStream("\n")); 95 $this->assertNull($questionHelper->ask($input, $this->createOutputInterface(), $question)); 96 } 97 98 public function testAskEscapeDefaultValue() 99 { 100 $helper = new SymfonyQuestionHelper(); 101 $input = $this->createStreamableInputInterfaceMock($this->getInputStream('\\')); 102 $helper->ask($input, $output = $this->createOutputInterface(), new Question('Can I have a backslash?', '\\')); 103 104 $this->assertOutputContains('Can I have a backslash? [\]', $output); 105 } 106 107 public function testAskEscapeAndFormatLabel() 108 { 109 $helper = new SymfonyQuestionHelper(); 110 $input = $this->createStreamableInputInterfaceMock($this->getInputStream('Foo\\Bar')); 111 $helper->ask($input, $output = $this->createOutputInterface(), new Question('Do you want to use Foo\\Bar <comment>or</comment> Foo\\Baz\\?', 'Foo\\Baz')); 112 113 $this->assertOutputContains('Do you want to use Foo\\Bar or Foo\\Baz\\? [Foo\\Baz]:', $output); 114 } 115 116 public function testLabelTrailingBackslash() 117 { 118 $helper = new SymfonyQuestionHelper(); 119 $input = $this->createStreamableInputInterfaceMock($this->getInputStream('sure')); 120 $helper->ask($input, $output = $this->createOutputInterface(), new Question('Question with a trailing \\')); 121 122 $this->assertOutputContains('Question with a trailing \\', $output); 123 } 124 125 public function testAskThrowsExceptionOnMissingInput() 126 { 127 $this->expectException('Symfony\Component\Console\Exception\RuntimeException'); 128 $this->expectExceptionMessage('Aborted.'); 129 $dialog = new SymfonyQuestionHelper(); 130 $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), new Question('What\'s your name?')); 131 } 132 133 public function testChoiceQuestionPadding() 134 { 135 $choiceQuestion = new ChoiceQuestion('qqq', [ 136 'foo' => 'foo', 137 'żółw' => 'bar', 138 'łabądź' => 'baz', 139 ]); 140 141 (new SymfonyQuestionHelper())->ask( 142 $this->createStreamableInputInterfaceMock($this->getInputStream("foo\n")), 143 $output = $this->createOutputInterface(), 144 $choiceQuestion 145 ); 146 147 $this->assertOutputContains(<<<EOT 148 qqq: 149 [foo ] foo 150 [żółw ] bar 151 [łabądź] baz 152 > 153EOT 154 , $output, true); 155 } 156 157 public function testChoiceQuestionCustomPrompt() 158 { 159 $choiceQuestion = new ChoiceQuestion('qqq', ['foo']); 160 $choiceQuestion->setPrompt(' >ccc> '); 161 162 (new SymfonyQuestionHelper())->ask( 163 $this->createStreamableInputInterfaceMock($this->getInputStream("foo\n")), 164 $output = $this->createOutputInterface(), 165 $choiceQuestion 166 ); 167 168 $this->assertOutputContains(<<<EOT 169 qqq: 170 [0] foo 171 >ccc> 172EOT 173 , $output, true); 174 } 175 176 protected function getInputStream($input) 177 { 178 $stream = fopen('php://memory', 'r+', false); 179 fwrite($stream, $input); 180 rewind($stream); 181 182 return $stream; 183 } 184 185 protected function createOutputInterface() 186 { 187 $output = new StreamOutput(fopen('php://memory', 'r+', false)); 188 $output->setDecorated(false); 189 190 return $output; 191 } 192 193 protected function createInputInterfaceMock($interactive = true) 194 { 195 $mock = $this->getMockBuilder('Symfony\Component\Console\Input\InputInterface')->getMock(); 196 $mock->expects($this->any()) 197 ->method('isInteractive') 198 ->willReturn($interactive); 199 200 return $mock; 201 } 202 203 private function assertOutputContains($expected, StreamOutput $output, $normalize = false) 204 { 205 rewind($output->getStream()); 206 $stream = stream_get_contents($output->getStream()); 207 208 if ($normalize) { 209 $stream = str_replace(\PHP_EOL, "\n", $stream); 210 } 211 212 $this->assertStringContainsString($expected, $stream); 213 } 214} 215