summaryrefslogtreecommitdiff
path: root/vendor/symfony/console/Tests/Helper
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/symfony/console/Tests/Helper')
-rw-r--r--vendor/symfony/console/Tests/Helper/FormatterHelperTest.php92
-rw-r--r--vendor/symfony/console/Tests/Helper/HelperSetTest.php133
-rw-r--r--vendor/symfony/console/Tests/Helper/HelperTest.php54
-rw-r--r--vendor/symfony/console/Tests/Helper/LegacyDialogHelperTest.php263
-rw-r--r--vendor/symfony/console/Tests/Helper/LegacyProgressHelperTest.php224
-rw-r--r--vendor/symfony/console/Tests/Helper/LegacyTableHelperTest.php316
-rw-r--r--vendor/symfony/console/Tests/Helper/ProcessHelperTest.php117
-rw-r--r--vendor/symfony/console/Tests/Helper/ProgressBarTest.php664
-rw-r--r--vendor/symfony/console/Tests/Helper/ProgressIndicatorTest.php182
-rw-r--r--vendor/symfony/console/Tests/Helper/QuestionHelperTest.php435
-rw-r--r--vendor/symfony/console/Tests/Helper/TableStyleTest.php27
-rw-r--r--vendor/symfony/console/Tests/Helper/TableTest.php645
12 files changed, 3152 insertions, 0 deletions
diff --git a/vendor/symfony/console/Tests/Helper/FormatterHelperTest.php b/vendor/symfony/console/Tests/Helper/FormatterHelperTest.php
new file mode 100644
index 00000000..e0aa9211
--- /dev/null
+++ b/vendor/symfony/console/Tests/Helper/FormatterHelperTest.php
@@ -0,0 +1,92 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\Helper;
+
+use Symfony\Component\Console\Helper\FormatterHelper;
+
+class FormatterHelperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testFormatSection()
+ {
+ $formatter = new FormatterHelper();
+
+ $this->assertEquals(
+ '<info>[cli]</info> Some text to display',
+ $formatter->formatSection('cli', 'Some text to display'),
+ '::formatSection() formats a message in a section'
+ );
+ }
+
+ public function testFormatBlock()
+ {
+ $formatter = new FormatterHelper();
+
+ $this->assertEquals(
+ '<error> Some text to display </error>',
+ $formatter->formatBlock('Some text to display', 'error'),
+ '::formatBlock() formats a message in a block'
+ );
+
+ $this->assertEquals(
+ '<error> Some text to display </error>'."\n".
+ '<error> foo bar </error>',
+ $formatter->formatBlock(array('Some text to display', 'foo bar'), 'error'),
+ '::formatBlock() formats a message in a block'
+ );
+
+ $this->assertEquals(
+ '<error> </error>'."\n".
+ '<error> Some text to display </error>'."\n".
+ '<error> </error>',
+ $formatter->formatBlock('Some text to display', 'error', true),
+ '::formatBlock() formats a message in a block'
+ );
+ }
+
+ public function testFormatBlockWithDiacriticLetters()
+ {
+ $formatter = new FormatterHelper();
+
+ $this->assertEquals(
+ '<error> </error>'."\n".
+ '<error> Du texte à afficher </error>'."\n".
+ '<error> </error>',
+ $formatter->formatBlock('Du texte à afficher', 'error', true),
+ '::formatBlock() formats a message in a block'
+ );
+ }
+
+ public function testFormatBlockWithDoubleWidthDiacriticLetters()
+ {
+ $formatter = new FormatterHelper();
+ $this->assertEquals(
+ '<error> </error>'."\n".
+ '<error> 表示するテキスト </error>'."\n".
+ '<error> </error>',
+ $formatter->formatBlock('表示するテキスト', 'error', true),
+ '::formatBlock() formats a message in a block'
+ );
+ }
+
+ public function testFormatBlockLGEscaping()
+ {
+ $formatter = new FormatterHelper();
+
+ $this->assertEquals(
+ '<error> </error>'."\n".
+ '<error> \<info>some info\</info> </error>'."\n".
+ '<error> </error>',
+ $formatter->formatBlock('<info>some info</info>', 'error', true),
+ '::formatBlock() escapes \'<\' chars'
+ );
+ }
+}
diff --git a/vendor/symfony/console/Tests/Helper/HelperSetTest.php b/vendor/symfony/console/Tests/Helper/HelperSetTest.php
new file mode 100644
index 00000000..04edd304
--- /dev/null
+++ b/vendor/symfony/console/Tests/Helper/HelperSetTest.php
@@ -0,0 +1,133 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\Helper;
+
+use Symfony\Component\Console\Helper\HelperSet;
+use Symfony\Component\Console\Command\Command;
+
+class HelperSetTest extends \PHPUnit_Framework_TestCase
+{
+ public function testConstructor()
+ {
+ $mock_helper = $this->getGenericMockHelper('fake_helper');
+ $helperset = new HelperSet(array('fake_helper_alias' => $mock_helper));
+
+ $this->assertEquals($mock_helper, $helperset->get('fake_helper_alias'), '__construct sets given helper to helpers');
+ $this->assertTrue($helperset->has('fake_helper_alias'), '__construct sets helper alias for given helper');
+ }
+
+ public function testSet()
+ {
+ $helperset = new HelperSet();
+ $helperset->set($this->getGenericMockHelper('fake_helper', $helperset));
+ $this->assertTrue($helperset->has('fake_helper'), '->set() adds helper to helpers');
+
+ $helperset = new HelperSet();
+ $helperset->set($this->getGenericMockHelper('fake_helper_01', $helperset));
+ $helperset->set($this->getGenericMockHelper('fake_helper_02', $helperset));
+ $this->assertTrue($helperset->has('fake_helper_01'), '->set() will set multiple helpers on consecutive calls');
+ $this->assertTrue($helperset->has('fake_helper_02'), '->set() will set multiple helpers on consecutive calls');
+
+ $helperset = new HelperSet();
+ $helperset->set($this->getGenericMockHelper('fake_helper', $helperset), 'fake_helper_alias');
+ $this->assertTrue($helperset->has('fake_helper'), '->set() adds helper alias when set');
+ $this->assertTrue($helperset->has('fake_helper_alias'), '->set() adds helper alias when set');
+ }
+
+ public function testHas()
+ {
+ $helperset = new HelperSet(array('fake_helper_alias' => $this->getGenericMockHelper('fake_helper')));
+ $this->assertTrue($helperset->has('fake_helper'), '->has() finds set helper');
+ $this->assertTrue($helperset->has('fake_helper_alias'), '->has() finds set helper by alias');
+ }
+
+ public function testGet()
+ {
+ $helper_01 = $this->getGenericMockHelper('fake_helper_01');
+ $helper_02 = $this->getGenericMockHelper('fake_helper_02');
+ $helperset = new HelperSet(array('fake_helper_01_alias' => $helper_01, 'fake_helper_02_alias' => $helper_02));
+ $this->assertEquals($helper_01, $helperset->get('fake_helper_01'), '->get() returns correct helper by name');
+ $this->assertEquals($helper_01, $helperset->get('fake_helper_01_alias'), '->get() returns correct helper by alias');
+ $this->assertEquals($helper_02, $helperset->get('fake_helper_02'), '->get() returns correct helper by name');
+ $this->assertEquals($helper_02, $helperset->get('fake_helper_02_alias'), '->get() returns correct helper by alias');
+
+ $helperset = new HelperSet();
+ try {
+ $helperset->get('foo');
+ $this->fail('->get() throws InvalidArgumentException when helper not found');
+ } catch (\Exception $e) {
+ $this->assertInstanceOf('\InvalidArgumentException', $e, '->get() throws InvalidArgumentException when helper not found');
+ $this->assertInstanceOf('Symfony\Component\Console\Exception\ExceptionInterface', $e, '->get() throws domain specific exception when helper not found');
+ $this->assertContains('The helper "foo" is not defined.', $e->getMessage(), '->get() throws InvalidArgumentException when helper not found');
+ }
+ }
+
+ public function testSetCommand()
+ {
+ $cmd_01 = new Command('foo');
+ $cmd_02 = new Command('bar');
+
+ $helperset = new HelperSet();
+ $helperset->setCommand($cmd_01);
+ $this->assertEquals($cmd_01, $helperset->getCommand(), '->setCommand() stores given command');
+
+ $helperset = new HelperSet();
+ $helperset->setCommand($cmd_01);
+ $helperset->setCommand($cmd_02);
+ $this->assertEquals($cmd_02, $helperset->getCommand(), '->setCommand() overwrites stored command with consecutive calls');
+ }
+
+ public function testGetCommand()
+ {
+ $cmd = new Command('foo');
+ $helperset = new HelperSet();
+ $helperset->setCommand($cmd);
+ $this->assertEquals($cmd, $helperset->getCommand(), '->getCommand() retrieves stored command');
+ }
+
+ public function testIteration()
+ {
+ $helperset = new HelperSet();
+ $helperset->set($this->getGenericMockHelper('fake_helper_01', $helperset));
+ $helperset->set($this->getGenericMockHelper('fake_helper_02', $helperset));
+
+ $helpers = array('fake_helper_01', 'fake_helper_02');
+ $i = 0;
+
+ foreach ($helperset as $helper) {
+ $this->assertEquals($helpers[$i++], $helper->getName());
+ }
+ }
+
+ /**
+ * Create a generic mock for the helper interface. Optionally check for a call to setHelperSet with a specific
+ * helperset instance.
+ *
+ * @param string $name
+ * @param HelperSet $helperset allows a mock to verify a particular helperset set is being added to the Helper
+ */
+ private function getGenericMockHelper($name, HelperSet $helperset = null)
+ {
+ $mock_helper = $this->getMock('\Symfony\Component\Console\Helper\HelperInterface');
+ $mock_helper->expects($this->any())
+ ->method('getName')
+ ->will($this->returnValue($name));
+
+ if ($helperset) {
+ $mock_helper->expects($this->any())
+ ->method('setHelperSet')
+ ->with($this->equalTo($helperset));
+ }
+
+ return $mock_helper;
+ }
+}
diff --git a/vendor/symfony/console/Tests/Helper/HelperTest.php b/vendor/symfony/console/Tests/Helper/HelperTest.php
new file mode 100644
index 00000000..33fa2205
--- /dev/null
+++ b/vendor/symfony/console/Tests/Helper/HelperTest.php
@@ -0,0 +1,54 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\Helper;
+
+use Symfony\Component\Console\Helper\Helper;
+
+class HelperTest extends \PHPUnit_Framework_TestCase
+{
+ public function formatTimeProvider()
+ {
+ return array(
+ array(0, '< 1 sec'),
+ array(1, '1 sec'),
+ array(2, '2 secs'),
+ array(59, '59 secs'),
+ array(60, '1 min'),
+ array(61, '1 min'),
+ array(119, '1 min'),
+ array(120, '2 mins'),
+ array(121, '2 mins'),
+ array(3599, '59 mins'),
+ array(3600, '1 hr'),
+ array(7199, '1 hr'),
+ array(7200, '2 hrs'),
+ array(7201, '2 hrs'),
+ array(86399, '23 hrs'),
+ array(86400, '1 day'),
+ array(86401, '1 day'),
+ array(172799, '1 day'),
+ array(172800, '2 days'),
+ array(172801, '2 days'),
+ );
+ }
+
+ /**
+ * @dataProvider formatTimeProvider
+ *
+ * @param int $secs
+ * @param string $expectedFormat
+ */
+ public function testFormatTime($secs, $expectedFormat)
+ {
+ $this->assertEquals($expectedFormat, Helper::formatTime($secs));
+ }
+}
diff --git a/vendor/symfony/console/Tests/Helper/LegacyDialogHelperTest.php b/vendor/symfony/console/Tests/Helper/LegacyDialogHelperTest.php
new file mode 100644
index 00000000..97bf7756
--- /dev/null
+++ b/vendor/symfony/console/Tests/Helper/LegacyDialogHelperTest.php
@@ -0,0 +1,263 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\Helper;
+
+use Symfony\Component\Console\Input\ArrayInput;
+use Symfony\Component\Console\Helper\DialogHelper;
+use Symfony\Component\Console\Helper\HelperSet;
+use Symfony\Component\Console\Helper\FormatterHelper;
+use Symfony\Component\Console\Output\ConsoleOutput;
+use Symfony\Component\Console\Output\StreamOutput;
+use Symfony\Component\Console\Exception\InvalidArgumentException;
+
+/**
+ * @group legacy
+ */
+class LegacyDialogHelperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testSelect()
+ {
+ $dialog = new DialogHelper();
+
+ $helperSet = new HelperSet(array(new FormatterHelper()));
+ $dialog->setHelperSet($helperSet);
+
+ $heroes = array('Superman', 'Batman', 'Spiderman');
+
+ $dialog->setInputStream($this->getInputStream("\n1\n 1 \nFabien\n1\nFabien\n1\n0,2\n 0 , 2 \n\n\n"));
+ $this->assertEquals('2', $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, '2'));
+ $this->assertEquals('1', $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes));
+ $this->assertEquals('1', $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes));
+ $this->assertEquals('1', $dialog->select($output = $this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!', false));
+
+ rewind($output->getStream());
+ $this->assertContains('Input "Fabien" is not a superhero!', stream_get_contents($output->getStream()));
+
+ try {
+ $this->assertEquals('1', $dialog->select($output = $this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, 1));
+ $this->fail();
+ } catch (\InvalidArgumentException $e) {
+ $this->assertEquals('Value "Fabien" is invalid', $e->getMessage());
+ }
+
+ $this->assertEquals(array('1'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!', true));
+ $this->assertEquals(array('0', '2'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!', true));
+ $this->assertEquals(array('0', '2'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!', true));
+ $this->assertEquals(array('0', '1'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, '0,1', false, 'Input "%s" is not a superhero!', true));
+ $this->assertEquals(array('0', '1'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, ' 0 , 1 ', false, 'Input "%s" is not a superhero!', true));
+ }
+
+ public function testSelectOnErrorOutput()
+ {
+ $dialog = new DialogHelper();
+
+ $helperSet = new HelperSet(array(new FormatterHelper()));
+ $dialog->setHelperSet($helperSet);
+
+ $heroes = array('Superman', 'Batman', 'Spiderman');
+
+ $dialog->setInputStream($this->getInputStream("Stdout\n1\n"));
+ $this->assertEquals('1', $dialog->select($output = $this->getConsoleOutput($this->getOutputStream()), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!', false));
+
+ rewind($output->getErrorOutput()->getStream());
+ $this->assertContains('Input "Stdout" is not a superhero!', stream_get_contents($output->getErrorOutput()->getStream()));
+ }
+
+ public function testAsk()
+ {
+ $dialog = new DialogHelper();
+
+ $dialog->setInputStream($this->getInputStream("\n8AM\n"));
+
+ $this->assertEquals('2PM', $dialog->ask($this->getOutputStream(), 'What time is it?', '2PM'));
+ $this->assertEquals('8AM', $dialog->ask($output = $this->getOutputStream(), 'What time is it?', '2PM'));
+
+ rewind($output->getStream());
+ $this->assertEquals('What time is it?', stream_get_contents($output->getStream()));
+ }
+
+ public function testAskOnErrorOutput()
+ {
+ if (!$this->hasSttyAvailable()) {
+ $this->markTestSkipped('`stderr` is required to test stderr output functionality');
+ }
+
+ $dialog = new DialogHelper();
+
+ $dialog->setInputStream($this->getInputStream("not stdout\n"));
+
+ $this->assertEquals('not stdout', $dialog->ask($output = $this->getConsoleOutput($this->getOutputStream()), 'Where should output go?', 'stderr'));
+
+ rewind($output->getErrorOutput()->getStream());
+ $this->assertEquals('Where should output go?', stream_get_contents($output->getErrorOutput()->getStream()));
+ }
+
+ public function testAskWithAutocomplete()
+ {
+ 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 DialogHelper();
+ $dialog->setInputStream($inputStream);
+
+ $bundles = array('AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle');
+
+ $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
+ $this->assertEquals('AsseticBundleTest', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
+ $this->assertEquals('FrameworkBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
+ $this->assertEquals('SecurityBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
+ $this->assertEquals('FooBundleTest', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
+ $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
+ $this->assertEquals('AsseticBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
+ $this->assertEquals('FooBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
+ }
+
+ /**
+ * @group tty
+ */
+ public function testAskHiddenResponse()
+ {
+ if ('\\' === DIRECTORY_SEPARATOR) {
+ $this->markTestSkipped('This test is not supported on Windows');
+ }
+
+ $dialog = new DialogHelper();
+
+ $dialog->setInputStream($this->getInputStream("8AM\n"));
+
+ $this->assertEquals('8AM', $dialog->askHiddenResponse($this->getOutputStream(), 'What time is it?'));
+ }
+
+ /**
+ * @group tty
+ */
+ public function testAskHiddenResponseOnErrorOutput()
+ {
+ if ('\\' === DIRECTORY_SEPARATOR) {
+ $this->markTestSkipped('This test is not supported on Windows');
+ }
+
+ $dialog = new DialogHelper();
+
+ $dialog->setInputStream($this->getInputStream("8AM\n"));
+
+ $this->assertEquals('8AM', $dialog->askHiddenResponse($output = $this->getConsoleOutput($this->getOutputStream()), 'What time is it?'));
+
+ rewind($output->getErrorOutput()->getStream());
+ $this->assertContains('What time is it?', stream_get_contents($output->getErrorOutput()->getStream()));
+ }
+
+ public function testAskConfirmation()
+ {
+ $dialog = new DialogHelper();
+
+ $dialog->setInputStream($this->getInputStream("\n\n"));
+ $this->assertTrue($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?'));
+ $this->assertFalse($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', false));
+
+ $dialog->setInputStream($this->getInputStream("y\nyes\n"));
+ $this->assertTrue($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', false));
+ $this->assertTrue($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', false));
+
+ $dialog->setInputStream($this->getInputStream("n\nno\n"));
+ $this->assertFalse($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', true));
+ $this->assertFalse($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', true));
+ }
+
+ public function testAskAndValidate()
+ {
+ $dialog = new DialogHelper();
+ $helperSet = new HelperSet(array(new FormatterHelper()));
+ $dialog->setHelperSet($helperSet);
+
+ $question = 'What color was the white horse of Henry IV?';
+ $error = 'This is not a color!';
+ $validator = function ($color) use ($error) {
+ if (!in_array($color, array('white', 'black'))) {
+ throw new InvalidArgumentException($error);
+ }
+
+ return $color;
+ };
+
+ $dialog->setInputStream($this->getInputStream("\nblack\n"));
+ $this->assertEquals('white', $dialog->askAndValidate($this->getOutputStream(), $question, $validator, 2, 'white'));
+ $this->assertEquals('black', $dialog->askAndValidate($this->getOutputStream(), $question, $validator, 2, 'white'));
+
+ $dialog->setInputStream($this->getInputStream("green\nyellow\norange\n"));
+ try {
+ $this->assertEquals('white', $dialog->askAndValidate($output = $this->getConsoleOutput($this->getOutputStream()), $question, $validator, 2, 'white'));
+ $this->fail();
+ } catch (\InvalidArgumentException $e) {
+ $this->assertEquals($error, $e->getMessage());
+ rewind($output->getErrorOutput()->getStream());
+ $this->assertContains('What color was the white horse of Henry IV?', stream_get_contents($output->getErrorOutput()->getStream()));
+ }
+ }
+
+ public function testNoInteraction()
+ {
+ $dialog = new DialogHelper();
+
+ $input = new ArrayInput(array());
+ $input->setInteractive(false);
+
+ $dialog->setInput($input);
+
+ $this->assertEquals('not yet', $dialog->ask($this->getOutputStream(), 'Do you have a job?', 'not yet'));
+ }
+
+ protected function getInputStream($input)
+ {
+ $stream = fopen('php://memory', 'r+', false);
+ fwrite($stream, $input);
+ rewind($stream);
+
+ return $stream;
+ }
+
+ protected function getOutputStream()
+ {
+ return new StreamOutput(fopen('php://memory', 'r+', false));
+ }
+
+ protected function getConsoleOutput($stderr)
+ {
+ $output = new ConsoleOutput();
+ $output->setErrorOutput($stderr);
+
+ return $output;
+ }
+
+ private function hasStderrSupport()
+ {
+ return false === $this->isRunningOS400();
+ }
+
+ private function hasSttyAvailable()
+ {
+ exec('stty 2>&1', $output, $exitcode);
+
+ return $exitcode === 0;
+ }
+}
diff --git a/vendor/symfony/console/Tests/Helper/LegacyProgressHelperTest.php b/vendor/symfony/console/Tests/Helper/LegacyProgressHelperTest.php
new file mode 100644
index 00000000..f835a71e
--- /dev/null
+++ b/vendor/symfony/console/Tests/Helper/LegacyProgressHelperTest.php
@@ -0,0 +1,224 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\Helper;
+
+use Symfony\Component\Console\Helper\ProgressHelper;
+use Symfony\Component\Console\Output\StreamOutput;
+
+/**
+ * @group legacy
+ * @group time-sensitive
+ */
+class LegacyProgressHelperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testAdvance()
+ {
+ $progress = new ProgressHelper();
+ $progress->start($output = $this->getOutputStream());
+ $progress->advance();
+
+ rewind($output->getStream());
+ $this->assertEquals($this->generateOutput(' 1 [->--------------------------]'), stream_get_contents($output->getStream()));
+ }
+
+ public function testAdvanceWithStep()
+ {
+ $progress = new ProgressHelper();
+ $progress->start($output = $this->getOutputStream());
+ $progress->advance(5);
+
+ rewind($output->getStream());
+ $this->assertEquals($this->generateOutput(' 5 [----->----------------------]'), stream_get_contents($output->getStream()));
+ }
+
+ public function testAdvanceMultipleTimes()
+ {
+ $progress = new ProgressHelper();
+ $progress->start($output = $this->getOutputStream());
+ $progress->advance(3);
+ $progress->advance(2);
+
+ rewind($output->getStream());
+ $this->assertEquals($this->generateOutput(' 3 [--->------------------------]').$this->generateOutput(' 5 [----->----------------------]'), stream_get_contents($output->getStream()));
+ }
+
+ public function testCustomizations()
+ {
+ $progress = new ProgressHelper();
+ $progress->setBarWidth(10);
+ $progress->setBarCharacter('_');
+ $progress->setEmptyBarCharacter(' ');
+ $progress->setProgressCharacter('/');
+ $progress->setFormat(' %current%/%max% [%bar%] %percent%%');
+ $progress->start($output = $this->getOutputStream(), 10);
+ $progress->advance();
+
+ rewind($output->getStream());
+ $this->assertEquals($this->generateOutput(' 1/10 [_/ ] 10%'), stream_get_contents($output->getStream()));
+ }
+
+ public function testPercent()
+ {
+ $progress = new ProgressHelper();
+ $progress->start($output = $this->getOutputStream(), 50);
+ $progress->display();
+ $progress->advance();
+ $progress->advance();
+
+ rewind($output->getStream());
+ $this->assertEquals($this->generateOutput(' 0/50 [>---------------------------] 0%').$this->generateOutput(' 1/50 [>---------------------------] 2%').$this->generateOutput(' 2/50 [=>--------------------------] 4%'), stream_get_contents($output->getStream()));
+ }
+
+ public function testOverwriteWithShorterLine()
+ {
+ $progress = new ProgressHelper();
+ $progress->setFormat(' %current%/%max% [%bar%] %percent%%');
+ $progress->start($output = $this->getOutputStream(), 50);
+ $progress->display();
+ $progress->advance();
+
+ // set shorter format
+ $progress->setFormat(' %current%/%max% [%bar%]');
+ $progress->advance();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 0/50 [>---------------------------] 0%').
+ $this->generateOutput(' 1/50 [>---------------------------] 2%').
+ $this->generateOutput(' 2/50 [=>--------------------------] '),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testSetCurrentProgress()
+ {
+ $progress = new ProgressHelper();
+ $progress->start($output = $this->getOutputStream(), 50);
+ $progress->display();
+ $progress->advance();
+ $progress->setCurrent(15);
+ $progress->setCurrent(25);
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 0/50 [>---------------------------] 0%').
+ $this->generateOutput(' 1/50 [>---------------------------] 2%').
+ $this->generateOutput(' 15/50 [========>-------------------] 30%').
+ $this->generateOutput(' 25/50 [==============>-------------] 50%'),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ /**
+ * @expectedException \LogicException
+ * @expectedExceptionMessage You must start the progress bar
+ */
+ public function testSetCurrentBeforeStarting()
+ {
+ $progress = new ProgressHelper();
+ $progress->setCurrent(15);
+ }
+
+ /**
+ * @expectedException \LogicException
+ * @expectedExceptionMessage You can't regress the progress bar
+ */
+ public function testRegressProgress()
+ {
+ $progress = new ProgressHelper();
+ $progress->start($output = $this->getOutputStream(), 50);
+ $progress->setCurrent(15);
+ $progress->setCurrent(10);
+ }
+
+ public function testRedrawFrequency()
+ {
+ $progress = $this->getMock('Symfony\Component\Console\Helper\ProgressHelper', array('display'));
+ $progress->expects($this->exactly(4))
+ ->method('display');
+
+ $progress->setRedrawFrequency(2);
+
+ $progress->start($output = $this->getOutputStream(), 6);
+ $progress->setCurrent(1);
+ $progress->advance(2);
+ $progress->advance(2);
+ $progress->advance(1);
+ }
+
+ public function testMultiByteSupport()
+ {
+ $progress = new ProgressHelper();
+ $progress->start($output = $this->getOutputStream());
+ $progress->setBarCharacter('■');
+ $progress->advance(3);
+
+ rewind($output->getStream());
+ $this->assertEquals($this->generateOutput(' 3 [■■■>------------------------]'), stream_get_contents($output->getStream()));
+ }
+
+ public function testClear()
+ {
+ $progress = new ProgressHelper();
+ $progress->start($output = $this->getOutputStream(), 50);
+ $progress->setCurrent(25);
+ $progress->clear();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 25/50 [==============>-------------] 50%').$this->generateOutput(''),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testPercentNotHundredBeforeComplete()
+ {
+ $progress = new ProgressHelper();
+ $progress->start($output = $this->getOutputStream(), 200);
+ $progress->display();
+ $progress->advance(199);
+ $progress->advance();
+
+ rewind($output->getStream());
+ $this->assertEquals($this->generateOutput(' 0/200 [>---------------------------] 0%').$this->generateOutput(' 199/200 [===========================>] 99%').$this->generateOutput(' 200/200 [============================] 100%'), stream_get_contents($output->getStream()));
+ }
+
+ public function testNonDecoratedOutput()
+ {
+ $progress = new ProgressHelper();
+ $progress->start($output = $this->getOutputStream(false));
+ $progress->advance();
+
+ rewind($output->getStream());
+ $this->assertEquals('', stream_get_contents($output->getStream()));
+ }
+
+ protected function getOutputStream($decorated = true)
+ {
+ return new StreamOutput(fopen('php://memory', 'r+', false), StreamOutput::VERBOSITY_NORMAL, $decorated);
+ }
+
+ protected $lastMessagesLength;
+
+ protected function generateOutput($expected)
+ {
+ $expectedout = $expected;
+
+ if ($this->lastMessagesLength !== null) {
+ $expectedout = str_pad($expected, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
+ }
+
+ $this->lastMessagesLength = strlen($expectedout);
+
+ return "\x0D".$expectedout;
+ }
+}
diff --git a/vendor/symfony/console/Tests/Helper/LegacyTableHelperTest.php b/vendor/symfony/console/Tests/Helper/LegacyTableHelperTest.php
new file mode 100644
index 00000000..557dc14f
--- /dev/null
+++ b/vendor/symfony/console/Tests/Helper/LegacyTableHelperTest.php
@@ -0,0 +1,316 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\Helper;
+
+use Symfony\Component\Console\Helper\TableHelper;
+use Symfony\Component\Console\Output\StreamOutput;
+
+/**
+ * @group legacy
+ */
+class LegacyTableHelperTest extends \PHPUnit_Framework_TestCase
+{
+ protected $stream;
+
+ protected function setUp()
+ {
+ $this->stream = fopen('php://memory', 'r+');
+ }
+
+ protected function tearDown()
+ {
+ fclose($this->stream);
+ $this->stream = null;
+ }
+
+ /**
+ * @dataProvider testRenderProvider
+ */
+ public function testRender($headers, $rows, $layout, $expected)
+ {
+ $table = new TableHelper();
+ $table
+ ->setHeaders($headers)
+ ->setRows($rows)
+ ->setLayout($layout)
+ ;
+ $table->render($output = $this->getOutputStream());
+
+ $this->assertEquals($expected, $this->getOutputContent($output));
+ }
+
+ /**
+ * @dataProvider testRenderProvider
+ */
+ public function testRenderAddRows($headers, $rows, $layout, $expected)
+ {
+ $table = new TableHelper();
+ $table
+ ->setHeaders($headers)
+ ->addRows($rows)
+ ->setLayout($layout)
+ ;
+ $table->render($output = $this->getOutputStream());
+
+ $this->assertEquals($expected, $this->getOutputContent($output));
+ }
+
+ /**
+ * @dataProvider testRenderProvider
+ */
+ public function testRenderAddRowsOneByOne($headers, $rows, $layout, $expected)
+ {
+ $table = new TableHelper();
+ $table
+ ->setHeaders($headers)
+ ->setLayout($layout)
+ ;
+ foreach ($rows as $row) {
+ $table->addRow($row);
+ }
+ $table->render($output = $this->getOutputStream());
+
+ $this->assertEquals($expected, $this->getOutputContent($output));
+ }
+
+ public function testRenderProvider()
+ {
+ $books = array(
+ array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
+ array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'),
+ array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
+ array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
+ );
+
+ return array(
+ array(
+ array('ISBN', 'Title', 'Author'),
+ $books,
+ TableHelper::LAYOUT_DEFAULT,
+<<<'TABLE'
++---------------+--------------------------+------------------+
+| ISBN | Title | Author |
++---------------+--------------------------+------------------+
+| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
+| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
+| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
+| 80-902734-1-6 | And Then There Were None | Agatha Christie |
++---------------+--------------------------+------------------+
+
+TABLE
+ ),
+ array(
+ array('ISBN', 'Title', 'Author'),
+ $books,
+ TableHelper::LAYOUT_COMPACT,
+<<<TABLE
+ ISBN Title Author
+ 99921-58-10-7 Divine Comedy Dante Alighieri
+ 9971-5-0210-0 A Tale of Two Cities Charles Dickens
+ 960-425-059-0 The Lord of the Rings J. R. R. Tolkien
+ 80-902734-1-6 And Then There Were None Agatha Christie
+
+TABLE
+ ),
+ array(
+ array('ISBN', 'Title', 'Author'),
+ $books,
+ TableHelper::LAYOUT_BORDERLESS,
+<<<TABLE
+ =============== ========================== ==================
+ ISBN Title Author
+ =============== ========================== ==================
+ 99921-58-10-7 Divine Comedy Dante Alighieri
+ 9971-5-0210-0 A Tale of Two Cities Charles Dickens
+ 960-425-059-0 The Lord of the Rings J. R. R. Tolkien
+ 80-902734-1-6 And Then There Were None Agatha Christie
+ =============== ========================== ==================
+
+TABLE
+ ),
+ array(
+ array('ISBN', 'Title'),
+ array(
+ array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
+ array('9971-5-0210-0'),
+ array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
+ array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
+ ),
+ TableHelper::LAYOUT_DEFAULT,
+<<<'TABLE'
++---------------+--------------------------+------------------+
+| ISBN | Title | |
++---------------+--------------------------+------------------+
+| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
+| 9971-5-0210-0 | | |
+| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
+| 80-902734-1-6 | And Then There Were None | Agatha Christie |
++---------------+--------------------------+------------------+
+
+TABLE
+ ),
+ array(
+ array(),
+ array(
+ array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
+ array('9971-5-0210-0'),
+ array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
+ array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
+ ),
+ TableHelper::LAYOUT_DEFAULT,
+<<<'TABLE'
++---------------+--------------------------+------------------+
+| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
+| 9971-5-0210-0 | | |
+| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
+| 80-902734-1-6 | And Then There Were None | Agatha Christie |
++---------------+--------------------------+------------------+
+
+TABLE
+ ),
+ array(
+ array('ISBN', 'Title', 'Author'),
+ array(
+ array('99921-58-10-7', "Divine\nComedy", 'Dante Alighieri'),
+ array('9971-5-0210-2', "Harry Potter\nand the Chamber of Secrets", "Rowling\nJoanne K."),
+ array('9971-5-0210-2', "Harry Potter\nand the Chamber of Secrets", "Rowling\nJoanne K."),
+ array('960-425-059-0', 'The Lord of the Rings', "J. R. R.\nTolkien"),
+ ),
+ TableHelper::LAYOUT_DEFAULT,
+<<<'TABLE'
++---------------+----------------------------+-----------------+
+| ISBN | Title | Author |
++---------------+----------------------------+-----------------+
+| 99921-58-10-7 | Divine | Dante Alighieri |
+| | Comedy | |
+| 9971-5-0210-2 | Harry Potter | Rowling |
+| | and the Chamber of Secrets | Joanne K. |
+| 9971-5-0210-2 | Harry Potter | Rowling |
+| | and the Chamber of Secrets | Joanne K. |
+| 960-425-059-0 | The Lord of the Rings | J. R. R. |
+| | | Tolkien |
++---------------+----------------------------+-----------------+
+
+TABLE
+ ),
+ array(
+ array('ISBN', 'Title'),
+ array(),
+ TableHelper::LAYOUT_DEFAULT,
+<<<'TABLE'
++------+-------+
+| ISBN | Title |
++------+-------+
+
+TABLE
+ ),
+ array(
+ array(),
+ array(),
+ TableHelper::LAYOUT_DEFAULT,
+ '',
+ ),
+ 'Cell text with tags used for Output styling' => array(
+ array('ISBN', 'Title', 'Author'),
+ array(
+ array('<info>99921-58-10-7</info>', '<error>Divine Comedy</error>', '<fg=blue;bg=white>Dante Alighieri</fg=blue;bg=white>'),
+ array('9971-5-0210-0', 'A Tale of Two Cities', '<info>Charles Dickens</>'),
+ ),
+ TableHelper::LAYOUT_DEFAULT,
+<<<'TABLE'
++---------------+----------------------+-----------------+
+| ISBN | Title | Author |
++---------------+----------------------+-----------------+
+| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
+| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
++---------------+----------------------+-----------------+
+
+TABLE
+ ),
+ 'Cell text with tags not used for Output styling' => array(
+ array('ISBN', 'Title', 'Author'),
+ array(
+ array('<strong>99921-58-10-700</strong>', '<f>Divine Com</f>', 'Dante Alighieri'),
+ array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'),
+ ),
+ TableHelper::LAYOUT_DEFAULT,
+<<<'TABLE'
++----------------------------------+----------------------+-----------------+
+| ISBN | Title | Author |
++----------------------------------+----------------------+-----------------+
+| <strong>99921-58-10-700</strong> | <f>Divine Com</f> | Dante Alighieri |
+| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
++----------------------------------+----------------------+-----------------+
+
+TABLE
+ ),
+ );
+ }
+
+ public function testRenderMultiByte()
+ {
+ $table = new TableHelper();
+ $table
+ ->setHeaders(array('■■'))
+ ->setRows(array(array(1234)))
+ ->setLayout(TableHelper::LAYOUT_DEFAULT)
+ ;
+ $table->render($output = $this->getOutputStream());
+
+ $expected =
+<<<'TABLE'
++------+
+| ■■ |
++------+
+| 1234 |
++------+
+
+TABLE;
+
+ $this->assertEquals($expected, $this->getOutputContent($output));
+ }
+
+ public function testRenderFullWidthCharacters()
+ {
+ $table = new TableHelper();
+ $table
+ ->setHeaders(array('あいうえお'))
+ ->setRows(array(array(1234567890)))
+ ->setLayout(TableHelper::LAYOUT_DEFAULT)
+ ;
+ $table->render($output = $this->getOutputStream());
+
+ $expected =
+ <<<'TABLE'
++------------+
+| あいうえお |
++------------+
+| 1234567890 |
++------------+
+
+TABLE;
+
+ $this->assertEquals($expected, $this->getOutputContent($output));
+ }
+
+ protected function getOutputStream()
+ {
+ return new StreamOutput($this->stream, StreamOutput::VERBOSITY_NORMAL, false);
+ }
+
+ protected function getOutputContent(StreamOutput $output)
+ {
+ rewind($output->getStream());
+
+ return str_replace(PHP_EOL, "\n", stream_get_contents($output->getStream()));
+ }
+}
diff --git a/vendor/symfony/console/Tests/Helper/ProcessHelperTest.php b/vendor/symfony/console/Tests/Helper/ProcessHelperTest.php
new file mode 100644
index 00000000..a51fb435
--- /dev/null
+++ b/vendor/symfony/console/Tests/Helper/ProcessHelperTest.php
@@ -0,0 +1,117 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\Helper;
+
+use Symfony\Component\Console\Helper\DebugFormatterHelper;
+use Symfony\Component\Console\Helper\HelperSet;
+use Symfony\Component\Console\Output\StreamOutput;
+use Symfony\Component\Console\Helper\ProcessHelper;
+use Symfony\Component\Process\Process;
+
+class ProcessHelperTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @dataProvider provideCommandsAndOutput
+ */
+ public function testVariousProcessRuns($expected, $cmd, $verbosity, $error)
+ {
+ $helper = new ProcessHelper();
+ $helper->setHelperSet(new HelperSet(array(new DebugFormatterHelper())));
+ $output = $this->getOutputStream($verbosity);
+ $helper->run($output, $cmd, $error);
+ $this->assertEquals($expected, $this->getOutput($output));
+ }
+
+ public function testPassedCallbackIsExecuted()
+ {
+ $helper = new ProcessHelper();
+ $helper->setHelperSet(new HelperSet(array(new DebugFormatterHelper())));
+ $output = $this->getOutputStream(StreamOutput::VERBOSITY_NORMAL);
+
+ $executed = false;
+ $callback = function () use (&$executed) { $executed = true; };
+
+ $helper->run($output, 'php -r "echo 42;"', null, $callback);
+ $this->assertTrue($executed);
+ }
+
+ public function provideCommandsAndOutput()
+ {
+ $successOutputVerbose = <<<EOT
+ RUN php -r "echo 42;"
+ RES Command ran successfully
+
+EOT;
+ $successOutputDebug = <<<EOT
+ RUN php -r "echo 42;"
+ OUT 42
+ RES Command ran successfully
+
+EOT;
+ $successOutputDebugWithTags = <<<EOT
+ RUN php -r "echo '<info>42</info>';"
+ OUT <info>42</info>
+ RES Command ran successfully
+
+EOT;
+ $successOutputProcessDebug = <<<EOT
+ RUN 'php' '-r' 'echo 42;'
+ OUT 42
+ RES Command ran successfully
+
+EOT;
+ $syntaxErrorOutputVerbose = <<<EOT
+ RUN php -r "fwrite(STDERR, 'error message');usleep(50000);fwrite(STDOUT, 'out message');exit(252);"
+ RES 252 Command did not run successfully
+
+EOT;
+ $syntaxErrorOutputDebug = <<<EOT
+ RUN php -r "fwrite(STDERR, 'error message');usleep(500000);fwrite(STDOUT, 'out message');exit(252);"
+ ERR error message
+ OUT out message
+ RES 252 Command did not run successfully
+
+EOT;
+
+ $errorMessage = 'An error occurred';
+ if ('\\' === DIRECTORY_SEPARATOR) {
+ $successOutputProcessDebug = str_replace("'", '"', $successOutputProcessDebug);
+ }
+
+ return array(
+ array('', 'php -r "echo 42;"', StreamOutput::VERBOSITY_VERBOSE, null),
+ array($successOutputVerbose, 'php -r "echo 42;"', StreamOutput::VERBOSITY_VERY_VERBOSE, null),
+ array($successOutputDebug, 'php -r "echo 42;"', StreamOutput::VERBOSITY_DEBUG, null),
+ array($successOutputDebugWithTags, 'php -r "echo \'<info>42</info>\';"', StreamOutput::VERBOSITY_DEBUG, null),
+ array('', 'php -r "syntax error"', StreamOutput::VERBOSITY_VERBOSE, null),
+ array($syntaxErrorOutputVerbose, 'php -r "fwrite(STDERR, \'error message\');usleep(50000);fwrite(STDOUT, \'out message\');exit(252);"', StreamOutput::VERBOSITY_VERY_VERBOSE, null),
+ array($syntaxErrorOutputDebug, 'php -r "fwrite(STDERR, \'error message\');usleep(500000);fwrite(STDOUT, \'out message\');exit(252);"', StreamOutput::VERBOSITY_DEBUG, null),
+ array($errorMessage.PHP_EOL, 'php -r "fwrite(STDERR, \'error message\');usleep(50000);fwrite(STDOUT, \'out message\');exit(252);"', StreamOutput::VERBOSITY_VERBOSE, $errorMessage),
+ array($syntaxErrorOutputVerbose.$errorMessage.PHP_EOL, 'php -r "fwrite(STDERR, \'error message\');usleep(50000);fwrite(STDOUT, \'out message\');exit(252);"', StreamOutput::VERBOSITY_VERY_VERBOSE, $errorMessage),
+ array($syntaxErrorOutputDebug.$errorMessage.PHP_EOL, 'php -r "fwrite(STDERR, \'error message\');usleep(500000);fwrite(STDOUT, \'out message\');exit(252);"', StreamOutput::VERBOSITY_DEBUG, $errorMessage),
+ array($successOutputProcessDebug, array('php', '-r', 'echo 42;'), StreamOutput::VERBOSITY_DEBUG, null),
+ array($successOutputDebug, new Process('php -r "echo 42;"'), StreamOutput::VERBOSITY_DEBUG, null),
+ );
+ }
+
+ private function getOutputStream($verbosity)
+ {
+ return new StreamOutput(fopen('php://memory', 'r+', false), $verbosity, false);
+ }
+
+ private function getOutput(StreamOutput $output)
+ {
+ rewind($output->getStream());
+
+ return stream_get_contents($output->getStream());
+ }
+}
diff --git a/vendor/symfony/console/Tests/Helper/ProgressBarTest.php b/vendor/symfony/console/Tests/Helper/ProgressBarTest.php
new file mode 100644
index 00000000..261908b5
--- /dev/null
+++ b/vendor/symfony/console/Tests/Helper/ProgressBarTest.php
@@ -0,0 +1,664 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\Helper;
+
+use Symfony\Component\Console\Helper\ProgressBar;
+use Symfony\Component\Console\Helper\Helper;
+use Symfony\Component\Console\Output\StreamOutput;
+
+/**
+ * @group time-sensitive
+ */
+class ProgressBarTest extends \PHPUnit_Framework_TestCase
+{
+ public function testMultipleStart()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream());
+ $bar->start();
+ $bar->advance();
+ $bar->start();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 0 [>---------------------------]').
+ $this->generateOutput(' 1 [->--------------------------]').
+ $this->generateOutput(' 0 [>---------------------------]'),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testAdvance()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream());
+ $bar->start();
+ $bar->advance();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 0 [>---------------------------]').
+ $this->generateOutput(' 1 [->--------------------------]'),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testAdvanceWithStep()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream());
+ $bar->start();
+ $bar->advance(5);
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 0 [>---------------------------]').
+ $this->generateOutput(' 5 [----->----------------------]'),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testAdvanceMultipleTimes()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream());
+ $bar->start();
+ $bar->advance(3);
+ $bar->advance(2);
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 0 [>---------------------------]').
+ $this->generateOutput(' 3 [--->------------------------]').
+ $this->generateOutput(' 5 [----->----------------------]'),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testAdvanceOverMax()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream(), 10);
+ $bar->setProgress(9);
+ $bar->advance();
+ $bar->advance();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 9/10 [=========================>--] 90%').
+ $this->generateOutput(' 10/10 [============================] 100%').
+ $this->generateOutput(' 11/11 [============================] 100%'),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testFormat()
+ {
+ $expected =
+ $this->generateOutput(' 0/10 [>---------------------------] 0%').
+ $this->generateOutput(' 10/10 [============================] 100%').
+ $this->generateOutput(' 10/10 [============================] 100%')
+ ;
+
+ // max in construct, no format
+ $bar = new ProgressBar($output = $this->getOutputStream(), 10);
+ $bar->start();
+ $bar->advance(10);
+ $bar->finish();
+
+ rewind($output->getStream());
+ $this->assertEquals($expected, stream_get_contents($output->getStream()));
+
+ // max in start, no format
+ $bar = new ProgressBar($output = $this->getOutputStream());
+ $bar->start(10);
+ $bar->advance(10);
+ $bar->finish();
+
+ rewind($output->getStream());
+ $this->assertEquals($expected, stream_get_contents($output->getStream()));
+
+ // max in construct, explicit format before
+ $bar = new ProgressBar($output = $this->getOutputStream(), 10);
+ $bar->setFormat('normal');
+ $bar->start();
+ $bar->advance(10);
+ $bar->finish();
+
+ rewind($output->getStream());
+ $this->assertEquals($expected, stream_get_contents($output->getStream()));
+
+ // max in start, explicit format before
+ $bar = new ProgressBar($output = $this->getOutputStream());
+ $bar->setFormat('normal');
+ $bar->start(10);
+ $bar->advance(10);
+ $bar->finish();
+
+ rewind($output->getStream());
+ $this->assertEquals($expected, stream_get_contents($output->getStream()));
+ }
+
+ public function testCustomizations()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream(), 10);
+ $bar->setBarWidth(10);
+ $bar->setBarCharacter('_');
+ $bar->setEmptyBarCharacter(' ');
+ $bar->setProgressCharacter('/');
+ $bar->setFormat(' %current%/%max% [%bar%] %percent:3s%%');
+ $bar->start();
+ $bar->advance();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 0/10 [/ ] 0%').
+ $this->generateOutput(' 1/10 [_/ ] 10%'),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testDisplayWithoutStart()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream(), 50);
+ $bar->display();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 0/50 [>---------------------------] 0%'),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testDisplayWithQuietVerbosity()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream(true, StreamOutput::VERBOSITY_QUIET), 50);
+ $bar->display();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ '',
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testFinishWithoutStart()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream(), 50);
+ $bar->finish();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 50/50 [============================] 100%'),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testPercent()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream(), 50);
+ $bar->start();
+ $bar->display();
+ $bar->advance();
+ $bar->advance();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 0/50 [>---------------------------] 0%').
+ $this->generateOutput(' 0/50 [>---------------------------] 0%').
+ $this->generateOutput(' 1/50 [>---------------------------] 2%').
+ $this->generateOutput(' 2/50 [=>--------------------------] 4%'),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testOverwriteWithShorterLine()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream(), 50);
+ $bar->setFormat(' %current%/%max% [%bar%] %percent:3s%%');
+ $bar->start();
+ $bar->display();
+ $bar->advance();
+
+ // set shorter format
+ $bar->setFormat(' %current%/%max% [%bar%]');
+ $bar->advance();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 0/50 [>---------------------------] 0%').
+ $this->generateOutput(' 0/50 [>---------------------------] 0%').
+ $this->generateOutput(' 1/50 [>---------------------------] 2%').
+ $this->generateOutput(' 2/50 [=>--------------------------]'),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testStartWithMax()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream());
+ $bar->setFormat('%current%/%max% [%bar%]');
+ $bar->start(50);
+ $bar->advance();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 0/50 [>---------------------------]').
+ $this->generateOutput(' 1/50 [>---------------------------]'),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testSetCurrentProgress()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream(), 50);
+ $bar->start();
+ $bar->display();
+ $bar->advance();
+ $bar->setProgress(15);
+ $bar->setProgress(25);
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 0/50 [>---------------------------] 0%').
+ $this->generateOutput(' 0/50 [>---------------------------] 0%').
+ $this->generateOutput(' 1/50 [>---------------------------] 2%').
+ $this->generateOutput(' 15/50 [========>-------------------] 30%').
+ $this->generateOutput(' 25/50 [==============>-------------] 50%'),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ /**
+ */
+ public function testSetCurrentBeforeStarting()
+ {
+ $bar = new ProgressBar($this->getOutputStream());
+ $bar->setProgress(15);
+ $this->assertNotNull($bar->getStartTime());
+ }
+
+ /**
+ * @expectedException \LogicException
+ * @expectedExceptionMessage You can't regress the progress bar
+ */
+ public function testRegressProgress()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream(), 50);
+ $bar->start();
+ $bar->setProgress(15);
+ $bar->setProgress(10);
+ }
+
+ public function testRedrawFrequency()
+ {
+ $bar = $this->getMock('Symfony\Component\Console\Helper\ProgressBar', array('display'), array($this->getOutputStream(), 6));
+ $bar->expects($this->exactly(4))->method('display');
+
+ $bar->setRedrawFrequency(2);
+ $bar->start();
+ $bar->setProgress(1);
+ $bar->advance(2);
+ $bar->advance(2);
+ $bar->advance(1);
+ }
+
+ public function testRedrawFrequencyIsAtLeastOneIfZeroGiven()
+ {
+ $bar = $this->getMock('Symfony\Component\Console\Helper\ProgressBar', array('display'), array($this->getOutputStream()));
+
+ $bar->expects($this->exactly(2))->method('display');
+ $bar->setRedrawFrequency(0);
+ $bar->start();
+ $bar->advance();
+ }
+
+ public function testRedrawFrequencyIsAtLeastOneIfSmallerOneGiven()
+ {
+ $bar = $this->getMock('Symfony\Component\Console\Helper\ProgressBar', array('display'), array($this->getOutputStream()));
+
+ $bar->expects($this->exactly(2))->method('display');
+ $bar->setRedrawFrequency(0.9);
+ $bar->start();
+ $bar->advance();
+ }
+
+ public function testMultiByteSupport()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream());
+ $bar->start();
+ $bar->setBarCharacter('■');
+ $bar->advance(3);
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 0 [>---------------------------]').
+ $this->generateOutput(' 3 [■■■>------------------------]'),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testClear()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream(), 50);
+ $bar->start();
+ $bar->setProgress(25);
+ $bar->clear();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 0/50 [>---------------------------] 0%').
+ $this->generateOutput(' 25/50 [==============>-------------] 50%').
+ $this->generateOutput(''),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testPercentNotHundredBeforeComplete()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream(), 200);
+ $bar->start();
+ $bar->display();
+ $bar->advance(199);
+ $bar->advance();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 0/200 [>---------------------------] 0%').
+ $this->generateOutput(' 0/200 [>---------------------------] 0%').
+ $this->generateOutput(' 199/200 [===========================>] 99%').
+ $this->generateOutput(' 200/200 [============================] 100%'),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testNonDecoratedOutput()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream(false), 200);
+ $bar->start();
+
+ for ($i = 0; $i < 200; ++$i) {
+ $bar->advance();
+ }
+
+ $bar->finish();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ ' 0/200 [>---------------------------] 0%'.PHP_EOL.
+ ' 20/200 [==>-------------------------] 10%'.PHP_EOL.
+ ' 40/200 [=====>----------------------] 20%'.PHP_EOL.
+ ' 60/200 [========>-------------------] 30%'.PHP_EOL.
+ ' 80/200 [===========>----------------] 40%'.PHP_EOL.
+ ' 100/200 [==============>-------------] 50%'.PHP_EOL.
+ ' 120/200 [================>-----------] 60%'.PHP_EOL.
+ ' 140/200 [===================>--------] 70%'.PHP_EOL.
+ ' 160/200 [======================>-----] 80%'.PHP_EOL.
+ ' 180/200 [=========================>--] 90%'.PHP_EOL.
+ ' 200/200 [============================] 100%',
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testNonDecoratedOutputWithClear()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream(false), 50);
+ $bar->start();
+ $bar->setProgress(25);
+ $bar->clear();
+ $bar->setProgress(50);
+ $bar->finish();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ ' 0/50 [>---------------------------] 0%'.PHP_EOL.
+ ' 25/50 [==============>-------------] 50%'.PHP_EOL.
+ ' 50/50 [============================] 100%',
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testNonDecoratedOutputWithoutMax()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream(false));
+ $bar->start();
+ $bar->advance();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ ' 0 [>---------------------------]'.PHP_EOL.
+ ' 1 [->--------------------------]',
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testParallelBars()
+ {
+ $output = $this->getOutputStream();
+ $bar1 = new ProgressBar($output, 2);
+ $bar2 = new ProgressBar($output, 3);
+ $bar2->setProgressCharacter('#');
+ $bar3 = new ProgressBar($output);
+
+ $bar1->start();
+ $output->write("\n");
+ $bar2->start();
+ $output->write("\n");
+ $bar3->start();
+
+ for ($i = 1; $i <= 3; ++$i) {
+ // up two lines
+ $output->write("\033[2A");
+ if ($i <= 2) {
+ $bar1->advance();
+ }
+ $output->write("\n");
+ $bar2->advance();
+ $output->write("\n");
+ $bar3->advance();
+ }
+ $output->write("\033[2A");
+ $output->write("\n");
+ $output->write("\n");
+ $bar3->finish();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 0/2 [>---------------------------] 0%')."\n".
+ $this->generateOutput(' 0/3 [#---------------------------] 0%')."\n".
+ rtrim($this->generateOutput(' 0 [>---------------------------]')).
+
+ "\033[2A".
+ $this->generateOutput(' 1/2 [==============>-------------] 50%')."\n".
+ $this->generateOutput(' 1/3 [=========#------------------] 33%')."\n".
+ rtrim($this->generateOutput(' 1 [->--------------------------]')).
+
+ "\033[2A".
+ $this->generateOutput(' 2/2 [============================] 100%')."\n".
+ $this->generateOutput(' 2/3 [==================#---------] 66%')."\n".
+ rtrim($this->generateOutput(' 2 [-->-------------------------]')).
+
+ "\033[2A".
+ "\n".
+ $this->generateOutput(' 3/3 [============================] 100%')."\n".
+ rtrim($this->generateOutput(' 3 [--->------------------------]')).
+
+ "\033[2A".
+ "\n".
+ "\n".
+ rtrim($this->generateOutput(' 3 [============================]')),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testWithoutMax()
+ {
+ $output = $this->getOutputStream();
+
+ $bar = new ProgressBar($output);
+ $bar->start();
+ $bar->advance();
+ $bar->advance();
+ $bar->advance();
+ $bar->finish();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ rtrim($this->generateOutput(' 0 [>---------------------------]')).
+ rtrim($this->generateOutput(' 1 [->--------------------------]')).
+ rtrim($this->generateOutput(' 2 [-->-------------------------]')).
+ rtrim($this->generateOutput(' 3 [--->------------------------]')).
+ rtrim($this->generateOutput(' 3 [============================]')),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testAddingPlaceholderFormatter()
+ {
+ ProgressBar::setPlaceholderFormatterDefinition('remaining_steps', function (ProgressBar $bar) {
+ return $bar->getMaxSteps() - $bar->getProgress();
+ });
+ $bar = new ProgressBar($output = $this->getOutputStream(), 3);
+ $bar->setFormat(' %remaining_steps% [%bar%]');
+
+ $bar->start();
+ $bar->advance();
+ $bar->finish();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 3 [>---------------------------]').
+ $this->generateOutput(' 2 [=========>------------------]').
+ $this->generateOutput(' 0 [============================]'),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testMultilineFormat()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream(), 3);
+ $bar->setFormat("%bar%\nfoobar");
+
+ $bar->start();
+ $bar->advance();
+ $bar->clear();
+ $bar->finish();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(">---------------------------\nfoobar").
+ $this->generateOutput("=========>------------------\nfoobar").
+ "\x0D\x1B[2K\x1B[1A\x1B[2K".
+ $this->generateOutput("============================\nfoobar"),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testAnsiColorsAndEmojis()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream(), 15);
+ ProgressBar::setPlaceholderFormatterDefinition('memory', function (ProgressBar $bar) {
+ static $i = 0;
+ $mem = 100000 * $i;
+ $colors = $i++ ? '41;37' : '44;37';
+
+ return "\033[".$colors.'m '.Helper::formatMemory($mem)." \033[0m";
+ });
+ $bar->setFormat(" \033[44;37m %title:-37s% \033[0m\n %current%/%max% %bar% %percent:3s%%\n 🏁 %remaining:-10s% %memory:37s%");
+ $bar->setBarCharacter($done = "\033[32m●\033[0m");
+ $bar->setEmptyBarCharacter($empty = "\033[31m●\033[0m");
+ $bar->setProgressCharacter($progress = "\033[32m➤ \033[0m");
+
+ $bar->setMessage('Starting the demo... fingers crossed', 'title');
+ $bar->start();
+ $bar->setMessage('Looks good to me...', 'title');
+ $bar->advance(4);
+ $bar->setMessage('Thanks, bye', 'title');
+ $bar->finish();
+
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(
+ " \033[44;37m Starting the demo... fingers crossed \033[0m\n".
+ ' 0/15 '.$progress.str_repeat($empty, 26)." 0%\n".
+ " \xf0\x9f\x8f\x81 < 1 sec \033[44;37m 0 B \033[0m"
+ ).
+ $this->generateOutput(
+ " \033[44;37m Looks good to me... \033[0m\n".
+ ' 4/15 '.str_repeat($done, 7).$progress.str_repeat($empty, 19)." 26%\n".
+ " \xf0\x9f\x8f\x81 < 1 sec \033[41;37m 97 KiB \033[0m"
+ ).
+ $this->generateOutput(
+ " \033[44;37m Thanks, bye \033[0m\n".
+ ' 15/15 '.str_repeat($done, 28)." 100%\n".
+ " \xf0\x9f\x8f\x81 < 1 sec \033[41;37m 195 KiB \033[0m"
+ ),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testSetFormat()
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream());
+ $bar->setFormat('normal');
+ $bar->start();
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 0 [>---------------------------]'),
+ stream_get_contents($output->getStream())
+ );
+
+ $bar = new ProgressBar($output = $this->getOutputStream(), 10);
+ $bar->setFormat('normal');
+ $bar->start();
+ rewind($output->getStream());
+ $this->assertEquals(
+ $this->generateOutput(' 0/10 [>---------------------------] 0%'),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ /**
+ * @dataProvider provideFormat
+ */
+ public function testFormatsWithoutMax($format)
+ {
+ $bar = new ProgressBar($output = $this->getOutputStream());
+ $bar->setFormat($format);
+ $bar->start();
+
+ rewind($output->getStream());
+ $this->assertNotEmpty(stream_get_contents($output->getStream()));
+ }
+
+ /**
+ * Provides each defined format.
+ *
+ * @return array
+ */
+ public function provideFormat()
+ {
+ return array(
+ array('normal'),
+ array('verbose'),
+ array('very_verbose'),
+ array('debug'),
+ );
+ }
+
+ protected function getOutputStream($decorated = true, $verbosity = StreamOutput::VERBOSITY_NORMAL)
+ {
+ return new StreamOutput(fopen('php://memory', 'r+', false), $verbosity, $decorated);
+ }
+
+ protected function generateOutput($expected)
+ {
+ $count = substr_count($expected, "\n");
+
+ return "\x0D\x1B[2K".($count ? str_repeat("\x1B[1A\x1B[2K", $count) : '').$expected;
+ }
+}
diff --git a/vendor/symfony/console/Tests/Helper/ProgressIndicatorTest.php b/vendor/symfony/console/Tests/Helper/ProgressIndicatorTest.php
new file mode 100644
index 00000000..19262526
--- /dev/null
+++ b/vendor/symfony/console/Tests/Helper/ProgressIndicatorTest.php
@@ -0,0 +1,182 @@
+<?php
+
+namespace Symfony\Component\Console\Tests\Helper;
+
+use Symfony\Component\Console\Helper\ProgressIndicator;
+use Symfony\Component\Console\Output\StreamOutput;
+
+/**
+ * @group time-sensitive
+ */
+class ProgressIndicatorTest extends \PHPUnit_Framework_TestCase
+{
+ public function testDefaultIndicator()
+ {
+ $bar = new ProgressIndicator($output = $this->getOutputStream());
+ $bar->start('Starting...');
+ usleep(101000);
+ $bar->advance();
+ usleep(101000);
+ $bar->advance();
+ usleep(101000);
+ $bar->advance();
+ usleep(101000);
+ $bar->advance();
+ usleep(101000);
+ $bar->advance();
+ usleep(101000);
+ $bar->setMessage('Advancing...');
+ $bar->advance();
+ $bar->finish('Done...');
+ $bar->start('Starting Again...');
+ usleep(101000);
+ $bar->advance();
+ $bar->finish('Done Again...');
+
+ rewind($output->getStream());
+
+ $this->assertEquals(
+ $this->generateOutput(' - Starting...').
+ $this->generateOutput(' \\ Starting...').
+ $this->generateOutput(' | Starting...').
+ $this->generateOutput(' / Starting...').
+ $this->generateOutput(' - Starting...').
+ $this->generateOutput(' \\ Starting...').
+ $this->generateOutput(' \\ Advancing...').
+ $this->generateOutput(' | Advancing...').
+ $this->generateOutput(' | Done... ').
+ PHP_EOL.
+ $this->generateOutput(' - Starting Again...').
+ $this->generateOutput(' \\ Starting Again...').
+ $this->generateOutput(' \\ Done Again... ').
+ PHP_EOL,
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testNonDecoratedOutput()
+ {
+ $bar = new ProgressIndicator($output = $this->getOutputStream(false));
+
+ $bar->start('Starting...');
+ $bar->advance();
+ $bar->advance();
+ $bar->setMessage('Midway...');
+ $bar->advance();
+ $bar->advance();
+ $bar->finish('Done...');
+
+ rewind($output->getStream());
+
+ $this->assertEquals(
+ ' Starting...'.PHP_EOL.
+ ' Midway... '.PHP_EOL.
+ ' Done... '.PHP_EOL.PHP_EOL,
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ public function testCustomIndicatorValues()
+ {
+ $bar = new ProgressIndicator($output = $this->getOutputStream(), null, 100, array('a', 'b', 'c'));
+
+ $bar->start('Starting...');
+ usleep(101000);
+ $bar->advance();
+ usleep(101000);
+ $bar->advance();
+ usleep(101000);
+ $bar->advance();
+
+ rewind($output->getStream());
+
+ $this->assertEquals(
+ $this->generateOutput(' a Starting...').
+ $this->generateOutput(' b Starting...').
+ $this->generateOutput(' c Starting...').
+ $this->generateOutput(' a Starting...'),
+ stream_get_contents($output->getStream())
+ );
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Must have at least 2 indicator value characters.
+ */
+ public function testCannotSetInvalidIndicatorCharacters()
+ {
+ $bar = new ProgressIndicator($this->getOutputStream(), null, 100, array('1'));
+ }
+
+ /**
+ * @expectedException \LogicException
+ * @expectedExceptionMessage Progress indicator already started.
+ */
+ public function testCannotStartAlreadyStartedIndicator()
+ {
+ $bar = new ProgressIndicator($this->getOutputStream());
+ $bar->start('Starting...');
+ $bar->start('Starting Again.');
+ }
+
+ /**
+ * @expectedException \LogicException
+ * @expectedExceptionMessage Progress indicator has not yet been started.
+ */
+ public function testCannotAdvanceUnstartedIndicator()
+ {
+ $bar = new ProgressIndicator($this->getOutputStream());
+ $bar->advance();
+ }
+
+ /**
+ * @expectedException \LogicException
+ * @expectedExceptionMessage Progress indicator has not yet been started.
+ */
+ public function testCannotFinishUnstartedIndicator()
+ {
+ $bar = new ProgressIndicator($this->getOutputStream());
+ $bar->finish('Finished');
+ }
+
+ /**
+ * @dataProvider provideFormat
+ */
+ public function testFormats($format)
+ {
+ $bar = new ProgressIndicator($output = $this->getOutputStream(), $format);
+ $bar->start('Starting...');
+ $bar->advance();
+
+ rewind($output->getStream());
+
+ $this->assertNotEmpty(stream_get_contents($output->getStream()));
+ }
+
+ /**
+ * Provides each defined format.
+ *
+ * @return array
+ */
+ public function provideFormat()
+ {
+ return array(
+ array('normal'),
+ array('verbose'),
+ array('very_verbose'),
+ array('debug'),
+ );
+ }
+
+ protected function getOutputStream($decorated = true, $verbosity = StreamOutput::VERBOSITY_NORMAL)
+ {
+ return new StreamOutput(fopen('php://memory', 'r+', false), $verbosity, $decorated);
+ }
+
+ protected function generateOutput($expected)
+ {
+ $count = substr_count($expected, "\n");
+
+ return "\x0D".($count ? sprintf("\033[%dA", $count) : '').$expected;
+ }
+}
diff --git a/vendor/symfony/console/Tests/Helper/QuestionHelperTest.php b/vendor/symfony/console/Tests/Helper/QuestionHelperTest.php
new file mode 100644
index 00000000..6a4f8ace
--- /dev/null
+++ b/vendor/symfony/console/Tests/Helper/QuestionHelperTest.php
@@ -0,0 +1,435 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\Helper;
+
+use Symfony\Component\Console\Formatter\OutputFormatter;
+use Symfony\Component\Console\Helper\QuestionHelper;
+use Symfony\Component\Console\Helper\HelperSet;
+use Symfony\Component\Console\Helper\FormatterHelper;
+use Symfony\Component\Console\Output\StreamOutput;
+use Symfony\Component\Console\Question\ChoiceQuestion;
+use Symfony\Component\Console\Question\ConfirmationQuestion;
+use Symfony\Component\Console\Question\Question;
+
+/**
+ * @group tty
+ */
+class QuestionHelperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testAskChoice()
+ {
+ $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));
+ }
+
+ public function testAsk()
+ {
+ $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()));
+ }
+
+ public function testAskWithAutocomplete()
+ {
+ 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));
+ }
+
+ public function testAskWithAutocompleteWithNonSequentialKeys()
+ {
+ 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));
+ }
+
+ public function testAskHiddenResponse()
+ {
+ 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));
+ }
+
+ /**
+ * @dataProvider getAskConfirmationData
+ */
+ public function testAskConfirmation($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'));
+ }
+
+ public function getAskConfirmationData()
+ {
+ return array(
+ array('', true),
+ array('', false, false),
+ array('y', true),
+ array('yes', true),
+ array('n', false),
+ array('no', false),
+ );
+ }
+
+ public function testAskConfirmationWithCustomTrueAnswer()
+ {
+ $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));
+ }
+
+ public function testAskAndValidate()
+ {
+ $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());
+ }
+ }
+
+ /**
+ * @dataProvider simpleAnswerProvider
+ */
+ public function testSelectChoiceFromSimpleChoices($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);
+ }
+
+ public function simpleAnswerProvider()
+ {
+ return array(
+ array(0, 'My environment 1'),
+ array(1, 'My environment 2'),
+ array(2, 'My environment 3'),
+ array('My environment 1', 'My environment 1'),
+ array('My environment 2', 'My environment 2'),
+ array('My environment 3', 'My environment 3'),
+ );
+ }
+
+ /**
+ * @dataProvider mixedKeysChoiceListAnswerProvider
+ */
+ public function testChoiceFromChoicelistWithMixedKeys($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);
+ }
+
+ public function mixedKeysChoiceListAnswerProvider()
+ {
+ return array(
+ array('0', '0'),
+ array('No environment', '0'),
+ array('1', '1'),
+ array('env_2', 'env_2'),
+ array(3, '3'),
+ array('My environment 1', '1'),
+ );
+ }
+
+ /**
+ * @dataProvider answerProvider
+ */
+ public function testSelectChoiceFromChoiceList($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);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage The provided answer is ambiguous. Value should be one of env_2 or env_3.
+ */
+ public function testAmbiguousChoiceFromChoicelist()
+ {
+ $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);
+ }
+
+ public function answerProvider()
+ {
+ return array(
+ array('env_1', 'env_1'),
+ array('env_2', 'env_2'),
+ array('env_3', 'env_3'),
+ array('My environment 1', 'env_1'),
+ );
+ }
+
+ public function testNoInteraction()
+ {
+ $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));
+ }
+
+ /**
+ * @requires function mb_strwidth
+ */
+ public function testChoiceOutputFormattingQuestionForUtf8Keys()
+ {
+ $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->getMock('\Symfony\Component\Console\Output\OutputInterface');
+ $output->method('getFormatter')->willReturn(new OutputFormatter());
+
+ $dialog = new QuestionHelper();
+ $dialog->setInputStream($this->getInputStream("\n"));
+ $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->createInputInterfaceMock(), $output, $question);
+ }
+
+ protected function getInputStream($input)
+ {
+ $stream = fopen('php://memory', 'r+', false);
+ fwrite($stream, $input);
+ rewind($stream);
+
+ return $stream;
+ }
+
+ protected function createOutputInterface()
+ {
+ return new StreamOutput(fopen('php://memory', 'r+', false));
+ }
+
+ protected function createInputInterfaceMock($interactive = true)
+ {
+ $mock = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $mock->expects($this->any())
+ ->method('isInteractive')
+ ->will($this->returnValue($interactive));
+
+ return $mock;
+ }
+
+ private function hasSttyAvailable()
+ {
+ exec('stty 2>&1', $output, $exitcode);
+
+ return $exitcode === 0;
+ }
+}
diff --git a/vendor/symfony/console/Tests/Helper/TableStyleTest.php b/vendor/symfony/console/Tests/Helper/TableStyleTest.php
new file mode 100644
index 00000000..587d8414
--- /dev/null
+++ b/vendor/symfony/console/Tests/Helper/TableStyleTest.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\Helper;
+
+use Symfony\Component\Console\Helper\TableStyle;
+
+class TableStyleTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).
+ */
+ public function testSetPadTypeWithInvalidType()
+ {
+ $style = new TableStyle();
+ $style->setPadType('TEST');
+ }
+}
diff --git a/vendor/symfony/console/Tests/Helper/TableTest.php b/vendor/symfony/console/Tests/Helper/TableTest.php
new file mode 100644
index 00000000..9ecb381a
--- /dev/null
+++ b/vendor/symfony/console/Tests/Helper/TableTest.php
@@ -0,0 +1,645 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Console\Tests\Helper;
+
+use Symfony\Component\Console\Helper\Table;
+use Symfony\Component\Console\Helper\TableStyle;
+use Symfony\Component\Console\Helper\TableSeparator;
+use Symfony\Component\Console\Helper\TableCell;
+use Symfony\Component\Console\Output\StreamOutput;
+
+class TableTest extends \PHPUnit_Framework_TestCase
+{
+ protected $stream;
+
+ protected function setUp()
+ {
+ $this->stream = fopen('php://memory', 'r+');
+ }
+
+ protected function tearDown()
+ {
+ fclose($this->stream);
+ $this->stream = null;
+ }
+
+ /**
+ * @dataProvider testRenderProvider
+ */
+ public function testRender($headers, $rows, $style, $expected)
+ {
+ $table = new Table($output = $this->getOutputStream());
+ $table
+ ->setHeaders($headers)
+ ->setRows($rows)
+ ->setStyle($style)
+ ;
+ $table->render();
+
+ $this->assertEquals($expected, $this->getOutputContent($output));
+ }
+
+ /**
+ * @dataProvider testRenderProvider
+ */
+ public function testRenderAddRows($headers, $rows, $style, $expected)
+ {
+ $table = new Table($output = $this->getOutputStream());
+ $table
+ ->setHeaders($headers)
+ ->addRows($rows)
+ ->setStyle($style)
+ ;
+ $table->render();
+
+ $this->assertEquals($expected, $this->getOutputContent($output));
+ }
+
+ /**
+ * @dataProvider testRenderProvider
+ */
+ public function testRenderAddRowsOneByOne($headers, $rows, $style, $expected)
+ {
+ $table = new Table($output = $this->getOutputStream());
+ $table
+ ->setHeaders($headers)
+ ->setStyle($style)
+ ;
+ foreach ($rows as $row) {
+ $table->addRow($row);
+ }
+ $table->render();
+
+ $this->assertEquals($expected, $this->getOutputContent($output));
+ }
+
+ public function testRenderProvider()
+ {
+ $books = array(
+ array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
+ array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'),
+ array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
+ array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
+ );
+
+ return array(
+ array(
+ array('ISBN', 'Title', 'Author'),
+ $books,
+ 'default',
+<<<TABLE
++---------------+--------------------------+------------------+
+| ISBN | Title | Author |
++---------------+--------------------------+------------------+
+| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
+| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
+| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
+| 80-902734-1-6 | And Then There Were None | Agatha Christie |
++---------------+--------------------------+------------------+
+
+TABLE
+ ),
+ array(
+ array('ISBN', 'Title', 'Author'),
+ $books,
+ 'compact',
+<<<TABLE
+ ISBN Title Author
+ 99921-58-10-7 Divine Comedy Dante Alighieri
+ 9971-5-0210-0 A Tale of Two Cities Charles Dickens
+ 960-425-059-0 The Lord of the Rings J. R. R. Tolkien
+ 80-902734-1-6 And Then There Were None Agatha Christie
+
+TABLE
+ ),
+ array(
+ array('ISBN', 'Title', 'Author'),
+ $books,
+ 'borderless',
+<<<TABLE
+ =============== ========================== ==================
+ ISBN Title Author
+ =============== ========================== ==================
+ 99921-58-10-7 Divine Comedy Dante Alighieri
+ 9971-5-0210-0 A Tale of Two Cities Charles Dickens
+ 960-425-059-0 The Lord of the Rings J. R. R. Tolkien
+ 80-902734-1-6 And Then There Were None Agatha Christie
+ =============== ========================== ==================
+
+TABLE
+ ),
+ array(
+ array('ISBN', 'Title'),
+ array(
+ array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
+ array('9971-5-0210-0'),
+ array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
+ array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
+ ),
+ 'default',
+<<<TABLE
++---------------+--------------------------+------------------+
+| ISBN | Title | |
++---------------+--------------------------+------------------+
+| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
+| 9971-5-0210-0 | | |
+| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
+| 80-902734-1-6 | And Then There Were None | Agatha Christie |
++---------------+--------------------------+------------------+
+
+TABLE
+ ),
+ array(
+ array(),
+ array(
+ array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
+ array('9971-5-0210-0'),
+ array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
+ array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
+ ),
+ 'default',
+<<<TABLE
++---------------+--------------------------+------------------+
+| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
+| 9971-5-0210-0 | | |
+| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
+| 80-902734-1-6 | And Then There Were None | Agatha Christie |
++---------------+--------------------------+------------------+
+
+TABLE
+ ),
+ array(
+ array('ISBN', 'Title', 'Author'),
+ array(
+ array('99921-58-10-7', "Divine\nComedy", 'Dante Alighieri'),
+ array('9971-5-0210-2', "Harry Potter\nand the Chamber of Secrets", "Rowling\nJoanne K."),
+ array('9971-5-0210-2', "Harry Potter\nand the Chamber of Secrets", "Rowling\nJoanne K."),
+ array('960-425-059-0', 'The Lord of the Rings', "J. R. R.\nTolkien"),
+ ),
+ 'default',
+<<<TABLE
++---------------+----------------------------+-----------------+
+| ISBN | Title | Author |
++---------------+----------------------------+-----------------+
+| 99921-58-10-7 | Divine | Dante Alighieri |
+| | Comedy | |
+| 9971-5-0210-2 | Harry Potter | Rowling |
+| | and the Chamber of Secrets | Joanne K. |
+| 9971-5-0210-2 | Harry Potter | Rowling |
+| | and the Chamber of Secrets | Joanne K. |
+| 960-425-059-0 | The Lord of the Rings | J. R. R. |
+| | | Tolkien |
++---------------+----------------------------+-----------------+
+
+TABLE
+ ),
+ array(
+ array('ISBN', 'Title'),
+ array(),
+ 'default',
+<<<TABLE
++------+-------+
+| ISBN | Title |
++------+-------+
+
+TABLE
+ ),
+ array(
+ array(),
+ array(),
+ 'default',
+ '',
+ ),
+ 'Cell text with tags used for Output styling' => array(
+ array('ISBN', 'Title', 'Author'),
+ array(
+ array('<info>99921-58-10-7</info>', '<error>Divine Comedy</error>', '<fg=blue;bg=white>Dante Alighieri</fg=blue;bg=white>'),
+ array('9971-5-0210-0', 'A Tale of Two Cities', '<info>Charles Dickens</>'),
+ ),
+ 'default',
+<<<TABLE
++---------------+----------------------+-----------------+
+| ISBN | Title | Author |
++---------------+----------------------+-----------------+
+| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
+| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
++---------------+----------------------+-----------------+
+
+TABLE
+ ),
+ 'Cell text with tags not used for Output styling' => array(
+ array('ISBN', 'Title', 'Author'),
+ array(
+ array('<strong>99921-58-10-700</strong>', '<f>Divine Com</f>', 'Dante Alighieri'),
+ array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'),
+ ),
+ 'default',
+<<<TABLE
++----------------------------------+----------------------+-----------------+
+| ISBN | Title | Author |
++----------------------------------+----------------------+-----------------+
+| <strong>99921-58-10-700</strong> | <f>Divine Com</f> | Dante Alighieri |
+| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
++----------------------------------+----------------------+-----------------+
+
+TABLE
+ ),
+ 'Cell with colspan' => array(
+ array('ISBN', 'Title', 'Author'),
+ array(
+ array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
+ new TableSeparator(),
+ array(new TableCell('Divine Comedy(Dante Alighieri)', array('colspan' => 3))),
+ new TableSeparator(),
+ array(
+ new TableCell('Arduino: A Quick-Start Guide', array('colspan' => 2)),
+ 'Mark Schmidt',
+ ),
+ new TableSeparator(),
+ array(
+ '9971-5-0210-0',
+ new TableCell("A Tale of \nTwo Cities", array('colspan' => 2)),
+ ),
+ new TableSeparator(),
+ array(
+ new TableCell('Cupiditate dicta atque porro, tempora exercitationem modi animi nulla nemo vel nihil!', array('colspan' => 3)),
+ ),
+ ),
+ 'default',
+<<<TABLE
++-------------------------------+-------------------------------+-----------------------------+
+| ISBN | Title | Author |
++-------------------------------+-------------------------------+-----------------------------+
+| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
++-------------------------------+-------------------------------+-----------------------------+
+| Divine Comedy(Dante Alighieri) |
++-------------------------------+-------------------------------+-----------------------------+
+| Arduino: A Quick-Start Guide | Mark Schmidt |
++-------------------------------+-------------------------------+-----------------------------+
+| 9971-5-0210-0 | A Tale of |
+| | Two Cities |
++-------------------------------+-------------------------------+-----------------------------+
+| Cupiditate dicta atque porro, tempora exercitationem modi animi nulla nemo vel nihil! |
++-------------------------------+-------------------------------+-----------------------------+
+
+TABLE
+ ),
+ 'Cell with rowspan' => array(
+ array('ISBN', 'Title', 'Author'),
+ array(
+ array(
+ new TableCell('9971-5-0210-0', array('rowspan' => 3)),
+ 'Divine Comedy',
+ 'Dante Alighieri',
+ ),
+ array('A Tale of Two Cities', 'Charles Dickens'),
+ array("The Lord of \nthe Rings", "J. R. \nR. Tolkien"),
+ new TableSeparator(),
+ array('80-902734-1-6', new TableCell("And Then \nThere \nWere None", array('rowspan' => 3)), 'Agatha Christie'),
+ array('80-902734-1-7', 'Test'),
+ ),
+ 'default',
+<<<TABLE
++---------------+----------------------+-----------------+
+| ISBN | Title | Author |
++---------------+----------------------+-----------------+
+| 9971-5-0210-0 | Divine Comedy | Dante Alighieri |
+| | A Tale of Two Cities | Charles Dickens |
+| | The Lord of | J. R. |
+| | the Rings | R. Tolkien |
++---------------+----------------------+-----------------+
+| 80-902734-1-6 | And Then | Agatha Christie |
+| 80-902734-1-7 | There | Test |
+| | Were None | |
++---------------+----------------------+-----------------+
+
+TABLE
+ ),
+ 'Cell with rowspan and colspan' => array(
+ array('ISBN', 'Title', 'Author'),
+ array(
+ array(
+ new TableCell('9971-5-0210-0', array('rowspan' => 2, 'colspan' => 2)),
+ 'Dante Alighieri',
+ ),
+ array('Charles Dickens'),
+ new TableSeparator(),
+ array(
+ 'Dante Alighieri',
+ new TableCell('9971-5-0210-0', array('rowspan' => 3, 'colspan' => 2)),
+ ),
+ array('J. R. R. Tolkien'),
+ array('J. R. R'),
+ ),
+ 'default',
+<<<TABLE
++------------------+---------+-----------------+
+| ISBN | Title | Author |
++------------------+---------+-----------------+
+| 9971-5-0210-0 | Dante Alighieri |
+| | Charles Dickens |
++------------------+---------+-----------------+
+| Dante Alighieri | 9971-5-0210-0 |
+| J. R. R. Tolkien | |
+| J. R. R | |
++------------------+---------+-----------------+
+
+TABLE
+ ),
+ 'Cell with rowspan and colspan contains new line break' => array(
+ array('ISBN', 'Title', 'Author'),
+ array(
+ array(
+ new TableCell("9971\n-5-\n021\n0-0", array('rowspan' => 2, 'colspan' => 2)),
+ 'Dante Alighieri',
+ ),
+ array('Charles Dickens'),
+ new TableSeparator(),
+ array(
+ 'Dante Alighieri',
+ new TableCell("9971\n-5-\n021\n0-0", array('rowspan' => 2, 'colspan' => 2)),
+ ),
+ array('Charles Dickens'),
+ new TableSeparator(),
+ array(
+ new TableCell("9971\n-5-\n021\n0-0", array('rowspan' => 2, 'colspan' => 2)),
+ new TableCell("Dante \nAlighieri", array('rowspan' => 2, 'colspan' => 1)),
+ ),
+ ),
+ 'default',
+<<<TABLE
++-----------------+-------+-----------------+
+| ISBN | Title | Author |
++-----------------+-------+-----------------+
+| 9971 | Dante Alighieri |
+| -5- | Charles Dickens |
+| 021 | |
+| 0-0 | |
++-----------------+-------+-----------------+
+| Dante Alighieri | 9971 |
+| Charles Dickens | -5- |
+| | 021 |
+| | 0-0 |
++-----------------+-------+-----------------+
+| 9971 | Dante |
+| -5- | Alighieri |
+| 021 | |
+| 0-0 | |
++-----------------+-------+-----------------+
+
+TABLE
+ ),
+ 'Cell with rowspan and colspan without using TableSeparator' => array(
+ array('ISBN', 'Title', 'Author'),
+ array(
+ array(
+ new TableCell("9971\n-5-\n021\n0-0", array('rowspan' => 2, 'colspan' => 2)),
+ 'Dante Alighieri',
+ ),
+ array('Charles Dickens'),
+ array(
+ 'Dante Alighieri',
+ new TableCell("9971\n-5-\n021\n0-0", array('rowspan' => 2, 'colspan' => 2)),
+ ),
+ array('Charles Dickens'),
+ ),
+ 'default',
+<<<TABLE
++-----------------+-------+-----------------+
+| ISBN | Title | Author |
++-----------------+-------+-----------------+
+| 9971 | Dante Alighieri |
+| -5- | Charles Dickens |
+| 021 | |
+| 0-0 | |
+| Dante Alighieri | 9971 |
+| Charles Dickens | -5- |
+| | 021 |
+| | 0-0 |
++-----------------+-------+-----------------+
+
+TABLE
+ ),
+ 'Cell with rowspan and colspan with separator inside a rowspan' => array(
+ array('ISBN', 'Author'),
+ array(
+ array(
+ new TableCell('9971-5-0210-0', array('rowspan' => 3, 'colspan' => 1)),
+ 'Dante Alighieri',
+ ),
+ array(new TableSeparator()),
+ array('Charles Dickens'),
+ ),
+ 'default',
+<<<TABLE
++---------------+-----------------+
+| ISBN | Author |
++---------------+-----------------+
+| 9971-5-0210-0 | Dante Alighieri |
+| |-----------------|
+| | Charles Dickens |
++---------------+-----------------+
+
+TABLE
+ ),
+ 'Multiple header lines' => array(
+ array(
+ array(new TableCell('Main title', array('colspan' => 3))),
+ array('ISBN', 'Title', 'Author'),
+ ),
+ array(),
+ 'default',
+<<<TABLE
++------+-------+--------+
+| Main title |
++------+-------+--------+
+| ISBN | Title | Author |
++------+-------+--------+
+
+TABLE
+ ),
+ 'Row with multiple cells' => array(
+ array(),
+ array(
+ array(
+ new TableCell('1', array('colspan' => 3)),
+ new TableCell('2', array('colspan' => 2)),
+ new TableCell('3', array('colspan' => 2)),
+ new TableCell('4', array('colspan' => 2)),
+ ),
+ ),
+ 'default',
+<<<TABLE
++---+--+--+---+--+---+--+---+--+
+| 1 | 2 | 3 | 4 |
++---+--+--+---+--+---+--+---+--+
+
+TABLE
+ ),
+ );
+ }
+
+ public function testRenderMultiByte()
+ {
+ $table = new Table($output = $this->getOutputStream());
+ $table
+ ->setHeaders(array('■■'))
+ ->setRows(array(array(1234)))
+ ->setStyle('default')
+ ;
+ $table->render();
+
+ $expected =
+<<<TABLE
++------+
+| ■■ |
++------+
+| 1234 |
++------+
+
+TABLE;
+
+ $this->assertEquals($expected, $this->getOutputContent($output));
+ }
+
+ public function testStyle()
+ {
+ $style = new TableStyle();
+ $style
+ ->setHorizontalBorderChar('.')
+ ->setVerticalBorderChar('.')
+ ->setCrossingChar('.')
+ ;
+
+ Table::setStyleDefinition('dotfull', $style);
+ $table = new Table($output = $this->getOutputStream());
+ $table
+ ->setHeaders(array('Foo'))
+ ->setRows(array(array('Bar')))
+ ->setStyle('dotfull');
+ $table->render();
+
+ $expected =
+<<<TABLE
+.......
+. Foo .
+.......
+. Bar .
+.......
+
+TABLE;
+
+ $this->assertEquals($expected, $this->getOutputContent($output));
+ }
+
+ public function testRowSeparator()
+ {
+ $table = new Table($output = $this->getOutputStream());
+ $table
+ ->setHeaders(array('Foo'))
+ ->setRows(array(
+ array('Bar1'),
+ new TableSeparator(),
+ array('Bar2'),
+ new TableSeparator(),
+ array('Bar3'),
+ ));
+ $table->render();
+
+ $expected =
+<<<TABLE
++------+
+| Foo |
++------+
+| Bar1 |
++------+
+| Bar2 |
++------+
+| Bar3 |
++------+
+
+TABLE;
+
+ $this->assertEquals($expected, $this->getOutputContent($output));
+
+ $this->assertEquals($table, $table->addRow(new TableSeparator()), 'fluent interface on addRow() with a single TableSeparator() works');
+ }
+
+ public function testRenderMultiCalls()
+ {
+ $table = new Table($output = $this->getOutputStream());
+ $table->setRows(array(
+ array(new TableCell('foo', array('colspan' => 2))),
+ ));
+ $table->render();
+ $table->render();
+ $table->render();
+
+ $expected =
+<<<TABLE
++----+---+
+| foo |
++----+---+
++----+---+
+| foo |
++----+---+
++----+---+
+| foo |
++----+---+
+
+TABLE;
+
+ $this->assertEquals($expected, $this->getOutputContent($output));
+ }
+
+ public function testColumnStyle()
+ {
+ $table = new Table($output = $this->getOutputStream());
+ $table
+ ->setHeaders(array('ISBN', 'Title', 'Author', 'Price'))
+ ->setRows(array(
+ array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri', '9.95'),
+ array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens', '139.25'),
+ ));
+
+ $style = new TableStyle();
+ $style->setPadType(STR_PAD_LEFT);
+ $table->setColumnStyle(3, $style);
+
+ $table->render();
+
+ $expected =
+ <<<TABLE
++---------------+----------------------+-----------------+--------+
+| ISBN | Title | Author | Price |
++---------------+----------------------+-----------------+--------+
+| 99921-58-10-7 | Divine Comedy | Dante Alighieri | 9.95 |
+| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | 139.25 |
++---------------+----------------------+-----------------+--------+
+
+TABLE;
+
+ $this->assertEquals($expected, $this->getOutputContent($output));
+ }
+
+ protected function getOutputStream()
+ {
+ return new StreamOutput($this->stream, StreamOutput::VERBOSITY_NORMAL, false);
+ }
+
+ protected function getOutputContent(StreamOutput $output)
+ {
+ rewind($output->getStream());
+
+ return str_replace(PHP_EOL, "\n", stream_get_contents($output->getStream()));
+ }
+}