This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
symfony/src/Symfony/Component/Console/Tests/ApplicationTest.php

1372 lines
59 KiB
PHP
Raw Normal View History

<?php
/*
2010-04-25 16:06:54 +01:00
* 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;
2017-02-08 07:24:27 +00:00
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\StreamOutput;
use Symfony\Component\Console\Tester\ApplicationTester;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
2016-01-18 16:12:22 +00:00
use Symfony\Component\Console\Event\ConsoleErrorEvent;
use Symfony\Component\Console\Event\ConsoleExceptionEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\Console\Exception\CommandNotFoundException;
use Symfony\Component\EventDispatcher\EventDispatcher;
2017-02-08 07:24:27 +00:00
class ApplicationTest extends TestCase
{
2012-07-09 13:50:58 +01:00
protected static $fixturesPath;
2012-07-09 13:50:58 +01:00
public static function setUpBeforeClass()
{
2010-06-28 08:31:54 +01:00
self::$fixturesPath = realpath(__DIR__.'/Fixtures/');
require_once self::$fixturesPath.'/FooCommand.php';
require_once self::$fixturesPath.'/Foo1Command.php';
require_once self::$fixturesPath.'/Foo2Command.php';
require_once self::$fixturesPath.'/Foo3Command.php';
2012-10-09 22:27:04 +01:00
require_once self::$fixturesPath.'/Foo4Command.php';
require_once self::$fixturesPath.'/Foo5Command.php';
2013-08-07 07:55:13 +01:00
require_once self::$fixturesPath.'/FoobarCommand.php';
require_once self::$fixturesPath.'/BarBucCommand.php';
2015-01-07 22:10:19 +00:00
require_once self::$fixturesPath.'/FooSubnamespaced1Command.php';
require_once self::$fixturesPath.'/FooSubnamespaced2Command.php';
}
protected function normalizeLineBreaks($text)
{
return str_replace(PHP_EOL, "\n", $text);
}
/**
* Replaces the dynamic placeholders of the command help text with a static version.
* The placeholder %command.full_name% includes the script path that is not predictable
* and can not be tested against.
*/
protected function ensureStaticCommandHelp(Application $application)
{
foreach ($application->all() as $command) {
$command->setHelp(str_replace('%command.full_name%', 'app/console %command.name%', $command->getHelp()));
}
}
public function testConstructor()
{
$application = new Application('foo', 'bar');
$this->assertEquals('foo', $application->getName(), '__construct() takes the application name as its first argument');
2013-06-27 00:04:51 +01:00
$this->assertEquals('bar', $application->getVersion(), '__construct() takes the application version as its second argument');
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
$this->assertEquals(array('help', 'list'), array_keys($application->all()), '__construct() registered the help and list commands by default');
}
public function testSetGetName()
{
$application = new Application();
$application->setName('foo');
$this->assertEquals('foo', $application->getName(), '->setName() sets the name of the application');
}
public function testSetGetVersion()
{
$application = new Application();
$application->setVersion('bar');
$this->assertEquals('bar', $application->getVersion(), '->setVersion() sets the version of the application');
}
public function testGetLongVersion()
{
$application = new Application('foo', 'bar');
$this->assertEquals('foo <info>bar</info>', $application->getLongVersion(), '->getLongVersion() returns the long version of the application');
}
public function testHelp()
{
$application = new Application();
$this->assertStringEqualsFile(self::$fixturesPath.'/application_gethelp.txt', $this->normalizeLineBreaks($application->getHelp()), '->getHelp() returns a help message');
}
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
public function testAll()
{
$application = new Application();
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
$commands = $application->all();
$this->assertInstanceOf('Symfony\\Component\\Console\\Command\\HelpCommand', $commands['help'], '->all() returns the registered commands');
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
$application->add(new \FooCommand());
$commands = $application->all('foo');
$this->assertCount(1, $commands, '->all() takes a namespace as its first argument');
}
public function testRegister()
{
$application = new Application();
$command = $application->register('foo');
$this->assertEquals('foo', $command->getName(), '->register() registers a new command');
}
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
public function testAdd()
{
$application = new Application();
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
$application->add($foo = new \FooCommand());
$commands = $application->all();
$this->assertEquals($foo, $commands['foo:bar'], '->add() registers a command');
$application = new Application();
$application->addCommands(array($foo = new \FooCommand(), $foo1 = new \Foo1Command()));
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
$commands = $application->all();
$this->assertEquals(array($foo, $foo1), array($commands['foo:bar'], $commands['foo:bar1']), '->addCommands() registers an array of commands');
}
/**
* @expectedException \LogicException
* @expectedExceptionMessage Command class "Foo5Command" is not correctly initialized. You probably forgot to call the parent constructor.
*/
2013-10-23 09:18:42 +01:00
public function testAddCommandWithEmptyConstructor()
{
$application = new Application();
$application->add(new \Foo5Command());
}
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
public function testHasGet()
{
$application = new Application();
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
$this->assertTrue($application->has('list'), '->has() returns true if a named command is registered');
$this->assertFalse($application->has('afoobar'), '->has() returns false if a named command is not registered');
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
$application->add($foo = new \FooCommand());
$this->assertTrue($application->has('afoobar'), '->has() returns true if an alias is registered');
$this->assertEquals($foo, $application->get('foo:bar'), '->get() returns a command by name');
$this->assertEquals($foo, $application->get('afoobar'), '->get() returns a command by alias');
$application = new Application();
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
$application->add($foo = new \FooCommand());
// simulate --help
$r = new \ReflectionObject($application);
$p = $r->getProperty('wantHelps');
$p->setAccessible(true);
$p->setValue($application, true);
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
$command = $application->get('foo:bar');
2013-02-05 21:55:33 +00:00
$this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $command, '->get() returns the help command if --help is provided as the input');
}
public function testSilentHelp()
{
$application = new Application();
$application->setAutoExit(false);
$application->setCatchExceptions(false);
$tester = new ApplicationTester($application);
$tester->run(array('-h' => true, '-q' => true), array('decorated' => false));
$this->assertEmpty($tester->getDisplay(true));
}
2013-02-05 21:55:33 +00:00
/**
2016-09-24 10:47:20 +01:00
* @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException
2013-02-05 21:55:33 +00:00
* @expectedExceptionMessage The command "foofoo" does not exist.
*/
public function testGetInvalidCommand()
{
$application = new Application();
$application->get('foofoo');
}
public function testGetNamespaces()
{
$application = new Application();
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
$application->add(new \FooCommand());
$application->add(new \Foo1Command());
$this->assertEquals(array('foo'), $application->getNamespaces(), '->getNamespaces() returns an array of unique used namespaces');
}
public function testFindNamespace()
{
$application = new Application();
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
$application->add(new \FooCommand());
$this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns the given namespace if it exists');
$this->assertEquals('foo', $application->findNamespace('f'), '->findNamespace() finds a namespace given an abbreviation');
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
$application->add(new \Foo2Command());
$this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns the given namespace if it exists');
2013-02-05 21:55:33 +00:00
}
2015-01-07 22:10:19 +00:00
public function testFindNamespaceWithSubnamespaces()
{
$application = new Application();
$application->add(new \FooSubnamespaced1Command());
$application->add(new \FooSubnamespaced2Command());
$this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns commands even if the commands are only contained in subnamespaces');
}
2013-02-05 21:55:33 +00:00
public function testFindAmbiguousNamespace()
{
$application = new Application();
$application->add(new \BarBucCommand());
2013-02-05 21:55:33 +00:00
$application->add(new \FooCommand());
$application->add(new \Foo2Command());
$expectedMsg = "The namespace \"f\" is ambiguous.\nDid you mean one of these?\n foo\n foo1";
if (method_exists($this, 'expectException')) {
$this->expectException(CommandNotFoundException::class);
$this->expectExceptionMessage($expectedMsg);
} else {
$this->setExpectedException(CommandNotFoundException::class, $expectedMsg);
}
2013-02-05 21:55:33 +00:00
$application->findNamespace('f');
}
/**
2016-09-24 10:47:20 +01:00
* @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException
2013-02-05 21:55:33 +00:00
* @expectedExceptionMessage There are no commands defined in the "bar" namespace.
*/
public function testFindInvalidNamespace()
{
$application = new Application();
$application->findNamespace('bar');
}
2013-08-07 07:55:13 +01:00
/**
2016-09-24 10:47:20 +01:00
* @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException
2013-08-07 07:55:13 +01:00
* @expectedExceptionMessage Command "foo1" is not defined
*/
public function testFindUniqueNameButNamespaceName()
{
$application = new Application();
$application->add(new \FooCommand());
$application->add(new \Foo1Command());
$application->add(new \Foo2Command());
$application->find($commandName = 'foo1');
}
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
public function testFind()
{
$application = new Application();
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
$application->add(new \FooCommand());
2013-02-05 21:55:33 +00:00
$this->assertInstanceOf('FooCommand', $application->find('foo:bar'), '->find() returns a command if its name exists');
$this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $application->find('h'), '->find() returns a command if its name exists');
$this->assertInstanceOf('FooCommand', $application->find('f:bar'), '->find() returns a command if the abbreviation for the namespace exists');
$this->assertInstanceOf('FooCommand', $application->find('f:b'), '->find() returns a command if the abbreviation for the namespace and the command name exist');
$this->assertInstanceOf('FooCommand', $application->find('a'), '->find() returns a command if the abbreviation exists for an alias');
}
/**
* @dataProvider provideAmbiguousAbbreviations
*/
public function testFindWithAmbiguousAbbreviations($abbreviation, $expectedExceptionMessage)
{
if (method_exists($this, 'expectException')) {
$this->expectException('Symfony\Component\Console\Exception\CommandNotFoundException');
$this->expectExceptionMessage($expectedExceptionMessage);
} else {
$this->setExpectedException('Symfony\Component\Console\Exception\CommandNotFoundException', $expectedExceptionMessage);
}
2013-02-05 21:55:33 +00:00
$application = new Application();
$application->add(new \FooCommand());
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
$application->add(new \Foo1Command());
$application->add(new \Foo2Command());
2013-02-05 21:55:33 +00:00
$application->find($abbreviation);
}
2013-02-05 21:55:33 +00:00
public function provideAmbiguousAbbreviations()
{
return array(
array('f', 'Command "f" is not defined.'),
array(
'a',
"Command \"a\" is ambiguous.\nDid you mean one of these?\n".
" afoobar The foo:bar command\n".
" afoobar1 The foo:bar1 command\n".
' afoobar2 The foo1:bar command',
),
array(
'foo:b',
"Command \"foo:b\" is ambiguous.\nDid you mean one of these?\n".
" foo:bar The foo:bar command\n".
" foo:bar1 The foo:bar1 command\n".
' foo1:bar The foo1:bar command',
),
2013-02-05 21:55:33 +00:00
);
}
public function testFindCommandEqualNamespace()
{
$application = new Application();
$application->add(new \Foo3Command());
$application->add(new \Foo4Command());
$this->assertInstanceOf('Foo3Command', $application->find('foo3:bar'), '->find() returns the good command even if a namespace has same name');
$this->assertInstanceOf('Foo4Command', $application->find('foo3:bar:toh'), '->find() returns a command even if its namespace equals another command name');
}
2013-08-07 07:55:13 +01:00
public function testFindCommandWithAmbiguousNamespacesButUniqueName()
{
$application = new Application();
$application->add(new \FooCommand());
$application->add(new \FoobarCommand());
$this->assertInstanceOf('FoobarCommand', $application->find('f:f'));
}
public function testFindCommandWithMissingNamespace()
{
$application = new Application();
$application->add(new \Foo4Command());
$this->assertInstanceOf('Foo4Command', $application->find('f::t'));
}
2013-02-05 21:55:33 +00:00
/**
* @dataProvider provideInvalidCommandNamesSingle
2016-09-24 10:47:20 +01:00
* @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException
2013-02-05 21:55:33 +00:00
* @expectedExceptionMessage Did you mean this
*/
public function testFindAlternativeExceptionMessageSingle($name)
{
$application = new Application();
2013-08-07 07:55:13 +01:00
$application->add(new \Foo3Command());
2013-02-05 21:55:33 +00:00
$application->find($name);
}
2013-02-05 21:55:33 +00:00
public function provideInvalidCommandNamesSingle()
{
return array(
2013-08-07 07:55:13 +01:00
array('foo3:baR'),
Merge branch '2.3' into 2.4 * 2.3: fixed CS [Process] fixed some volatile tests [HttpKernel] fixed a volatile test [HttpFoundation] fixed some volatile tests Use getPathname() instead of string casting to get BinaryFileReponse file path Conflicts: src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php src/Symfony/Component/ClassLoader/Tests/ApcUniversalClassLoaderTest.php src/Symfony/Component/Config/Definition/ReferenceDumper.php src/Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.php src/Symfony/Component/Console/Application.php src/Symfony/Component/Console/Tests/ApplicationTest.php src/Symfony/Component/Filesystem/Exception/IOException.php src/Symfony/Component/Form/Extension/Templating/TemplatingExtension.php src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php src/Symfony/Component/HttpKernel/Debug/TraceableEventDispatcher.php src/Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.php src/Symfony/Component/HttpKernel/Tests/Fragment/RoutableFragmentRendererTest.php src/Symfony/Component/HttpKernel/Tests/Profiler/Mock/RedisMock.php src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php src/Symfony/Component/PropertyAccess/PropertyAccessor.php src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorCollectionTest.php src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php src/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php src/Symfony/Component/Routing/Tests/Annotation/RouteTest.php src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php src/Symfony/Component/Serializer/Encoder/XmlEncoder.php src/Symfony/Component/Validator/Constraints/CollectionValidator.php src/Symfony/Component/Validator/Tests/ExecutionContextTest.php
2014-09-22 09:51:05 +01:00
array('foO3:bar'),
2013-02-05 21:55:33 +00:00
);
}
2013-02-05 21:55:33 +00:00
public function testFindAlternativeExceptionMessageMultiple()
{
$application = new Application();
$application->add(new \FooCommand());
$application->add(new \Foo1Command());
$application->add(new \Foo2Command());
// Command + plural
try {
$application->find('foo:baR');
$this->fail('->find() throws a CommandNotFoundException if command does not exist, with alternatives');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command does not exist, with alternatives');
$this->assertRegExp('/Did you mean one of these/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternatives');
2013-08-07 07:55:13 +01:00
$this->assertRegExp('/foo1:bar/', $e->getMessage());
$this->assertRegExp('/foo:bar/', $e->getMessage());
}
// Namespace + plural
try {
$application->find('foo2:bar');
$this->fail('->find() throws a CommandNotFoundException if command does not exist, with alternatives');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command does not exist, with alternatives');
$this->assertRegExp('/Did you mean one of these/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternatives');
2013-08-07 07:55:13 +01:00
$this->assertRegExp('/foo1/', $e->getMessage());
}
2012-10-09 22:27:04 +01:00
$application->add(new \Foo3Command());
$application->add(new \Foo4Command());
// Subnamespace + plural
try {
$a = $application->find('foo3:');
$this->fail('->find() should throw an Symfony\Component\Console\Exception\CommandNotFoundException if a command is ambiguous because of a subnamespace, with alternatives');
2012-10-09 22:27:04 +01:00
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e);
2012-10-09 22:27:04 +01:00
$this->assertRegExp('/foo3:bar/', $e->getMessage());
$this->assertRegExp('/foo3:bar:toh/', $e->getMessage());
}
}
public function testFindAlternativeCommands()
{
$application = new Application();
$application->add(new \FooCommand());
$application->add(new \Foo1Command());
$application->add(new \Foo2Command());
try {
2012-07-28 23:02:29 +01:00
$application->find($commandName = 'Unknown command');
$this->fail('->find() throws a CommandNotFoundException if command does not exist');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command does not exist');
$this->assertSame(array(), $e->getAlternatives());
$this->assertEquals(sprintf('Command "%s" is not defined.', $commandName), $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, without alternatives');
}
// Test if "bar1" command throw a "CommandNotFoundException" and does not contain
2013-08-07 07:55:13 +01:00
// "foo:bar" as alternative because "bar1" is too far from "foo:bar"
try {
2013-08-07 07:55:13 +01:00
$application->find($commandName = 'bar1');
$this->fail('->find() throws a CommandNotFoundException if command does not exist');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command does not exist');
$this->assertSame(array('afoobar1', 'foo:bar1'), $e->getAlternatives());
$this->assertRegExp(sprintf('/Command "%s" is not defined./', $commandName), $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternatives');
$this->assertRegExp('/afoobar1/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternative : "afoobar1"');
$this->assertRegExp('/foo:bar1/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternative : "foo:bar1"');
$this->assertNotRegExp('/foo:bar(?>!1)/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, without "foo:bar" alternative');
}
}
public function testFindAlternativeCommandsWithAnAlias()
{
$fooCommand = new \FooCommand();
$fooCommand->setAliases(array('foo2'));
$application = new Application();
$application->add($fooCommand);
$result = $application->find('foo');
$this->assertSame($fooCommand, $result);
}
public function testFindAlternativeNamespace()
{
$application = new Application();
$application->add(new \FooCommand());
$application->add(new \Foo1Command());
$application->add(new \Foo2Command());
$application->add(new \Foo3Command());
try {
2012-07-28 23:02:29 +01:00
$application->find('Unknown-namespace:Unknown-command');
$this->fail('->find() throws a CommandNotFoundException if namespace does not exist');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if namespace does not exist');
$this->assertSame(array(), $e->getAlternatives());
$this->assertEquals('There are no commands defined in the "Unknown-namespace" namespace.', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, without alternatives');
}
try {
$application->find('foo2:command');
$this->fail('->find() throws a CommandNotFoundException if namespace does not exist');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if namespace does not exist');
$this->assertCount(3, $e->getAlternatives());
$this->assertContains('foo', $e->getAlternatives());
$this->assertContains('foo1', $e->getAlternatives());
$this->assertContains('foo3', $e->getAlternatives());
$this->assertRegExp('/There are no commands defined in the "foo2" namespace./', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative');
$this->assertRegExp('/foo/', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative : "foo"');
$this->assertRegExp('/foo1/', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative : "foo1"');
$this->assertRegExp('/foo3/', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative : "foo3"');
}
}
public function testFindAlternativesOutput()
{
$application = new Application();
$application->add(new \FooCommand());
$application->add(new \Foo1Command());
$application->add(new \Foo2Command());
$application->add(new \Foo3Command());
$expectedAlternatives = array(
'afoobar',
'afoobar1',
'afoobar2',
'foo1:bar',
'foo3:bar',
'foo:bar',
'foo:bar1',
);
try {
$application->find('foo');
$this->fail('->find() throws a CommandNotFoundException if command is not defined');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command is not defined');
$this->assertSame($expectedAlternatives, $e->getAlternatives());
$this->assertRegExp('/Command "foo" is not defined\..*Did you mean one of these\?.*/Ums', $e->getMessage());
}
}
public function testFindNamespaceDoesNotFailOnDeepSimilarNamespaces()
{
2016-12-19 16:09:34 +00:00
$application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(array('getNamespaces'))->getMock();
$application->expects($this->once())
->method('getNamespaces')
->will($this->returnValue(array('foo:sublong', 'bar:sub')));
$this->assertEquals('foo:sublong', $application->findNamespace('f:sub'));
}
/**
2016-09-24 10:47:20 +01:00
* @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException
* @expectedExceptionMessage Command "foo::bar" is not defined.
*/
public function testFindWithDoubleColonInNameThrowsException()
{
$application = new Application();
$application->add(new \FooCommand());
$application->add(new \Foo4Command());
$application->find('foo::bar');
}
public function testSetCatchExceptions()
{
$application = new Application();
$application->setAutoExit(false);
putenv('COLUMNS=120');
$tester = new ApplicationTester($application);
$application->setCatchExceptions(true);
$this->assertTrue($application->areExceptionsCaught());
$tester->run(array('command' => 'foo'), array('decorated' => false));
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getDisplay(true), '->setCatchExceptions() sets the catch exception flag');
$tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true));
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getErrorOutput(true), '->setCatchExceptions() sets the catch exception flag');
$this->assertSame('', $tester->getDisplay(true));
$application->setCatchExceptions(false);
try {
$tester->run(array('command' => 'foo'), array('decorated' => false));
$this->fail('->setCatchExceptions() sets the catch exception flag');
} catch (\Exception $e) {
$this->assertInstanceOf('\Exception', $e, '->setCatchExceptions() sets the catch exception flag');
$this->assertEquals('Command "foo" is not defined.', $e->getMessage(), '->setCatchExceptions() sets the catch exception flag');
}
}
public function testAutoExitSetting()
{
$application = new Application();
$this->assertTrue($application->isAutoExitEnabled());
$application->setAutoExit(false);
$this->assertFalse($application->isAutoExitEnabled());
}
public function testRenderException()
{
$application = new Application();
$application->setAutoExit(false);
putenv('COLUMNS=120');
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true));
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exception');
$tester->run(array('command' => 'foo'), array('decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE, 'capture_stderr_separately' => true));
$this->assertContains('Exception trace', $tester->getErrorOutput(), '->renderException() renders a pretty exception with a stack trace when verbosity is verbose');
$tester->run(array('command' => 'list', '--foo' => true), array('decorated' => false, 'capture_stderr_separately' => true));
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception2.txt', $tester->getErrorOutput(true), '->renderException() renders the command synopsis when an exception occurs in the context of a command');
2014-02-11 07:51:18 +00:00
$application->add(new \Foo3Command());
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo3:bar'), array('decorated' => false, 'capture_stderr_separately' => true));
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions');
$tester->run(array('command' => 'foo3:bar'), array('decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE));
$this->assertRegExp('/\[Exception\]\s*First exception/', $tester->getDisplay(), '->renderException() renders a pretty exception without code exception when code exception is default and verbosity is verbose');
$this->assertRegExp('/\[Exception\]\s*Second exception/', $tester->getDisplay(), '->renderException() renders a pretty exception without code exception when code exception is 0 and verbosity is verbose');
$this->assertRegExp('/\[Exception \(404\)\]\s*Third exception/', $tester->getDisplay(), '->renderException() renders a pretty exception with code exception when code exception is 404 and verbosity is verbose');
$tester->run(array('command' => 'foo3:bar'), array('decorated' => true));
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3decorated.txt', $tester->getDisplay(true), '->renderException() renders a pretty exceptions with previous exceptions');
$tester->run(array('command' => 'foo3:bar'), array('decorated' => true, 'capture_stderr_separately' => true));
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3decorated.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions');
$application = new Application();
2012-04-06 13:21:18 +01:00
$application->setAutoExit(false);
putenv('COLUMNS=32');
2012-04-06 13:21:18 +01:00
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true));
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception4.txt', $tester->getErrorOutput(true), '->renderException() wraps messages when they are bigger than the terminal');
putenv('COLUMNS=120');
}
public function testRenderExceptionWithDoubleWidthCharacters()
{
$application = new Application();
$application->setAutoExit(false);
putenv('COLUMNS=120');
2014-05-13 09:47:23 +01:00
$application->register('foo')->setCode(function () {
throw new \Exception('エラーメッセージ');
});
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true));
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_doublewidth1.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions');
$tester->run(array('command' => 'foo'), array('decorated' => true, 'capture_stderr_separately' => true));
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_doublewidth1decorated.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions');
$application = new Application();
$application->setAutoExit(false);
putenv('COLUMNS=32');
2014-05-13 09:47:23 +01:00
$application->register('foo')->setCode(function () {
throw new \Exception('コマンドの実行中にエラーが発生しました。');
});
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true));
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_doublewidth2.txt', $tester->getErrorOutput(true), '->renderException() wraps messages when they are bigger than the terminal');
putenv('COLUMNS=120');
}
public function testRun()
{
$application = new Application();
$application->setAutoExit(false);
$application->setCatchExceptions(false);
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
$application->add($command = new \Foo1Command());
$_SERVER['argv'] = array('cli.php', 'foo:bar1');
ob_start();
$application->run();
ob_end_clean();
$this->assertInstanceOf('Symfony\Component\Console\Input\ArgvInput', $command->input, '->run() creates an ArgvInput by default if none is given');
$this->assertInstanceOf('Symfony\Component\Console\Output\ConsoleOutput', $command->output, '->run() creates a ConsoleOutput by default if none is given');
$application = new Application();
$application->setAutoExit(false);
$application->setCatchExceptions(false);
$this->ensureStaticCommandHelp($application);
$tester = new ApplicationTester($application);
$tester->run(array(), array('decorated' => false));
$this->assertStringEqualsFile(self::$fixturesPath.'/application_run1.txt', $tester->getDisplay(true), '->run() runs the list command if no argument is passed');
$tester->run(array('--help' => true), array('decorated' => false));
$this->assertStringEqualsFile(self::$fixturesPath.'/application_run2.txt', $tester->getDisplay(true), '->run() runs the help command if --help is passed');
$tester->run(array('-h' => true), array('decorated' => false));
$this->assertStringEqualsFile(self::$fixturesPath.'/application_run2.txt', $tester->getDisplay(true), '->run() runs the help command if -h is passed');
$tester->run(array('command' => 'list', '--help' => true), array('decorated' => false));
$this->assertStringEqualsFile(self::$fixturesPath.'/application_run3.txt', $tester->getDisplay(true), '->run() displays the help if --help is passed');
$tester->run(array('command' => 'list', '-h' => true), array('decorated' => false));
$this->assertStringEqualsFile(self::$fixturesPath.'/application_run3.txt', $tester->getDisplay(true), '->run() displays the help if -h is passed');
2010-07-01 19:19:54 +01:00
$tester->run(array('--ansi' => true));
$this->assertTrue($tester->getOutput()->isDecorated(), '->run() forces color output if --ansi is passed');
$tester->run(array('--no-ansi' => true));
$this->assertFalse($tester->getOutput()->isDecorated(), '->run() forces color output to be disabled if --no-ansi is passed');
$tester->run(array('--version' => true), array('decorated' => false));
$this->assertStringEqualsFile(self::$fixturesPath.'/application_run4.txt', $tester->getDisplay(true), '->run() displays the program version if --version is passed');
$tester->run(array('-V' => true), array('decorated' => false));
$this->assertStringEqualsFile(self::$fixturesPath.'/application_run4.txt', $tester->getDisplay(true), '->run() displays the program version if -v is passed');
$tester->run(array('command' => 'list', '--quiet' => true));
$this->assertSame('', $tester->getDisplay(), '->run() removes all output if --quiet is passed');
$this->assertFalse($tester->getInput()->isInteractive(), '->run() sets off the interactive mode if --quiet is passed');
$tester->run(array('command' => 'list', '-q' => true));
$this->assertSame('', $tester->getDisplay(), '->run() removes all output if -q is passed');
$this->assertFalse($tester->getInput()->isInteractive(), '->run() sets off the interactive mode if -q is passed');
$tester->run(array('command' => 'list', '--verbose' => true));
$this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if --verbose is passed');
2013-04-11 12:08:21 +01:00
$tester->run(array('command' => 'list', '--verbose' => 1));
2013-04-11 20:38:29 +01:00
$this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if --verbose=1 is passed');
2013-04-11 12:08:21 +01:00
$tester->run(array('command' => 'list', '--verbose' => 2));
$this->assertSame(Output::VERBOSITY_VERY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to very verbose if --verbose=2 is passed');
$tester->run(array('command' => 'list', '--verbose' => 3));
$this->assertSame(Output::VERBOSITY_DEBUG, $tester->getOutput()->getVerbosity(), '->run() sets the output to debug if --verbose=3 is passed');
$tester->run(array('command' => 'list', '--verbose' => 4));
$this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if unknown --verbose level is passed');
2013-04-11 12:08:21 +01:00
$tester->run(array('command' => 'list', '-v' => true));
$this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed');
$tester->run(array('command' => 'list', '-vv' => true));
$this->assertSame(Output::VERBOSITY_VERY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed');
$tester->run(array('command' => 'list', '-vvv' => true));
$this->assertSame(Output::VERBOSITY_DEBUG, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed');
$application = new Application();
$application->setAutoExit(false);
$application->setCatchExceptions(false);
made some method name changes to have a better coherence throughout the framework When an object has a "main" many relation with related "things" (objects, parameters, ...), the method names are normalized: * get() * set() * all() * replace() * remove() * clear() * isEmpty() * add() * register() * count() * keys() The classes below follow this method naming convention: * BrowserKit\CookieJar -> Cookie * BrowserKit\History -> Request * Console\Application -> Command * Console\Application\Helper\HelperSet -> HelperInterface * DependencyInjection\Container -> services * DependencyInjection\ContainerBuilder -> services * DependencyInjection\ParameterBag\ParameterBag -> parameters * DependencyInjection\ParameterBag\FrozenParameterBag -> parameters * DomCrawler\Form -> FormField * EventDispatcher\Event -> parameters * Form\FieldGroup -> Field * HttpFoundation\HeaderBag -> headers * HttpFoundation\ParameterBag -> parameters * HttpFoundation\Session -> attributes * HttpKernel\Profiler\Profiler -> DataCollectorInterface * Routing\RouteCollection -> Route * Security\Authentication\AuthenticationProviderManager -> AuthenticationProviderInterface * Templating\Engine -> HelperInterface * Translation\MessageCatalogue -> messages The usage of these methods are only allowed when it is clear that there is a main relation: * a CookieJar has many Cookies; * a Container has many services and many parameters (as services is the main relation, we use the naming convention for this relation); * a Console Input has many arguments and many options. There is no "main" relation, and so the naming convention does not apply. For many relations where the convention does not apply, the following methods must be used instead (where XXX is the name of the related thing): * get() -> getXXX() * set() -> setXXX() * all() -> getXXXs() * replace() -> setXXXs() * remove() -> removeXXX() * clear() -> clearXXX() * isEmpty() -> isEmptyXXX() * add() -> addXXX() * register() -> registerXXX() * count() -> countXXX() * keys()
2010-11-23 08:42:19 +00:00
$application->add(new \FooCommand());
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo:bar', '--no-interaction' => true), array('decorated' => false));
$this->assertSame('called'.PHP_EOL, $tester->getDisplay(), '->run() does not call interact() if --no-interaction is passed');
$tester->run(array('command' => 'foo:bar', '-n' => true), array('decorated' => false));
$this->assertSame('called'.PHP_EOL, $tester->getDisplay(), '->run() does not call interact() if -n is passed');
}
/**
* Issue #9285.
*
* If the "verbose" option is just before an argument in ArgvInput,
* an argument value should not be treated as verbosity value.
* This test will fail with "Not enough arguments." if broken
*/
public function testVerboseValueNotBreakArguments()
{
$application = new Application();
$application->setAutoExit(false);
$application->setCatchExceptions(false);
$application->add(new \FooCommand());
$output = new StreamOutput(fopen('php://memory', 'w', false));
$input = new ArgvInput(array('cli.php', '-v', 'foo:bar'));
$application->run($input, $output);
2017-03-18 09:10:35 +00:00
$this->addToAssertionCount(1);
$input = new ArgvInput(array('cli.php', '--verbose', 'foo:bar'));
$application->run($input, $output);
2017-03-18 09:10:35 +00:00
$this->addToAssertionCount(1);
}
public function testRunReturnsIntegerExitCode()
{
$exception = new \Exception('', 4);
2016-12-19 16:09:34 +00:00
$application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(array('doRun'))->getMock();
$application->setAutoExit(false);
$application->expects($this->once())
->method('doRun')
->will($this->throwException($exception));
$exitCode = $application->run(new ArrayInput(array()), new NullOutput());
$this->assertSame(4, $exitCode, '->run() returns integer exit code extracted from raised exception');
}
public function testRunReturnsExitCodeOneForExceptionCodeZero()
{
$exception = new \Exception('', 0);
2016-12-19 16:09:34 +00:00
$application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(array('doRun'))->getMock();
$application->setAutoExit(false);
$application->expects($this->once())
->method('doRun')
->will($this->throwException($exception));
$exitCode = $application->run(new ArrayInput(array()), new NullOutput());
$this->assertSame(1, $exitCode, '->run() returns exit code 1 when exception code is 0');
}
/**
* @expectedException \LogicException
* @expectedExceptionMessage An option with shortcut "e" already exists.
*/
public function testAddingOptionWithDuplicateShortcut()
{
$dispatcher = new EventDispatcher();
$application = new Application();
$application->setAutoExit(false);
$application->setCatchExceptions(false);
$application->setDispatcher($dispatcher);
$application->getDefinition()->addOption(new InputOption('--env', '-e', InputOption::VALUE_REQUIRED, 'Environment'));
$application
->register('foo')
2016-05-26 09:04:58 +01:00
->setAliases(array('f'))
->setDefinition(array(new InputOption('survey', 'e', InputOption::VALUE_REQUIRED, 'My option with a shortcut.')))
->setCode(function (InputInterface $input, OutputInterface $output) {})
;
$input = new ArrayInput(array('command' => 'foo'));
$output = new NullOutput();
$application->run($input, $output);
}
/**
* @expectedException \LogicException
* @dataProvider getAddingAlreadySetDefinitionElementData
*/
public function testAddingAlreadySetDefinitionElementData($def)
{
$application = new Application();
$application->setAutoExit(false);
$application->setCatchExceptions(false);
$application
->register('foo')
->setDefinition(array($def))
->setCode(function (InputInterface $input, OutputInterface $output) {})
;
$input = new ArrayInput(array('command' => 'foo'));
$output = new NullOutput();
$application->run($input, $output);
}
public function getAddingAlreadySetDefinitionElementData()
{
return array(
array(new InputArgument('command', InputArgument::REQUIRED)),
array(new InputOption('quiet', '', InputOption::VALUE_NONE)),
array(new InputOption('query', 'q', InputOption::VALUE_NONE)),
);
}
2012-10-04 07:44:49 +01:00
public function testGetDefaultHelperSetReturnsDefaultValues()
{
$application = new Application();
$application->setAutoExit(false);
$application->setCatchExceptions(false);
2012-10-04 07:44:49 +01:00
$helperSet = $application->getHelperSet();
2012-10-04 07:44:49 +01:00
$this->assertTrue($helperSet->has('formatter'));
}
2012-10-04 07:44:49 +01:00
public function testAddingSingleHelperSetOverwritesDefaultValues()
{
$application = new Application();
$application->setAutoExit(false);
$application->setCatchExceptions(false);
2012-10-04 07:44:49 +01:00
$application->setHelperSet(new HelperSet(array(new FormatterHelper())));
2012-10-04 07:44:49 +01:00
$helperSet = $application->getHelperSet();
2012-10-04 07:44:49 +01:00
$this->assertTrue($helperSet->has('formatter'));
2012-10-04 07:44:49 +01:00
// no other default helper set should be returned
$this->assertFalse($helperSet->has('dialog'));
$this->assertFalse($helperSet->has('progress'));
}
2012-10-04 07:44:49 +01:00
public function testOverwritingDefaultHelperSetOverwritesDefaultValues()
{
$application = new CustomApplication();
$application->setAutoExit(false);
$application->setCatchExceptions(false);
2012-10-04 07:44:49 +01:00
$application->setHelperSet(new HelperSet(array(new FormatterHelper())));
2012-10-04 07:44:49 +01:00
$helperSet = $application->getHelperSet();
2012-10-04 07:44:49 +01:00
$this->assertTrue($helperSet->has('formatter'));
2012-10-04 07:44:49 +01:00
// no other default helper set should be returned
$this->assertFalse($helperSet->has('dialog'));
$this->assertFalse($helperSet->has('progress'));
}
2012-10-04 07:44:49 +01:00
public function testGetDefaultInputDefinitionReturnsDefaultValues()
{
$application = new Application();
$application->setAutoExit(false);
$application->setCatchExceptions(false);
2012-10-04 07:44:49 +01:00
$inputDefinition = $application->getDefinition();
$this->assertTrue($inputDefinition->hasArgument('command'));
2012-10-04 07:44:49 +01:00
$this->assertTrue($inputDefinition->hasOption('help'));
$this->assertTrue($inputDefinition->hasOption('quiet'));
$this->assertTrue($inputDefinition->hasOption('verbose'));
$this->assertTrue($inputDefinition->hasOption('version'));
$this->assertTrue($inputDefinition->hasOption('ansi'));
$this->assertTrue($inputDefinition->hasOption('no-ansi'));
$this->assertTrue($inputDefinition->hasOption('no-interaction'));
}
2012-10-04 07:44:49 +01:00
public function testOverwritingDefaultInputDefinitionOverwritesDefaultValues()
{
$application = new CustomApplication();
$application->setAutoExit(false);
$application->setCatchExceptions(false);
2012-10-04 07:44:49 +01:00
$inputDefinition = $application->getDefinition();
2012-10-28 23:25:34 +00:00
// check whether the default arguments and options are not returned any more
$this->assertFalse($inputDefinition->hasArgument('command'));
2012-10-04 07:44:49 +01:00
$this->assertFalse($inputDefinition->hasOption('help'));
$this->assertFalse($inputDefinition->hasOption('quiet'));
$this->assertFalse($inputDefinition->hasOption('verbose'));
$this->assertFalse($inputDefinition->hasOption('version'));
$this->assertFalse($inputDefinition->hasOption('ansi'));
$this->assertFalse($inputDefinition->hasOption('no-ansi'));
$this->assertFalse($inputDefinition->hasOption('no-interaction'));
2012-10-04 07:44:49 +01:00
$this->assertTrue($inputDefinition->hasOption('custom'));
}
2012-12-11 10:49:22 +00:00
public function testSettingCustomInputDefinitionOverwritesDefaultValues()
{
$application = new Application();
$application->setAutoExit(false);
$application->setCatchExceptions(false);
2012-12-11 10:49:22 +00:00
$application->setDefinition(new InputDefinition(array(new InputOption('--custom', '-c', InputOption::VALUE_NONE, 'Set the custom input definition.'))));
2012-12-11 10:49:22 +00:00
$inputDefinition = $application->getDefinition();
2012-10-28 23:25:34 +00:00
// check whether the default arguments and options are not returned any more
$this->assertFalse($inputDefinition->hasArgument('command'));
$this->assertFalse($inputDefinition->hasOption('help'));
$this->assertFalse($inputDefinition->hasOption('quiet'));
$this->assertFalse($inputDefinition->hasOption('verbose'));
$this->assertFalse($inputDefinition->hasOption('version'));
$this->assertFalse($inputDefinition->hasOption('ansi'));
$this->assertFalse($inputDefinition->hasOption('no-ansi'));
$this->assertFalse($inputDefinition->hasOption('no-interaction'));
2012-10-04 07:44:49 +01:00
$this->assertTrue($inputDefinition->hasOption('custom'));
}
public function testRunWithDispatcher()
{
$application = new Application();
$application->setAutoExit(false);
$application->setDispatcher($this->getDispatcher());
$application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
$output->write('foo.');
});
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo'));
$this->assertEquals('before.foo.after.'.PHP_EOL, $tester->getDisplay());
}
/**
* @expectedException \LogicException
2016-01-18 16:12:22 +00:00
* @expectedExceptionMessage error
*/
public function testRunWithExceptionAndDispatcher()
{
$application = new Application();
$application->setDispatcher($this->getDispatcher());
$application->setAutoExit(false);
$application->setCatchExceptions(false);
$application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
throw new \RuntimeException('foo');
});
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo'));
}
public function testRunDispatchesAllEventsWithException()
{
$application = new Application();
$application->setDispatcher($this->getDispatcher());
$application->setAutoExit(false);
$application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
$output->write('foo.');
throw new \RuntimeException('foo');
});
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo'));
2016-01-18 16:12:22 +00:00
$this->assertContains('before.foo.error.after.', $tester->getDisplay());
}
public function testRunDispatchesAllEventsWithExceptionInListener()
{
$dispatcher = $this->getDispatcher();
$dispatcher->addListener('console.command', function () {
throw new \RuntimeException('foo');
});
$application = new Application();
$application->setDispatcher($dispatcher);
$application->setAutoExit(false);
$application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
$output->write('foo.');
});
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo'));
$this->assertContains('before.error.after.', $tester->getDisplay());
}
public function testRunAllowsErrorListenersToSilenceTheException()
{
$dispatcher = $this->getDispatcher();
$dispatcher->addListener('console.error', function (ConsoleErrorEvent $event) {
$event->getOutput()->write('silenced.');
$event->markErrorAsHandled();
});
$dispatcher->addListener('console.command', function () {
throw new \RuntimeException('foo');
});
$application = new Application();
$application->setDispatcher($dispatcher);
$application->setAutoExit(false);
$application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
$output->write('foo.');
});
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo'));
$this->assertContains('before.error.silenced.after.', $tester->getDisplay());
$this->assertEquals(0, $tester->getStatusCode());
}
2017-03-23 09:14:03 +00:00
/**
* @group legacy
* @expectedDeprecation The "console.exception" event is deprecated since version 3.3 and will be removed in 4.0. Use the "console.error" event instead.
*/
2016-01-18 16:12:22 +00:00
public function testLegacyExceptionListenersAreStillTriggered()
{
$dispatcher = $this->getDispatcher();
$dispatcher->addListener('console.exception', function (ConsoleExceptionEvent $event) {
$event->getOutput()->write('caught.');
$event->setException(new \RuntimeException('replaced in caught.'));
});
$application = new Application();
$application->setDispatcher($dispatcher);
$application->setAutoExit(false);
$application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
throw new \RuntimeException('foo');
});
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo'));
$this->assertContains('before.caught.error.after.', $tester->getDisplay());
$this->assertContains('replaced in caught.', $tester->getDisplay());
}
public function testRunWithError()
{
if (method_exists($this, 'expectException')) {
$this->expectException('Exception');
$this->expectExceptionMessage('dymerr');
} else {
$this->setExpectedException('Exception', 'dymerr');
}
$application = new Application();
$application->setAutoExit(false);
$application->setCatchExceptions(false);
$application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) {
$output->write('dym.');
throw new \Error('dymerr');
});
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'dym'));
}
/**
* @expectedException \LogicException
2016-01-18 16:12:22 +00:00
* @expectedExceptionMessage error
*/
public function testRunWithErrorAndDispatcher()
{
$application = new Application();
$application->setDispatcher($this->getDispatcher());
$application->setAutoExit(false);
$application->setCatchExceptions(false);
$application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) {
$output->write('dym.');
throw new \Error('dymerr');
});
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'dym'));
2016-01-18 16:12:22 +00:00
$this->assertContains('before.dym.error.after.', $tester->getDisplay(), 'The PHP Error did not dispached events');
}
public function testRunDispatchesAllEventsWithError()
{
$application = new Application();
$application->setDispatcher($this->getDispatcher());
$application->setAutoExit(false);
$application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) {
$output->write('dym.');
throw new \Error('dymerr');
});
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'dym'));
2016-01-18 16:12:22 +00:00
$this->assertContains('before.dym.error.after.', $tester->getDisplay(), 'The PHP Error did not dispached events');
}
public function testRunWithErrorFailingStatusCode()
{
$application = new Application();
$application->setDispatcher($this->getDispatcher());
$application->setAutoExit(false);
$application->register('dus')->setCode(function (InputInterface $input, OutputInterface $output) {
$output->write('dus.');
throw new \Error('duserr');
});
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'dus'));
$this->assertSame(1, $tester->getStatusCode(), 'Status code should be 1');
}
public function testRunWithDispatcherSkippingCommand()
{
$application = new Application();
$application->setDispatcher($this->getDispatcher(true));
$application->setAutoExit(false);
$application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
$output->write('foo.');
});
$tester = new ApplicationTester($application);
$exitCode = $tester->run(array('command' => 'foo'));
$this->assertContains('before.after.', $tester->getDisplay());
$this->assertEquals(ConsoleCommandEvent::RETURN_CODE_DISABLED, $exitCode);
}
public function testRunWithDispatcherAccessingInputOptions()
{
$noInteractionValue = null;
$quietValue = null;
$dispatcher = $this->getDispatcher();
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use (&$noInteractionValue, &$quietValue) {
$input = $event->getInput();
$noInteractionValue = $input->getOption('no-interaction');
$quietValue = $input->getOption('quiet');
});
$application = new Application();
$application->setDispatcher($dispatcher);
$application->setAutoExit(false);
$application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
$output->write('foo.');
});
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo', '--no-interaction' => true));
$this->assertTrue($noInteractionValue);
$this->assertFalse($quietValue);
}
public function testRunWithDispatcherAddingInputOptions()
{
$extraValue = null;
$dispatcher = $this->getDispatcher();
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use (&$extraValue) {
$definition = $event->getCommand()->getDefinition();
$input = $event->getInput();
$definition->addOption(new InputOption('extra', null, InputOption::VALUE_REQUIRED));
$input->bind($definition);
$extraValue = $input->getOption('extra');
});
$application = new Application();
$application->setDispatcher($dispatcher);
$application->setAutoExit(false);
$application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
$output->write('foo.');
});
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo', '--extra' => 'some test value'));
$this->assertEquals('some test value', $extraValue);
}
/**
* @group legacy
*/
public function testTerminalDimensions()
{
$application = new Application();
$originalDimensions = $application->getTerminalDimensions();
$this->assertCount(2, $originalDimensions);
$width = 80;
if ($originalDimensions[0] == $width) {
$width = 100;
}
$application->setTerminalDimensions($width, 80);
$this->assertSame(array($width, 80), $application->getTerminalDimensions());
}
public function testSetRunCustomDefaultCommand()
{
$command = new \FooCommand();
$application = new Application();
$application->setAutoExit(false);
$application->add($command);
$application->setDefaultCommand($command->getName());
$tester = new ApplicationTester($application);
$tester->run(array());
$this->assertEquals('interact called'.PHP_EOL.'called'.PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command');
$application = new CustomDefaultCommandApplication();
$application->setAutoExit(false);
$tester = new ApplicationTester($application);
$tester->run(array());
$this->assertEquals('interact called'.PHP_EOL.'called'.PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command');
}
2014-11-30 08:03:32 +00:00
public function testSetRunCustomSingleCommand()
{
$command = new \FooCommand();
$application = new Application();
$application->setAutoExit(false);
$application->add($command);
$application->setDefaultCommand($command->getName(), true);
$tester = new ApplicationTester($application);
$tester->run(array());
$this->assertContains('called', $tester->getDisplay());
$tester->run(array('--help' => true));
$this->assertContains('The foo:bar command', $tester->getDisplay());
}
/**
* @requires function posix_isatty
*/
2014-11-30 08:03:32 +00:00
public function testCanCheckIfTerminalIsInteractive()
{
$application = new CustomDefaultCommandApplication();
$application->setAutoExit(false);
$tester = new ApplicationTester($application);
$tester->run(array('command' => 'help'));
$this->assertFalse($tester->getInput()->hasParameterOption(array('--no-interaction', '-n')));
$inputStream = $tester->getInput()->getStream();
2014-11-30 08:03:32 +00:00
$this->assertEquals($tester->getInput()->isInteractive(), @posix_isatty($inputStream));
}
2016-01-18 16:12:22 +00:00
protected function getDispatcher($skipCommand = false)
{
$dispatcher = new EventDispatcher();
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use ($skipCommand) {
$event->getOutput()->write('before.');
if ($skipCommand) {
$event->disableCommand();
}
});
$dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use ($skipCommand) {
$event->getOutput()->writeln('after.');
if (!$skipCommand) {
$event->setExitCode(113);
}
});
$dispatcher->addListener('console.error', function (ConsoleErrorEvent $event) {
$event->getOutput()->write('error.');
$event->setError(new \LogicException('error.', $event->getExitCode(), $event->getError()));
});
return $dispatcher;
}
}
class CustomApplication extends Application
{
/**
* Overwrites the default input definition.
*
* @return InputDefinition An InputDefinition instance
*/
protected function getDefaultInputDefinition()
{
return new InputDefinition(array(new InputOption('--custom', '-c', InputOption::VALUE_NONE, 'Set the custom input definition.')));
}
2012-10-04 07:44:49 +01:00
/**
* Gets the default helper set with the helpers that should always be available.
*
* @return HelperSet A HelperSet instance
*/
protected function getDefaultHelperSet()
{
return new HelperSet(array(new FormatterHelper()));
}
}
class CustomDefaultCommandApplication extends Application
{
/**
* Overwrites the constructor in order to set a different default command.
*/
public function __construct()
{
parent::__construct();
$command = new \FooCommand();
$this->add($command);
$this->setDefaultCommand($command->getName());
}
}