3d19e800b4580a20d9d60c264b3f57bfe8b60f84
[yaffs-website] / vendor / symfony / console / Tests / Helper / QuestionHelperTest.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\Console\Tests\Helper;
13
14 use Symfony\Component\Console\Formatter\OutputFormatter;
15 use Symfony\Component\Console\Helper\QuestionHelper;
16 use Symfony\Component\Console\Helper\HelperSet;
17 use Symfony\Component\Console\Helper\FormatterHelper;
18 use Symfony\Component\Console\Output\StreamOutput;
19 use Symfony\Component\Console\Question\ChoiceQuestion;
20 use Symfony\Component\Console\Question\ConfirmationQuestion;
21 use Symfony\Component\Console\Question\Question;
22
23 /**
24  * @group tty
25  */
26 class QuestionHelperTest extends AbstractQuestionHelperTest
27 {
28     public function testAskChoice()
29     {
30         $questionHelper = new QuestionHelper();
31
32         $helperSet = new HelperSet(array(new FormatterHelper()));
33         $questionHelper->setHelperSet($helperSet);
34
35         $heroes = array('Superman', 'Batman', 'Spiderman');
36
37         $inputStream = $this->getInputStream("\n1\n  1  \nFabien\n1\nFabien\n1\n0,2\n 0 , 2  \n\n\n");
38
39         $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '2');
40         $question->setMaxAttempts(1);
41         // first answer is an empty answer, we're supposed to receive the default value
42         $this->assertEquals('Spiderman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
43
44         $question = new ChoiceQuestion('What is your favorite superhero?', $heroes);
45         $question->setMaxAttempts(1);
46         $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
47         $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
48
49         $question = new ChoiceQuestion('What is your favorite superhero?', $heroes);
50         $question->setErrorMessage('Input "%s" is not a superhero!');
51         $question->setMaxAttempts(2);
52         $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question));
53
54         rewind($output->getStream());
55         $stream = stream_get_contents($output->getStream());
56         $this->assertContains('Input "Fabien" is not a superhero!', $stream);
57
58         try {
59             $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '1');
60             $question->setMaxAttempts(1);
61             $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question);
62             $this->fail();
63         } catch (\InvalidArgumentException $e) {
64             $this->assertEquals('Value "Fabien" is invalid', $e->getMessage());
65         }
66
67         $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, null);
68         $question->setMaxAttempts(1);
69         $question->setMultiselect(true);
70
71         $this->assertEquals(array('Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
72         $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
73         $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
74
75         $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '0,1');
76         $question->setMaxAttempts(1);
77         $question->setMultiselect(true);
78
79         $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
80
81         $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, ' 0 , 1 ');
82         $question->setMaxAttempts(1);
83         $question->setMultiselect(true);
84
85         $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
86     }
87
88     public function testAsk()
89     {
90         $dialog = new QuestionHelper();
91
92         $inputStream = $this->getInputStream("\n8AM\n");
93
94         $question = new Question('What time is it?', '2PM');
95         $this->assertEquals('2PM', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
96
97         $question = new Question('What time is it?', '2PM');
98         $this->assertEquals('8AM', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question));
99
100         rewind($output->getStream());
101         $this->assertEquals('What time is it?', stream_get_contents($output->getStream()));
102     }
103
104     public function testAskWithAutocomplete()
105     {
106         if (!$this->hasSttyAvailable()) {
107             $this->markTestSkipped('`stty` is required to test autocomplete functionality');
108         }
109
110         // Acm<NEWLINE>
111         // Ac<BACKSPACE><BACKSPACE>s<TAB>Test<NEWLINE>
112         // <NEWLINE>
113         // <UP ARROW><UP ARROW><NEWLINE>
114         // <UP ARROW><UP ARROW><UP ARROW><UP ARROW><UP ARROW><TAB>Test<NEWLINE>
115         // <DOWN ARROW><NEWLINE>
116         // S<BACKSPACE><BACKSPACE><DOWN ARROW><DOWN ARROW><NEWLINE>
117         // F00<BACKSPACE><BACKSPACE>oo<TAB><NEWLINE>
118         $inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\nF00\177\177oo\t\n");
119
120         $dialog = new QuestionHelper();
121         $helperSet = new HelperSet(array(new FormatterHelper()));
122         $dialog->setHelperSet($helperSet);
123
124         $question = new Question('Please select a bundle', 'FrameworkBundle');
125         $question->setAutocompleterValues(array('AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle'));
126
127         $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
128         $this->assertEquals('AsseticBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
129         $this->assertEquals('FrameworkBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
130         $this->assertEquals('SecurityBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
131         $this->assertEquals('FooBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
132         $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
133         $this->assertEquals('AsseticBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
134         $this->assertEquals('FooBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
135     }
136
137     public function testAskWithAutocompleteWithNonSequentialKeys()
138     {
139         if (!$this->hasSttyAvailable()) {
140             $this->markTestSkipped('`stty` is required to test autocomplete functionality');
141         }
142
143         // <UP ARROW><UP ARROW><NEWLINE><DOWN ARROW><DOWN ARROW><NEWLINE>
144         $inputStream = $this->getInputStream("\033[A\033[A\n\033[B\033[B\n");
145
146         $dialog = new QuestionHelper();
147         $dialog->setHelperSet(new HelperSet(array(new FormatterHelper())));
148
149         $question = new ChoiceQuestion('Please select a bundle', array(1 => 'AcmeDemoBundle', 4 => 'AsseticBundle'));
150         $question->setMaxAttempts(1);
151
152         $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
153         $this->assertEquals('AsseticBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
154     }
155
156     public function testAskHiddenResponse()
157     {
158         if ('\\' === DIRECTORY_SEPARATOR) {
159             $this->markTestSkipped('This test is not supported on Windows');
160         }
161
162         $dialog = new QuestionHelper();
163
164         $question = new Question('What time is it?');
165         $question->setHidden(true);
166
167         $this->assertEquals('8AM', $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("8AM\n")), $this->createOutputInterface(), $question));
168     }
169
170     /**
171      * @dataProvider getAskConfirmationData
172      */
173     public function testAskConfirmation($question, $expected, $default = true)
174     {
175         $dialog = new QuestionHelper();
176
177         $inputStream = $this->getInputStream($question."\n");
178         $question = new ConfirmationQuestion('Do you like French fries?', $default);
179         $this->assertEquals($expected, $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question), 'confirmation question should '.($expected ? 'pass' : 'cancel'));
180     }
181
182     public function getAskConfirmationData()
183     {
184         return array(
185             array('', true),
186             array('', false, false),
187             array('y', true),
188             array('yes', true),
189             array('n', false),
190             array('no', false),
191         );
192     }
193
194     public function testAskConfirmationWithCustomTrueAnswer()
195     {
196         $dialog = new QuestionHelper();
197
198         $inputStream = $this->getInputStream("j\ny\n");
199         $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i');
200         $this->assertTrue($dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
201         $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i');
202         $this->assertTrue($dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
203     }
204
205     public function testAskAndValidate()
206     {
207         $dialog = new QuestionHelper();
208         $helperSet = new HelperSet(array(new FormatterHelper()));
209         $dialog->setHelperSet($helperSet);
210
211         $error = 'This is not a color!';
212         $validator = function ($color) use ($error) {
213             if (!in_array($color, array('white', 'black'))) {
214                 throw new \InvalidArgumentException($error);
215             }
216
217             return $color;
218         };
219
220         $question = new Question('What color was the white horse of Henry IV?', 'white');
221         $question->setValidator($validator);
222         $question->setMaxAttempts(2);
223
224         $inputStream = $this->getInputStream("\nblack\n");
225         $this->assertEquals('white', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
226         $this->assertEquals('black', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
227
228         try {
229             $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("green\nyellow\norange\n")), $this->createOutputInterface(), $question);
230             $this->fail();
231         } catch (\InvalidArgumentException $e) {
232             $this->assertEquals($error, $e->getMessage());
233         }
234     }
235
236     /**
237      * @dataProvider simpleAnswerProvider
238      */
239     public function testSelectChoiceFromSimpleChoices($providedAnswer, $expectedValue)
240     {
241         $possibleChoices = array(
242             'My environment 1',
243             'My environment 2',
244             'My environment 3',
245         );
246
247         $dialog = new QuestionHelper();
248         $helperSet = new HelperSet(array(new FormatterHelper()));
249         $dialog->setHelperSet($helperSet);
250
251         $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
252         $question->setMaxAttempts(1);
253         $answer = $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream($providedAnswer."\n")), $this->createOutputInterface(), $question);
254
255         $this->assertSame($expectedValue, $answer);
256     }
257
258     public function simpleAnswerProvider()
259     {
260         return array(
261             array(0, 'My environment 1'),
262             array(1, 'My environment 2'),
263             array(2, 'My environment 3'),
264             array('My environment 1', 'My environment 1'),
265             array('My environment 2', 'My environment 2'),
266             array('My environment 3', 'My environment 3'),
267         );
268     }
269
270     /**
271      * @dataProvider specialCharacterInMultipleChoice
272      */
273     public function testSpecialCharacterChoiceFromMultipleChoiceList($providedAnswer, $expectedValue)
274     {
275         $possibleChoices = array(
276             '.',
277             'src',
278         );
279
280         $dialog = new QuestionHelper();
281         $inputStream = $this->getInputStream($providedAnswer."\n");
282         $helperSet = new HelperSet(array(new FormatterHelper()));
283         $dialog->setHelperSet($helperSet);
284
285         $question = new ChoiceQuestion('Please select the directory', $possibleChoices);
286         $question->setMaxAttempts(1);
287         $question->setMultiselect(true);
288         $answer = $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question);
289
290         $this->assertSame($expectedValue, $answer);
291     }
292
293     public function specialCharacterInMultipleChoice()
294     {
295         return array(
296             array('.', array('.')),
297             array('., src', array('.', 'src')),
298         );
299     }
300
301     /**
302      * @dataProvider mixedKeysChoiceListAnswerProvider
303      */
304     public function testChoiceFromChoicelistWithMixedKeys($providedAnswer, $expectedValue)
305     {
306         $possibleChoices = array(
307             '0' => 'No environment',
308             '1' => 'My environment 1',
309             'env_2' => 'My environment 2',
310             3 => 'My environment 3',
311         );
312
313         $dialog = new QuestionHelper();
314         $helperSet = new HelperSet(array(new FormatterHelper()));
315         $dialog->setHelperSet($helperSet);
316
317         $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
318         $question->setMaxAttempts(1);
319         $answer = $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream($providedAnswer."\n")), $this->createOutputInterface(), $question);
320
321         $this->assertSame($expectedValue, $answer);
322     }
323
324     public function mixedKeysChoiceListAnswerProvider()
325     {
326         return array(
327             array('0', '0'),
328             array('No environment', '0'),
329             array('1', '1'),
330             array('env_2', 'env_2'),
331             array(3, '3'),
332             array('My environment 1', '1'),
333         );
334     }
335
336     /**
337      * @dataProvider answerProvider
338      */
339     public function testSelectChoiceFromChoiceList($providedAnswer, $expectedValue)
340     {
341         $possibleChoices = array(
342             'env_1' => 'My environment 1',
343             'env_2' => 'My environment',
344             'env_3' => 'My environment',
345         );
346
347         $dialog = new QuestionHelper();
348         $helperSet = new HelperSet(array(new FormatterHelper()));
349         $dialog->setHelperSet($helperSet);
350
351         $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
352         $question->setMaxAttempts(1);
353         $answer = $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream($providedAnswer."\n")), $this->createOutputInterface(), $question);
354
355         $this->assertSame($expectedValue, $answer);
356     }
357
358     /**
359      * @expectedException        \InvalidArgumentException
360      * @expectedExceptionMessage The provided answer is ambiguous. Value should be one of env_2 or env_3.
361      */
362     public function testAmbiguousChoiceFromChoicelist()
363     {
364         $possibleChoices = array(
365             'env_1' => 'My first environment',
366             'env_2' => 'My environment',
367             'env_3' => 'My environment',
368         );
369
370         $dialog = new QuestionHelper();
371         $helperSet = new HelperSet(array(new FormatterHelper()));
372         $dialog->setHelperSet($helperSet);
373
374         $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
375         $question->setMaxAttempts(1);
376
377         $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("My environment\n")), $this->createOutputInterface(), $question);
378     }
379
380     public function answerProvider()
381     {
382         return array(
383             array('env_1', 'env_1'),
384             array('env_2', 'env_2'),
385             array('env_3', 'env_3'),
386             array('My environment 1', 'env_1'),
387         );
388     }
389
390     public function testNoInteraction()
391     {
392         $dialog = new QuestionHelper();
393         $question = new Question('Do you have a job?', 'not yet');
394         $this->assertEquals('not yet', $dialog->ask($this->createStreamableInputInterfaceMock(null, false), $this->createOutputInterface(), $question));
395     }
396
397     /**
398      * @requires function mb_strwidth
399      */
400     public function testChoiceOutputFormattingQuestionForUtf8Keys()
401     {
402         $question = 'Lorem ipsum?';
403         $possibleChoices = array(
404             'foo' => 'foo',
405             'żółw' => 'bar',
406             'łabądź' => 'baz',
407         );
408         $outputShown = array(
409             $question,
410             '  [<info>foo   </info>] foo',
411             '  [<info>żółw  </info>] bar',
412             '  [<info>łabądź</info>] baz',
413         );
414         $output = $this->getMockBuilder('\Symfony\Component\Console\Output\OutputInterface')->getMock();
415         $output->method('getFormatter')->willReturn(new OutputFormatter());
416
417         $dialog = new QuestionHelper();
418         $helperSet = new HelperSet(array(new FormatterHelper()));
419         $dialog->setHelperSet($helperSet);
420
421         $output->expects($this->once())->method('writeln')->with($this->equalTo($outputShown));
422
423         $question = new ChoiceQuestion($question, $possibleChoices, 'foo');
424         $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("\n")), $output, $question);
425     }
426
427     /**
428      * @group legacy
429      */
430     public function testLegacyAskChoice()
431     {
432         $questionHelper = new QuestionHelper();
433
434         $helperSet = new HelperSet(array(new FormatterHelper()));
435         $questionHelper->setHelperSet($helperSet);
436
437         $heroes = array('Superman', 'Batman', 'Spiderman');
438
439         $questionHelper->setInputStream($this->getInputStream("\n1\n  1  \nFabien\n1\nFabien\n1\n0,2\n 0 , 2  \n\n\n"));
440
441         $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '2');
442         $question->setMaxAttempts(1);
443         // first answer is an empty answer, we're supposed to receive the default value
444         $this->assertEquals('Spiderman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
445
446         $question = new ChoiceQuestion('What is your favorite superhero?', $heroes);
447         $question->setMaxAttempts(1);
448         $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
449         $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
450
451         $question = new ChoiceQuestion('What is your favorite superhero?', $heroes);
452         $question->setErrorMessage('Input "%s" is not a superhero!');
453         $question->setMaxAttempts(2);
454         $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question));
455
456         rewind($output->getStream());
457         $stream = stream_get_contents($output->getStream());
458         $this->assertContains('Input "Fabien" is not a superhero!', $stream);
459
460         try {
461             $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '1');
462             $question->setMaxAttempts(1);
463             $questionHelper->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question);
464             $this->fail();
465         } catch (\InvalidArgumentException $e) {
466             $this->assertEquals('Value "Fabien" is invalid', $e->getMessage());
467         }
468
469         $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, null);
470         $question->setMaxAttempts(1);
471         $question->setMultiselect(true);
472
473         $this->assertEquals(array('Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
474         $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
475         $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
476
477         $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '0,1');
478         $question->setMaxAttempts(1);
479         $question->setMultiselect(true);
480
481         $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
482
483         $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, ' 0 , 1 ');
484         $question->setMaxAttempts(1);
485         $question->setMultiselect(true);
486
487         $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
488     }
489
490     /**
491      * @group legacy
492      */
493     public function testLegacyAsk()
494     {
495         $dialog = new QuestionHelper();
496
497         $dialog->setInputStream($this->getInputStream("\n8AM\n"));
498
499         $question = new Question('What time is it?', '2PM');
500         $this->assertEquals('2PM', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
501
502         $question = new Question('What time is it?', '2PM');
503         $this->assertEquals('8AM', $dialog->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question));
504
505         rewind($output->getStream());
506         $this->assertEquals('What time is it?', stream_get_contents($output->getStream()));
507     }
508
509     /**
510      * @group legacy
511      */
512     public function testLegacyAskWithAutocomplete()
513     {
514         if (!$this->hasSttyAvailable()) {
515             $this->markTestSkipped('`stty` is required to test autocomplete functionality');
516         }
517
518         // Acm<NEWLINE>
519         // Ac<BACKSPACE><BACKSPACE>s<TAB>Test<NEWLINE>
520         // <NEWLINE>
521         // <UP ARROW><UP ARROW><NEWLINE>
522         // <UP ARROW><UP ARROW><UP ARROW><UP ARROW><UP ARROW><TAB>Test<NEWLINE>
523         // <DOWN ARROW><NEWLINE>
524         // S<BACKSPACE><BACKSPACE><DOWN ARROW><DOWN ARROW><NEWLINE>
525         // F00<BACKSPACE><BACKSPACE>oo<TAB><NEWLINE>
526         $inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\nF00\177\177oo\t\n");
527
528         $dialog = new QuestionHelper();
529         $dialog->setInputStream($inputStream);
530         $helperSet = new HelperSet(array(new FormatterHelper()));
531         $dialog->setHelperSet($helperSet);
532
533         $question = new Question('Please select a bundle', 'FrameworkBundle');
534         $question->setAutocompleterValues(array('AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle'));
535
536         $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
537         $this->assertEquals('AsseticBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
538         $this->assertEquals('FrameworkBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
539         $this->assertEquals('SecurityBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
540         $this->assertEquals('FooBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
541         $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
542         $this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
543         $this->assertEquals('FooBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
544     }
545
546     /**
547      * @group legacy
548      */
549     public function testLegacyAskWithAutocompleteWithNonSequentialKeys()
550     {
551         if (!$this->hasSttyAvailable()) {
552             $this->markTestSkipped('`stty` is required to test autocomplete functionality');
553         }
554
555         // <UP ARROW><UP ARROW><NEWLINE><DOWN ARROW><DOWN ARROW><NEWLINE>
556         $inputStream = $this->getInputStream("\033[A\033[A\n\033[B\033[B\n");
557
558         $dialog = new QuestionHelper();
559         $dialog->setInputStream($inputStream);
560         $dialog->setHelperSet(new HelperSet(array(new FormatterHelper())));
561
562         $question = new ChoiceQuestion('Please select a bundle', array(1 => 'AcmeDemoBundle', 4 => 'AsseticBundle'));
563         $question->setMaxAttempts(1);
564
565         $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
566         $this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
567     }
568
569     /**
570      * @group legacy
571      */
572     public function testLegacyAskHiddenResponse()
573     {
574         if ('\\' === DIRECTORY_SEPARATOR) {
575             $this->markTestSkipped('This test is not supported on Windows');
576         }
577
578         $dialog = new QuestionHelper();
579         $dialog->setInputStream($this->getInputStream("8AM\n"));
580
581         $question = new Question('What time is it?');
582         $question->setHidden(true);
583
584         $this->assertEquals('8AM', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
585     }
586
587     /**
588      * @group        legacy
589      * @dataProvider getAskConfirmationData
590      */
591     public function testLegacyAskConfirmation($question, $expected, $default = true)
592     {
593         $dialog = new QuestionHelper();
594
595         $dialog->setInputStream($this->getInputStream($question."\n"));
596         $question = new ConfirmationQuestion('Do you like French fries?', $default);
597         $this->assertEquals($expected, $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question), 'confirmation question should '.($expected ? 'pass' : 'cancel'));
598     }
599
600     /**
601      * @group legacy
602      */
603     public function testLegacyAskConfirmationWithCustomTrueAnswer()
604     {
605         $dialog = new QuestionHelper();
606
607         $dialog->setInputStream($this->getInputStream("j\ny\n"));
608         $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i');
609         $this->assertTrue($dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
610         $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i');
611         $this->assertTrue($dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
612     }
613
614     /**
615      * @group legacy
616      */
617     public function testLegacyAskAndValidate()
618     {
619         $dialog = new QuestionHelper();
620         $helperSet = new HelperSet(array(new FormatterHelper()));
621         $dialog->setHelperSet($helperSet);
622
623         $error = 'This is not a color!';
624         $validator = function ($color) use ($error) {
625             if (!in_array($color, array('white', 'black'))) {
626                 throw new \InvalidArgumentException($error);
627             }
628
629             return $color;
630         };
631
632         $question = new Question('What color was the white horse of Henry IV?', 'white');
633         $question->setValidator($validator);
634         $question->setMaxAttempts(2);
635
636         $dialog->setInputStream($this->getInputStream("\nblack\n"));
637         $this->assertEquals('white', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
638         $this->assertEquals('black', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
639
640         $dialog->setInputStream($this->getInputStream("green\nyellow\norange\n"));
641         try {
642             $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
643             $this->fail();
644         } catch (\InvalidArgumentException $e) {
645             $this->assertEquals($error, $e->getMessage());
646         }
647     }
648
649     /**
650      * @group        legacy
651      * @dataProvider simpleAnswerProvider
652      */
653     public function testLegacySelectChoiceFromSimpleChoices($providedAnswer, $expectedValue)
654     {
655         $possibleChoices = array(
656             'My environment 1',
657             'My environment 2',
658             'My environment 3',
659         );
660
661         $dialog = new QuestionHelper();
662         $dialog->setInputStream($this->getInputStream($providedAnswer."\n"));
663         $helperSet = new HelperSet(array(new FormatterHelper()));
664         $dialog->setHelperSet($helperSet);
665
666         $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
667         $question->setMaxAttempts(1);
668         $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
669
670         $this->assertSame($expectedValue, $answer);
671     }
672
673     /**
674      * @group        legacy
675      * @dataProvider mixedKeysChoiceListAnswerProvider
676      */
677     public function testLegacyChoiceFromChoicelistWithMixedKeys($providedAnswer, $expectedValue)
678     {
679         $possibleChoices = array(
680             '0' => 'No environment',
681             '1' => 'My environment 1',
682             'env_2' => 'My environment 2',
683             3 => 'My environment 3',
684         );
685
686         $dialog = new QuestionHelper();
687         $dialog->setInputStream($this->getInputStream($providedAnswer."\n"));
688         $helperSet = new HelperSet(array(new FormatterHelper()));
689         $dialog->setHelperSet($helperSet);
690
691         $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
692         $question->setMaxAttempts(1);
693         $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
694
695         $this->assertSame($expectedValue, $answer);
696     }
697
698     /**
699      * @group        legacy
700      * @dataProvider answerProvider
701      */
702     public function testLegacySelectChoiceFromChoiceList($providedAnswer, $expectedValue)
703     {
704         $possibleChoices = array(
705             'env_1' => 'My environment 1',
706             'env_2' => 'My environment',
707             'env_3' => 'My environment',
708         );
709
710         $dialog = new QuestionHelper();
711         $dialog->setInputStream($this->getInputStream($providedAnswer."\n"));
712         $helperSet = new HelperSet(array(new FormatterHelper()));
713         $dialog->setHelperSet($helperSet);
714
715         $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
716         $question->setMaxAttempts(1);
717         $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
718
719         $this->assertSame($expectedValue, $answer);
720     }
721
722     /**
723      * @group                    legacy
724      * @expectedException        \InvalidArgumentException
725      * @expectedExceptionMessage The provided answer is ambiguous. Value should be one of env_2 or env_3.
726      */
727     public function testLegacyAmbiguousChoiceFromChoicelist()
728     {
729         $possibleChoices = array(
730             'env_1' => 'My first environment',
731             'env_2' => 'My environment',
732             'env_3' => 'My environment',
733         );
734
735         $dialog = new QuestionHelper();
736         $dialog->setInputStream($this->getInputStream("My environment\n"));
737         $helperSet = new HelperSet(array(new FormatterHelper()));
738         $dialog->setHelperSet($helperSet);
739
740         $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
741         $question->setMaxAttempts(1);
742
743         $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
744     }
745
746     /**
747      * @requires function mb_strwidth
748      * @group legacy
749      */
750     public function testLegacyChoiceOutputFormattingQuestionForUtf8Keys()
751     {
752         $question = 'Lorem ipsum?';
753         $possibleChoices = array(
754             'foo' => 'foo',
755             'żółw' => 'bar',
756             'łabądź' => 'baz',
757         );
758         $outputShown = array(
759             $question,
760             '  [<info>foo   </info>] foo',
761             '  [<info>żółw  </info>] bar',
762             '  [<info>łabądź</info>] baz',
763         );
764         $output = $this->getMockBuilder('\Symfony\Component\Console\Output\OutputInterface')->getMock();
765         $output->method('getFormatter')->willReturn(new OutputFormatter());
766
767         $dialog = new QuestionHelper();
768         $dialog->setInputStream($this->getInputStream("\n"));
769         $helperSet = new HelperSet(array(new FormatterHelper()));
770         $dialog->setHelperSet($helperSet);
771
772         $output->expects($this->once())->method('writeln')->with($this->equalTo($outputShown));
773
774         $question = new ChoiceQuestion($question, $possibleChoices, 'foo');
775         $dialog->ask($this->createInputInterfaceMock(), $output, $question);
776     }
777
778     /**
779      * @expectedException        \Symfony\Component\Console\Exception\RuntimeException
780      * @expectedExceptionMessage Aborted
781      */
782     public function testAskThrowsExceptionOnMissingInput()
783     {
784         $dialog = new QuestionHelper();
785         $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), new Question('What\'s your name?'));
786     }
787
788     /**
789      * @expectedException        \Symfony\Component\Console\Exception\RuntimeException
790      * @expectedExceptionMessage Aborted
791      */
792     public function testAskThrowsExceptionOnMissingInputWithValidator()
793     {
794         $dialog = new QuestionHelper();
795
796         $question = new Question('What\'s your name?');
797         $question->setValidator(function () {
798             if (!$value) {
799                 throw new \Exception('A value is required.');
800             }
801         });
802
803         $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), $question);
804     }
805
806     /**
807      * @expectedException \LogicException
808      * @expectedExceptionMessage Choice question must have at least 1 choice available.
809      */
810     public function testEmptyChoices()
811     {
812         new ChoiceQuestion('Question', array(), 'irrelevant');
813     }
814
815     protected function getInputStream($input)
816     {
817         $stream = fopen('php://memory', 'r+', false);
818         fwrite($stream, $input);
819         rewind($stream);
820
821         return $stream;
822     }
823
824     protected function createOutputInterface()
825     {
826         return new StreamOutput(fopen('php://memory', 'r+', false));
827     }
828
829     protected function createInputInterfaceMock($interactive = true)
830     {
831         $mock = $this->getMockBuilder('Symfony\Component\Console\Input\InputInterface')->getMock();
832         $mock->expects($this->any())
833             ->method('isInteractive')
834             ->will($this->returnValue($interactive));
835
836         return $mock;
837     }
838
839     private function hasSttyAvailable()
840     {
841         exec('stty 2>&1', $output, $exitcode);
842
843         return $exitcode === 0;
844     }
845 }