Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / vendor / symfony / console / Tests / Helper / QuestionHelperTest.php
index 7d450252301be48bc78beff0384e347da257df54..cf12acdb665b45972c23b436cd38ffbd1ac56c15 100644 (file)
@@ -11,7 +11,6 @@
 
 namespace Symfony\Component\Console\Tests\Helper;
 
-use PHPUnit\Framework\TestCase;
 use Symfony\Component\Console\Formatter\OutputFormatter;
 use Symfony\Component\Console\Helper\QuestionHelper;
 use Symfony\Component\Console\Helper\HelperSet;
@@ -24,7 +23,7 @@ use Symfony\Component\Console\Question\Question;
 /**
  * @group tty
  */
-class QuestionHelperTest extends TestCase
+class QuestionHelperTest extends AbstractQuestionHelperTest
 {
     public function testAskChoice()
     {
@@ -35,22 +34,22 @@ class QuestionHelperTest extends TestCase
 
         $heroes = array('Superman', 'Batman', 'Spiderman');
 
-        $questionHelper->setInputStream($this->getInputStream("\n1\n  1  \nFabien\n1\nFabien\n1\n0,2\n 0 , 2  \n\n\n"));
+        $inputStream = $this->getInputStream("\n1\n  1  \nFabien\n1\nFabien\n1\n0,2\n 0 , 2  \n\n\n");
 
         $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '2');
         $question->setMaxAttempts(1);
         // first answer is an empty answer, we're supposed to receive the default value
-        $this->assertEquals('Spiderman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals('Spiderman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
 
         $question = new ChoiceQuestion('What is your favorite superhero?', $heroes);
         $question->setMaxAttempts(1);
-        $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
-        $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
 
         $question = new ChoiceQuestion('What is your favorite superhero?', $heroes);
         $question->setErrorMessage('Input "%s" is not a superhero!');
         $question->setMaxAttempts(2);
-        $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question));
+        $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question));
 
         rewind($output->getStream());
         $stream = stream_get_contents($output->getStream());
@@ -59,7 +58,7 @@ class QuestionHelperTest extends TestCase
         try {
             $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '1');
             $question->setMaxAttempts(1);
-            $questionHelper->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question);
+            $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question);
             $this->fail();
         } catch (\InvalidArgumentException $e) {
             $this->assertEquals('Value "Fabien" is invalid', $e->getMessage());
@@ -69,34 +68,38 @@ class QuestionHelperTest extends TestCase
         $question->setMaxAttempts(1);
         $question->setMultiselect(true);
 
-        $this->assertEquals(array('Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
-        $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
-        $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals(array('Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
 
         $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '0,1');
         $question->setMaxAttempts(1);
         $question->setMultiselect(true);
 
-        $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
 
         $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, ' 0 , 1 ');
         $question->setMaxAttempts(1);
         $question->setMultiselect(true);
 
-        $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+
+        $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, 0);
+        // We are supposed to get the default value since we are not in interactive mode
+        $this->assertEquals('Superman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream, true), $this->createOutputInterface(), $question));
     }
 
     public function testAsk()
     {
         $dialog = new QuestionHelper();
 
-        $dialog->setInputStream($this->getInputStream("\n8AM\n"));
+        $inputStream = $this->getInputStream("\n8AM\n");
 
         $question = new Question('What time is it?', '2PM');
-        $this->assertEquals('2PM', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals('2PM', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
 
         $question = new Question('What time is it?', '2PM');
-        $this->assertEquals('8AM', $dialog->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question));
+        $this->assertEquals('8AM', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question));
 
         rewind($output->getStream());
         $this->assertEquals('What time is it?', stream_get_contents($output->getStream()));
@@ -119,21 +122,20 @@ class QuestionHelperTest extends TestCase
         $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");
 
         $dialog = new QuestionHelper();
-        $dialog->setInputStream($inputStream);
         $helperSet = new HelperSet(array(new FormatterHelper()));
         $dialog->setHelperSet($helperSet);
 
         $question = new Question('Please select a bundle', 'FrameworkBundle');
         $question->setAutocompleterValues(array('AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle'));
 
-        $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
-        $this->assertEquals('AsseticBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
-        $this->assertEquals('FrameworkBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
-        $this->assertEquals('SecurityBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
-        $this->assertEquals('FooBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
-        $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
-        $this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
-        $this->assertEquals('FooBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals('AsseticBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals('FrameworkBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals('SecurityBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals('FooBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals('AsseticBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals('FooBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
     }
 
     public function testAskWithAutocompleteWithNonSequentialKeys()
@@ -146,14 +148,75 @@ class QuestionHelperTest extends TestCase
         $inputStream = $this->getInputStream("\033[A\033[A\n\033[B\033[B\n");
 
         $dialog = new QuestionHelper();
-        $dialog->setInputStream($inputStream);
         $dialog->setHelperSet(new HelperSet(array(new FormatterHelper())));
 
         $question = new ChoiceQuestion('Please select a bundle', array(1 => 'AcmeDemoBundle', 4 => 'AsseticBundle'));
         $question->setMaxAttempts(1);
 
-        $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
-        $this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals('AsseticBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+    }
+
+    public function testAskWithAutocompleteWithExactMatch()
+    {
+        if (!$this->hasSttyAvailable()) {
+            $this->markTestSkipped('`stty` is required to test autocomplete functionality');
+        }
+
+        $inputStream = $this->getInputStream("b\n");
+
+        $possibleChoices = array(
+            'a' => 'berlin',
+            'b' => 'copenhagen',
+            'c' => 'amsterdam',
+        );
+
+        $dialog = new QuestionHelper();
+        $dialog->setHelperSet(new HelperSet(array(new FormatterHelper())));
+
+        $question = new ChoiceQuestion('Please select a city', $possibleChoices);
+        $question->setMaxAttempts(1);
+
+        $this->assertSame('b', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+    }
+
+    public function testAutocompleteWithTrailingBackslash()
+    {
+        if (!$this->hasSttyAvailable()) {
+            $this->markTestSkipped('`stty` is required to test autocomplete functionality');
+        }
+
+        $inputStream = $this->getInputStream('E');
+
+        $dialog = new QuestionHelper();
+        $helperSet = new HelperSet(array(new FormatterHelper()));
+        $dialog->setHelperSet($helperSet);
+
+        $question = new Question('');
+        $expectedCompletion = 'ExampleNamespace\\';
+        $question->setAutocompleterValues(array($expectedCompletion));
+
+        $output = $this->createOutputInterface();
+        $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $output, $question);
+
+        $outputStream = $output->getStream();
+        rewind($outputStream);
+        $actualOutput = stream_get_contents($outputStream);
+
+        // Shell control (esc) sequences are not so important: we only care that
+        // <hl> tag is interpreted correctly and replaced
+        $irrelevantEscSequences = array(
+            "\0337" => '', // Save cursor position
+            "\0338" => '', // Restore cursor position
+            "\033[K" => '', // Clear line from cursor till the end
+        );
+
+        $importantActualOutput = strtr($actualOutput, $irrelevantEscSequences);
+
+        // Remove colors (e.g. "\033[30m", "\033[31;41m")
+        $importantActualOutput = preg_replace('/\033\[\d+(;\d+)?m/', '', $importantActualOutput);
+
+        $this->assertEquals($expectedCompletion, $importantActualOutput);
     }
 
     public function testAskHiddenResponse()
@@ -163,12 +226,11 @@ class QuestionHelperTest extends TestCase
         }
 
         $dialog = new QuestionHelper();
-        $dialog->setInputStream($this->getInputStream("8AM\n"));
 
         $question = new Question('What time is it?');
         $question->setHidden(true);
 
-        $this->assertEquals('8AM', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals('8AM', $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("8AM\n")), $this->createOutputInterface(), $question));
     }
 
     /**
@@ -178,9 +240,9 @@ class QuestionHelperTest extends TestCase
     {
         $dialog = new QuestionHelper();
 
-        $dialog->setInputStream($this->getInputStream($question."\n"));
+        $inputStream = $this->getInputStream($question."\n");
         $question = new ConfirmationQuestion('Do you like French fries?', $default);
-        $this->assertEquals($expected, $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question), 'confirmation question should '.($expected ? 'pass' : 'cancel'));
+        $this->assertEquals($expected, $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question), 'confirmation question should '.($expected ? 'pass' : 'cancel'));
     }
 
     public function getAskConfirmationData()
@@ -199,11 +261,11 @@ class QuestionHelperTest extends TestCase
     {
         $dialog = new QuestionHelper();
 
-        $dialog->setInputStream($this->getInputStream("j\ny\n"));
+        $inputStream = $this->getInputStream("j\ny\n");
         $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i');
-        $this->assertTrue($dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertTrue($dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
         $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i');
-        $this->assertTrue($dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertTrue($dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
     }
 
     public function testAskAndValidate()
@@ -225,13 +287,12 @@ class QuestionHelperTest extends TestCase
         $question->setValidator($validator);
         $question->setMaxAttempts(2);
 
-        $dialog->setInputStream($this->getInputStream("\nblack\n"));
-        $this->assertEquals('white', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
-        $this->assertEquals('black', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $inputStream = $this->getInputStream("\nblack\n");
+        $this->assertEquals('white', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals('black', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
 
-        $dialog->setInputStream($this->getInputStream("green\nyellow\norange\n"));
         try {
-            $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
+            $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("green\nyellow\norange\n")), $this->createOutputInterface(), $question);
             $this->fail();
         } catch (\InvalidArgumentException $e) {
             $this->assertEquals($error, $e->getMessage());
@@ -250,13 +311,12 @@ class QuestionHelperTest extends TestCase
         );
 
         $dialog = new QuestionHelper();
-        $dialog->setInputStream($this->getInputStream($providedAnswer."\n"));
         $helperSet = new HelperSet(array(new FormatterHelper()));
         $dialog->setHelperSet($helperSet);
 
         $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
         $question->setMaxAttempts(1);
-        $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
+        $answer = $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream($providedAnswer."\n")), $this->createOutputInterface(), $question);
 
         $this->assertSame($expectedValue, $answer);
     }
@@ -284,14 +344,14 @@ class QuestionHelperTest extends TestCase
         );
 
         $dialog = new QuestionHelper();
-        $dialog->setInputStream($this->getInputStream($providedAnswer."\n"));
+        $inputStream = $this->getInputStream($providedAnswer."\n");
         $helperSet = new HelperSet(array(new FormatterHelper()));
         $dialog->setHelperSet($helperSet);
 
         $question = new ChoiceQuestion('Please select the directory', $possibleChoices);
         $question->setMaxAttempts(1);
         $question->setMultiselect(true);
-        $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
+        $answer = $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question);
 
         $this->assertSame($expectedValue, $answer);
     }
@@ -317,13 +377,12 @@ class QuestionHelperTest extends TestCase
         );
 
         $dialog = new QuestionHelper();
-        $dialog->setInputStream($this->getInputStream($providedAnswer."\n"));
         $helperSet = new HelperSet(array(new FormatterHelper()));
         $dialog->setHelperSet($helperSet);
 
         $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
         $question->setMaxAttempts(1);
-        $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
+        $answer = $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream($providedAnswer."\n")), $this->createOutputInterface(), $question);
 
         $this->assertSame($expectedValue, $answer);
     }
@@ -352,13 +411,12 @@ class QuestionHelperTest extends TestCase
         );
 
         $dialog = new QuestionHelper();
-        $dialog->setInputStream($this->getInputStream($providedAnswer."\n"));
         $helperSet = new HelperSet(array(new FormatterHelper()));
         $dialog->setHelperSet($helperSet);
 
         $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
         $question->setMaxAttempts(1);
-        $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
+        $answer = $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream($providedAnswer."\n")), $this->createOutputInterface(), $question);
 
         $this->assertSame($expectedValue, $answer);
     }
@@ -376,14 +434,13 @@ class QuestionHelperTest extends TestCase
         );
 
         $dialog = new QuestionHelper();
-        $dialog->setInputStream($this->getInputStream("My environment\n"));
         $helperSet = new HelperSet(array(new FormatterHelper()));
         $dialog->setHelperSet($helperSet);
 
         $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
         $question->setMaxAttempts(1);
 
-        $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
+        $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("My environment\n")), $this->createOutputInterface(), $question);
     }
 
     public function answerProvider()
@@ -400,7 +457,7 @@ class QuestionHelperTest extends TestCase
     {
         $dialog = new QuestionHelper();
         $question = new Question('Do you have a job?', 'not yet');
-        $this->assertEquals('not yet', $dialog->ask($this->createInputInterfaceMock(false), $this->createOutputInterface(), $question));
+        $this->assertEquals('not yet', $dialog->ask($this->createStreamableInputInterfaceMock(null, false), $this->createOutputInterface(), $question));
     }
 
     /**
@@ -423,6 +480,356 @@ class QuestionHelperTest extends TestCase
         $output = $this->getMockBuilder('\Symfony\Component\Console\Output\OutputInterface')->getMock();
         $output->method('getFormatter')->willReturn(new OutputFormatter());
 
+        $dialog = new QuestionHelper();
+        $helperSet = new HelperSet(array(new FormatterHelper()));
+        $dialog->setHelperSet($helperSet);
+
+        $output->expects($this->once())->method('writeln')->with($this->equalTo($outputShown));
+
+        $question = new ChoiceQuestion($question, $possibleChoices, 'foo');
+        $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("\n")), $output, $question);
+    }
+
+    /**
+     * @group legacy
+     */
+    public function testLegacyAskChoice()
+    {
+        $questionHelper = new QuestionHelper();
+
+        $helperSet = new HelperSet(array(new FormatterHelper()));
+        $questionHelper->setHelperSet($helperSet);
+
+        $heroes = array('Superman', 'Batman', 'Spiderman');
+
+        $questionHelper->setInputStream($this->getInputStream("\n1\n  1  \nFabien\n1\nFabien\n1\n0,2\n 0 , 2  \n\n\n"));
+
+        $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '2');
+        $question->setMaxAttempts(1);
+        // first answer is an empty answer, we're supposed to receive the default value
+        $this->assertEquals('Spiderman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+
+        $question = new ChoiceQuestion('What is your favorite superhero?', $heroes);
+        $question->setMaxAttempts(1);
+        $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+
+        $question = new ChoiceQuestion('What is your favorite superhero?', $heroes);
+        $question->setErrorMessage('Input "%s" is not a superhero!');
+        $question->setMaxAttempts(2);
+        $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question));
+
+        rewind($output->getStream());
+        $stream = stream_get_contents($output->getStream());
+        $this->assertContains('Input "Fabien" is not a superhero!', $stream);
+
+        try {
+            $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '1');
+            $question->setMaxAttempts(1);
+            $questionHelper->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question);
+            $this->fail();
+        } catch (\InvalidArgumentException $e) {
+            $this->assertEquals('Value "Fabien" is invalid', $e->getMessage());
+        }
+
+        $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, null);
+        $question->setMaxAttempts(1);
+        $question->setMultiselect(true);
+
+        $this->assertEquals(array('Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+
+        $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '0,1');
+        $question->setMaxAttempts(1);
+        $question->setMultiselect(true);
+
+        $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+
+        $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, ' 0 , 1 ');
+        $question->setMaxAttempts(1);
+        $question->setMultiselect(true);
+
+        $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+    }
+
+    /**
+     * @group legacy
+     */
+    public function testLegacyAsk()
+    {
+        $dialog = new QuestionHelper();
+
+        $dialog->setInputStream($this->getInputStream("\n8AM\n"));
+
+        $question = new Question('What time is it?', '2PM');
+        $this->assertEquals('2PM', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+
+        $question = new Question('What time is it?', '2PM');
+        $this->assertEquals('8AM', $dialog->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question));
+
+        rewind($output->getStream());
+        $this->assertEquals('What time is it?', stream_get_contents($output->getStream()));
+    }
+
+    /**
+     * @group legacy
+     */
+    public function testLegacyAskWithAutocomplete()
+    {
+        if (!$this->hasSttyAvailable()) {
+            $this->markTestSkipped('`stty` is required to test autocomplete functionality');
+        }
+
+        // Acm<NEWLINE>
+        // Ac<BACKSPACE><BACKSPACE>s<TAB>Test<NEWLINE>
+        // <NEWLINE>
+        // <UP ARROW><UP ARROW><NEWLINE>
+        // <UP ARROW><UP ARROW><UP ARROW><UP ARROW><UP ARROW><TAB>Test<NEWLINE>
+        // <DOWN ARROW><NEWLINE>
+        // S<BACKSPACE><BACKSPACE><DOWN ARROW><DOWN ARROW><NEWLINE>
+        // F00<BACKSPACE><BACKSPACE>oo<TAB><NEWLINE>
+        $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");
+
+        $dialog = new QuestionHelper();
+        $dialog->setInputStream($inputStream);
+        $helperSet = new HelperSet(array(new FormatterHelper()));
+        $dialog->setHelperSet($helperSet);
+
+        $question = new Question('Please select a bundle', 'FrameworkBundle');
+        $question->setAutocompleterValues(array('AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle'));
+
+        $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals('AsseticBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals('FrameworkBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals('SecurityBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals('FooBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals('FooBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+    }
+
+    /**
+     * @group legacy
+     */
+    public function testLegacyAskWithAutocompleteWithNonSequentialKeys()
+    {
+        if (!$this->hasSttyAvailable()) {
+            $this->markTestSkipped('`stty` is required to test autocomplete functionality');
+        }
+
+        // <UP ARROW><UP ARROW><NEWLINE><DOWN ARROW><DOWN ARROW><NEWLINE>
+        $inputStream = $this->getInputStream("\033[A\033[A\n\033[B\033[B\n");
+
+        $dialog = new QuestionHelper();
+        $dialog->setInputStream($inputStream);
+        $dialog->setHelperSet(new HelperSet(array(new FormatterHelper())));
+
+        $question = new ChoiceQuestion('Please select a bundle', array(1 => 'AcmeDemoBundle', 4 => 'AsseticBundle'));
+        $question->setMaxAttempts(1);
+
+        $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+    }
+
+    /**
+     * @group legacy
+     */
+    public function testLegacyAskHiddenResponse()
+    {
+        if ('\\' === DIRECTORY_SEPARATOR) {
+            $this->markTestSkipped('This test is not supported on Windows');
+        }
+
+        $dialog = new QuestionHelper();
+        $dialog->setInputStream($this->getInputStream("8AM\n"));
+
+        $question = new Question('What time is it?');
+        $question->setHidden(true);
+
+        $this->assertEquals('8AM', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+    }
+
+    /**
+     * @group        legacy
+     * @dataProvider getAskConfirmationData
+     */
+    public function testLegacyAskConfirmation($question, $expected, $default = true)
+    {
+        $dialog = new QuestionHelper();
+
+        $dialog->setInputStream($this->getInputStream($question."\n"));
+        $question = new ConfirmationQuestion('Do you like French fries?', $default);
+        $this->assertEquals($expected, $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question), 'confirmation question should '.($expected ? 'pass' : 'cancel'));
+    }
+
+    /**
+     * @group legacy
+     */
+    public function testLegacyAskConfirmationWithCustomTrueAnswer()
+    {
+        $dialog = new QuestionHelper();
+
+        $dialog->setInputStream($this->getInputStream("j\ny\n"));
+        $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i');
+        $this->assertTrue($dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i');
+        $this->assertTrue($dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+    }
+
+    /**
+     * @group legacy
+     */
+    public function testLegacyAskAndValidate()
+    {
+        $dialog = new QuestionHelper();
+        $helperSet = new HelperSet(array(new FormatterHelper()));
+        $dialog->setHelperSet($helperSet);
+
+        $error = 'This is not a color!';
+        $validator = function ($color) use ($error) {
+            if (!in_array($color, array('white', 'black'))) {
+                throw new \InvalidArgumentException($error);
+            }
+
+            return $color;
+        };
+
+        $question = new Question('What color was the white horse of Henry IV?', 'white');
+        $question->setValidator($validator);
+        $question->setMaxAttempts(2);
+
+        $dialog->setInputStream($this->getInputStream("\nblack\n"));
+        $this->assertEquals('white', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+        $this->assertEquals('black', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
+
+        $dialog->setInputStream($this->getInputStream("green\nyellow\norange\n"));
+        try {
+            $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
+            $this->fail();
+        } catch (\InvalidArgumentException $e) {
+            $this->assertEquals($error, $e->getMessage());
+        }
+    }
+
+    /**
+     * @group        legacy
+     * @dataProvider simpleAnswerProvider
+     */
+    public function testLegacySelectChoiceFromSimpleChoices($providedAnswer, $expectedValue)
+    {
+        $possibleChoices = array(
+            'My environment 1',
+            'My environment 2',
+            'My environment 3',
+        );
+
+        $dialog = new QuestionHelper();
+        $dialog->setInputStream($this->getInputStream($providedAnswer."\n"));
+        $helperSet = new HelperSet(array(new FormatterHelper()));
+        $dialog->setHelperSet($helperSet);
+
+        $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
+        $question->setMaxAttempts(1);
+        $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
+
+        $this->assertSame($expectedValue, $answer);
+    }
+
+    /**
+     * @group        legacy
+     * @dataProvider mixedKeysChoiceListAnswerProvider
+     */
+    public function testLegacyChoiceFromChoicelistWithMixedKeys($providedAnswer, $expectedValue)
+    {
+        $possibleChoices = array(
+            '0' => 'No environment',
+            '1' => 'My environment 1',
+            'env_2' => 'My environment 2',
+            3 => 'My environment 3',
+        );
+
+        $dialog = new QuestionHelper();
+        $dialog->setInputStream($this->getInputStream($providedAnswer."\n"));
+        $helperSet = new HelperSet(array(new FormatterHelper()));
+        $dialog->setHelperSet($helperSet);
+
+        $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
+        $question->setMaxAttempts(1);
+        $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
+
+        $this->assertSame($expectedValue, $answer);
+    }
+
+    /**
+     * @group        legacy
+     * @dataProvider answerProvider
+     */
+    public function testLegacySelectChoiceFromChoiceList($providedAnswer, $expectedValue)
+    {
+        $possibleChoices = array(
+            'env_1' => 'My environment 1',
+            'env_2' => 'My environment',
+            'env_3' => 'My environment',
+        );
+
+        $dialog = new QuestionHelper();
+        $dialog->setInputStream($this->getInputStream($providedAnswer."\n"));
+        $helperSet = new HelperSet(array(new FormatterHelper()));
+        $dialog->setHelperSet($helperSet);
+
+        $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
+        $question->setMaxAttempts(1);
+        $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
+
+        $this->assertSame($expectedValue, $answer);
+    }
+
+    /**
+     * @group                    legacy
+     * @expectedException        \InvalidArgumentException
+     * @expectedExceptionMessage The provided answer is ambiguous. Value should be one of env_2 or env_3.
+     */
+    public function testLegacyAmbiguousChoiceFromChoicelist()
+    {
+        $possibleChoices = array(
+            'env_1' => 'My first environment',
+            'env_2' => 'My environment',
+            'env_3' => 'My environment',
+        );
+
+        $dialog = new QuestionHelper();
+        $dialog->setInputStream($this->getInputStream("My environment\n"));
+        $helperSet = new HelperSet(array(new FormatterHelper()));
+        $dialog->setHelperSet($helperSet);
+
+        $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices);
+        $question->setMaxAttempts(1);
+
+        $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
+    }
+
+    /**
+     * @requires function mb_strwidth
+     * @group legacy
+     */
+    public function testLegacyChoiceOutputFormattingQuestionForUtf8Keys()
+    {
+        $question = 'Lorem ipsum?';
+        $possibleChoices = array(
+            'foo' => 'foo',
+            'żółw' => 'bar',
+            'łabądź' => 'baz',
+        );
+        $outputShown = array(
+            $question,
+            '  [<info>foo   </info>] foo',
+            '  [<info>żółw  </info>] bar',
+            '  [<info>łabądź</info>] baz',
+        );
+        $output = $this->getMockBuilder('\Symfony\Component\Console\Output\OutputInterface')->getMock();
+        $output->method('getFormatter')->willReturn(new OutputFormatter());
+
         $dialog = new QuestionHelper();
         $dialog->setInputStream($this->getInputStream("\n"));
         $helperSet = new HelperSet(array(new FormatterHelper()));
@@ -441,9 +848,7 @@ class QuestionHelperTest extends TestCase
     public function testAskThrowsExceptionOnMissingInput()
     {
         $dialog = new QuestionHelper();
-        $dialog->setInputStream($this->getInputStream(''));
-
-        $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), new Question('What\'s your name?'));
+        $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), new Question('What\'s your name?'));
     }
 
     /**
@@ -453,7 +858,6 @@ class QuestionHelperTest extends TestCase
     public function testAskThrowsExceptionOnMissingInputWithValidator()
     {
         $dialog = new QuestionHelper();
-        $dialog->setInputStream($this->getInputStream(''));
 
         $question = new Question('What\'s your name?');
         $question->setValidator(function () {
@@ -462,7 +866,7 @@ class QuestionHelperTest extends TestCase
             }
         });
 
-        $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
+        $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), $question);
     }
 
     /**
@@ -474,6 +878,39 @@ class QuestionHelperTest extends TestCase
         new ChoiceQuestion('Question', array(), 'irrelevant');
     }
 
+    public function testTraversableAutocomplete()
+    {
+        if (!$this->hasSttyAvailable()) {
+            $this->markTestSkipped('`stty` is required to test autocomplete functionality');
+        }
+
+        // Acm<NEWLINE>
+        // Ac<BACKSPACE><BACKSPACE>s<TAB>Test<NEWLINE>
+        // <NEWLINE>
+        // <UP ARROW><UP ARROW><NEWLINE>
+        // <UP ARROW><UP ARROW><UP ARROW><UP ARROW><UP ARROW><TAB>Test<NEWLINE>
+        // <DOWN ARROW><NEWLINE>
+        // S<BACKSPACE><BACKSPACE><DOWN ARROW><DOWN ARROW><NEWLINE>
+        // F00<BACKSPACE><BACKSPACE>oo<TAB><NEWLINE>
+        $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");
+
+        $dialog = new QuestionHelper();
+        $helperSet = new HelperSet(array(new FormatterHelper()));
+        $dialog->setHelperSet($helperSet);
+
+        $question = new Question('Please select a bundle', 'FrameworkBundle');
+        $question->setAutocompleterValues(new AutocompleteValues(array('irrelevant' => 'AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle')));
+
+        $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals('AsseticBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals('FrameworkBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals('SecurityBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals('FooBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals('AsseticBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+        $this->assertEquals('FooBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question));
+    }
+
     protected function getInputStream($input)
     {
         $stream = fopen('php://memory', 'r+', false);
@@ -502,6 +939,21 @@ class QuestionHelperTest extends TestCase
     {
         exec('stty 2>&1', $output, $exitcode);
 
-        return $exitcode === 0;
+        return 0 === $exitcode;
+    }
+}
+
+class AutocompleteValues implements \IteratorAggregate
+{
+    private $values;
+
+    public function __construct(array $values)
+    {
+        $this->values = $values;
+    }
+
+    public function getIterator()
+    {
+        return new \ArrayIterator($this->values);
     }
 }