Update Composer, update everything

This commit is contained in:
Oliver Davies 2018-11-23 12:29:20 +00:00
parent ea3e94409f
commit dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions

View file

@ -0,0 +1,69 @@
<?php
namespace Stecman\Component\Symfony\Console\BashCompletion\Tests\Common;
use PHPUnit\Framework\TestCase;
use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
use Stecman\Component\Symfony\Console\BashCompletion\CompletionHandler;
use Symfony\Component\Console\Application;
/**
* Base test case for running CompletionHandlers
*/
abstract class CompletionHandlerTestCase extends TestCase
{
/**
* @var Application
*/
protected $application;
public static function setUpBeforeClass()
{
require_once __DIR__ . '/../Fixtures/CompletionAwareCommand.php';
require_once __DIR__ . '/../Fixtures/HiddenCommand.php';
require_once __DIR__ . '/../Fixtures/TestBasicCommand.php';
require_once __DIR__ . '/../Fixtures/TestSymfonyStyleCommand.php';
}
protected function setUp()
{
$this->application = new Application('Base application');
$this->application->addCommands(array(
new \CompletionAwareCommand(),
new \TestBasicCommand(),
new \TestSymfonyStyleCommand()
));
if (method_exists('\HiddenCommand', 'setHidden')) {
$this->application->add(new \HiddenCommand());
}
}
/**
* Create a handler set up with the given commandline and cursor position
*
* @param $commandLine
* @param int $cursorIndex
* @return CompletionHandler
*/
protected function createHandler($commandLine, $cursorIndex = null)
{
$context = new CompletionContext();
$context->setCommandLine($commandLine);
$context->setCharIndex($cursorIndex === null ? strlen($commandLine) : $cursorIndex);
return new CompletionHandler($this->application, $context);
}
/**
* Get the list of terms from the output of CompletionHandler
* The array index needs to be reset so that PHPUnit's array equality assertions match correctly.
*
* @param string $handlerOutput
* @return string[]
*/
protected function getTerms($handlerOutput)
{
return array_values($handlerOutput);
}
}

View file

@ -0,0 +1,113 @@
<?php
namespace Stecman\Component\Symfony\Console\BashCompletion\Tests;
use PHPUnit\Framework\TestCase;
use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
use Stecman\Component\Symfony\Console\BashCompletion\EnvironmentCompletionContext;
class CompletionContextTest extends TestCase
{
public function testWordBreakSplit()
{
$context = new CompletionContext();
$context->setCommandLine('console config:application --direction="west" --with-bruce --repeat 3');
// Cursor at the end of the first word
$context->setCharIndex(7);
$words = $context->getWords();
$this->assertEquals(array(
'console',
'config:application',
'--direction',
'west',
'--with-bruce',
'--repeat',
'3'
), $words);
}
public function testCursorPosition()
{
$context = new CompletionContext();
$context->setCommandLine('make horse --legs 4 --colour black ');
// Cursor at the start of the line
$context->setCharIndex(0);
$this->assertEquals(0, $context->getWordIndex());
// Cursor at the end of the line
$context->setCharIndex(34);
$this->assertEquals(5, $context->getWordIndex());
$this->assertEquals('black', $context->getCurrentWord());
// Cursor after space at the end of the string
$context->setCharIndex(35);
$this->assertEquals(6, $context->getWordIndex());
$this->assertEquals('', $context->getCurrentWord());
// Cursor in the middle of 'horse'
$context->setCharIndex(8);
$this->assertEquals(1, $context->getWordIndex());
$this->assertEquals('hor', $context->getCurrentWord());
// Cursor at the end of '--legs'
$context->setCharIndex(17);
$this->assertEquals(2, $context->getWordIndex());
$this->assertEquals('--legs', $context->getCurrentWord());
}
public function testWordBreakingWithSmallInputs()
{
$context = new CompletionContext();
// Cursor at the end of a word and not in the following space has no effect
$context->setCommandLine('cmd a');
$context->setCharIndex(5);
$this->assertEquals(array('cmd', 'a'), $context->getWords());
$this->assertEquals(1, $context->getWordIndex());
$this->assertEquals('a', $context->getCurrentWord());
// As above, but in the middle of the command line string
$context->setCommandLine('cmd a');
$context->setCharIndex(3);
$this->assertEquals(array('cmd', 'a'), $context->getWords());
$this->assertEquals(0, $context->getWordIndex());
$this->assertEquals('cmd', $context->getCurrentWord());
// Cursor at the end of the command line with a space appends an empty word
$context->setCommandLine('cmd a ');
$context->setCharIndex(8);
$this->assertEquals(array('cmd', 'a', ''), $context->getWords());
$this->assertEquals(2, $context->getWordIndex());
$this->assertEquals('', $context->getCurrentWord());
// Cursor in break space before a word appends an empty word in that position
$context->setCommandLine('cmd a');
$context->setCharIndex(4);
$this->assertEquals(array('cmd', '', 'a',), $context->getWords());
$this->assertEquals(1, $context->getWordIndex());
$this->assertEquals('', $context->getCurrentWord());
}
public function testConfigureFromEnvironment()
{
putenv("CMDLINE_CONTENTS=beam up li");
putenv('CMDLINE_CURSOR_INDEX=10');
$context = new EnvironmentCompletionContext();
$this->assertEquals(
array(
'beam',
'up',
'li'
),
$context->getWords()
);
$this->assertEquals('li', $context->getCurrentWord());
}
}

View file

@ -0,0 +1,166 @@
<?php
namespace Stecman\Component\Symfony\Console\BashCompletion\Tests;
require_once __DIR__ . '/Common/CompletionHandlerTestCase.php';
use Stecman\Component\Symfony\Console\BashCompletion\Completion;
use Stecman\Component\Symfony\Console\BashCompletion\Tests\Common\CompletionHandlerTestCase;
class CompletionHandlerTest extends CompletionHandlerTestCase
{
public function testCompleteAppName()
{
$handler = $this->createHandler('app');
// It's not valid to complete the application name, so this should return nothing
$this->assertEmpty($handler->runCompletion());
}
public function testCompleteCommandNames()
{
$handler = $this->createHandler('app ');
$this->assertEquals(
array('help', 'list', 'completion-aware', 'wave', 'walk:north'),
$this->getTerms($handler->runCompletion())
);
}
public function testCompleteCommandNameNonMatch()
{
$handler = $this->createHandler('app br');
$this->assertEmpty($handler->runCompletion());
}
public function testCompleteCommandNamePartialTwoMatches()
{
$handler = $this->createHandler('app wa');
$this->assertEquals(array('wave', 'walk:north'), $this->getTerms($handler->runCompletion()));
}
public function testCompleteCommandNamePartialOneMatch()
{
$handler = $this->createHandler('app wav');
$this->assertEquals(array('wave'), $this->getTerms($handler->runCompletion()));
}
public function testCompleteCommandNameFull()
{
$handler = $this->createHandler('app wave');
// Completing on a matching word should return that word so that completion can continue
$this->assertEquals(array('wave'), $this->getTerms($handler->runCompletion()));
}
public function testCompleteSingleDash()
{
$handler = $this->createHandler('app wave -');
// Short options are not given as suggestions
$this->assertEmpty($handler->runCompletion());
}
public function testCompleteOptionShortcut()
{
$handler = $this->createHandler('app wave -j');
// If a valid option shortcut is completed on, the shortcut is returned so that completion can continue
$this->assertEquals(array('-j'), $this->getTerms($handler->runCompletion()));
}
public function testCompleteDoubleDash()
{
$handler = $this->createHandler('app wave --');
$this->assertArraySubset(array('--vigorous', '--jazz-hands'), $this->getTerms($handler->runCompletion()));
}
public function testCompleteOptionFull()
{
$handler = $this->createHandler('app wave --jazz');
$this->assertArraySubset(array('--jazz-hands'), $this->getTerms($handler->runCompletion()));
}
public function testCompleteOptionOrder()
{
// Completion of options should be able to happen anywhere after the command name
$handler = $this->createHandler('app wave bruce --vi');
$this->assertEquals(array('--vigorous'), $this->getTerms($handler->runCompletion()));
// Completing an option mid-commandline should work as normal
$handler = $this->createHandler('app wave --vi --jazz-hands bruce', 13);
$this->assertEquals(array('--vigorous'), $this->getTerms($handler->runCompletion()));
}
public function testCompleteColonCommand()
{
// Normal bash behaviour is to count the colon character as a word break
// Since a colon is used to namespace Symfony Framework console commands the
// character in a command name should not be taken as a word break
//
// @see https://github.com/stecman/symfony-console-completion/pull/1
$handler = $this->createHandler('app walk');
$this->assertEquals(array('walk:north'), $this->getTerms($handler->runCompletion()));
$handler = $this->createHandler('app walk:north');
$this->assertEquals(array('walk:north'), $this->getTerms($handler->runCompletion()));
$handler = $this->createHandler('app walk:north --deploy');
$this->assertEquals(array('--deploy:jazz-hands'), $this->getTerms($handler->runCompletion()));
}
/**
* @dataProvider completionAwareCommandDataProvider
*/
public function testCompletionAwareCommand($commandLine, array $suggestions)
{
$handler = $this->createHandler($commandLine);
$this->assertSame($suggestions, $this->getTerms($handler->runCompletion()));
}
public function completionAwareCommandDataProvider()
{
return array(
'not complete aware command' => array('app wave --vigorous ', array()),
'argument suggestions' => array('app completion-aware any-arg ', array('one-arg', 'two-arg')),
'argument no suggestions' => array('app completion-aware ', array()),
'argument suggestions + context' => array('app completion-aware any-arg one', array('one-arg', 'one-arg-context')),
'array argument suggestions' => array('app completion-aware any-arg one-arg array-arg1 ', array('one-arg', 'two-arg')),
'array argument suggestions + context' => array('app completion-aware any-arg one-arg array-arg1 one', array('one-arg', 'one-arg-context')),
'option suggestions' => array('app completion-aware --option-with-suggestions ', array('one-opt', 'two-opt')),
'option no suggestions' => array('app completion-aware --option-without-suggestions ', array()),
'option suggestions + context' => array(
'app completion-aware --option-with-suggestions one', array('one-opt', 'one-opt-context')
),
);
}
public function testShortCommandMatched()
{
$handler = $this->createHandler('app w:n --deploy');
$this->assertEquals(array('--deploy:jazz-hands'), $this->getTerms($handler->runCompletion()));
}
public function testShortCommandNotMatched()
{
$handler = $this->createHandler('app w --deploy');
$this->assertEquals(array(), $this->getTerms($handler->runCompletion()));
}
public function testHelpCommandCompletion()
{
$handler = $this->createHandler('app help ');
$this->assertEquals(
array('help', 'list', 'completion-aware', 'wave', 'walk:north'),
$this->getTerms($handler->runCompletion())
);
}
public function testListCommandCompletion()
{
$handler = $this->createHandler('app list ');
$this->assertEquals(
array('walk'),
$this->getTerms($handler->runCompletion())
);
}
}

View file

@ -0,0 +1,153 @@
<?php
namespace Stecman\Component\Symfony\Console\BashCompletion\Tests;
require_once __DIR__ . '/Common/CompletionHandlerTestCase.php';
use Stecman\Component\Symfony\Console\BashCompletion\Completion;
use Stecman\Component\Symfony\Console\BashCompletion\Tests\Common\CompletionHandlerTestCase;
class CompletionTest extends CompletionHandlerTestCase
{
/**
* @dataProvider getCompletionTestInput
*/
public function testCompletionResults($completions, $commandlineResultMap)
{
if (!is_array($completions)) {
$completions = array($completions);
}
foreach ($commandlineResultMap as $commandLine => $result) {
$handler = $this->createHandler($commandLine);
$handler->addHandlers($completions);
$this->assertEquals($result, $this->getTerms($handler->runCompletion()));
}
}
public function getCompletionTestInput()
{
$options = array('smooth', 'latin', 'moody');
return array(
'command match' => array(
new Completion(
'wave',
'target',
Completion::ALL_TYPES,
$options
),
array(
'app walk:north --target ' => array(),
'app wave ' => $options
)
),
'type restriction option' => array(
new Completion(
Completion::ALL_COMMANDS,
'target',
Completion::TYPE_OPTION,
$options
),
array(
'app walk:north --target ' => $options,
'app wave ' => array()
)
),
'type restriction argument' => array(
new Completion(
Completion::ALL_COMMANDS,
'target',
Completion::TYPE_ARGUMENT,
$options
),
array(
'app walk:north --target ' => array(),
'app wave ' => $options
)
),
'makeGlobalHandler static' => array(
Completion::makeGlobalHandler(
'target',
Completion::ALL_TYPES,
$options
),
array(
'app walk:north --target ' => $options,
'app wave ' => $options
)
),
'with anonymous function' => array(
new Completion(
'wave',
'style',
Completion::TYPE_OPTION,
function() {
return range(1, 5);
}
),
array(
'app walk:north --target ' => array(),
'app wave ' => array(),
'app wave --style ' => array(1, 2,3, 4, 5)
)
),
'with callable array' => array(
new Completion(
Completion::ALL_COMMANDS,
'target',
Completion::ALL_TYPES,
array($this, 'instanceMethodForCallableCheck')
),
array(
'app walk:north --target ' => array('hello', 'world'),
'app wave ' => array('hello', 'world')
)
),
'multiple handlers' => array(
array(
new Completion(
Completion::ALL_COMMANDS,
'target',
Completion::TYPE_OPTION,
array('all:option:target')
),
new Completion(
Completion::ALL_COMMANDS,
'target',
Completion::ALL_TYPES,
array('all:all:target')
),
new Completion(
Completion::ALL_COMMANDS,
'style',
Completion::TYPE_OPTION,
array('all:option:style')
),
),
array(
'app walk:north ' => array(),
'app walk:north -t ' => array('all:option:target'),
'app wave ' => array('all:all:target'),
'app wave bruce -s ' => array('all:option:style'),
'app walk:north --style ' => array('all:option:style'),
)
)
);
}
/**
* Used in the test "with callable array"
* @return array
*/
public function instanceMethodForCallableCheck()
{
return array('hello', 'world');
}
}

View file

@ -0,0 +1,69 @@
<?php
use Stecman\Component\Symfony\Console\BashCompletion\Completion\CompletionAwareInterface;
use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
class CompletionAwareCommand extends Command implements CompletionAwareInterface
{
protected function configure()
{
$this->setName('completion-aware')
->addOption('option-with-suggestions', null, InputOption::VALUE_REQUIRED)
->addOption('option-without-suggestions', null, InputOption::VALUE_REQUIRED)
->addArgument('argument-without-suggestions')
->addArgument('argument-with-suggestions')
->addArgument('array-argument-with-suggestions', InputArgument::IS_ARRAY)
;
}
/**
* Returns possible option values.
*
* @param string $optionName Option name.
* @param CompletionContext $context Completion context.
*
* @return array
*/
public function completeOptionValues($optionName, CompletionContext $context)
{
if ($optionName === 'option-with-suggestions') {
$suggestions = array('one-opt', 'two-opt');
if ('one' === $context->getCurrentWord()) {
$suggestions[] = 'one-opt-context';
}
return $suggestions;
}
return array();
}
/**
* Returns possible argument values.
*
* @param string $argumentName Argument name.
* @param CompletionContext $context Completion context.
*
* @return array
*/
public function completeArgumentValues($argumentName, CompletionContext $context)
{
if (in_array($argumentName, array('argument-with-suggestions', 'array-argument-with-suggestions'))) {
$suggestions = array('one-arg', 'two-arg');
if ('one' === $context->getCurrentWord()) {
$suggestions[] = 'one-arg-context';
}
return $suggestions;
}
return array();
}
}

View file

@ -0,0 +1,11 @@
<?php
class HiddenCommand extends \Symfony\Component\Console\Command\Command
{
protected function configure()
{
$this->setName('internals')
->setHidden(true);
}
}

View file

@ -0,0 +1,26 @@
<?php
class TestBasicCommand extends \Symfony\Component\Console\Command\Command
{
protected function configure()
{
$this->setName('wave')
->addOption(
'vigorous'
)
->addOption(
'jazz-hands',
'j'
)
->addOption(
'style',
's',
\Symfony\Component\Console\Input\InputOption::VALUE_REQUIRED
)
->addArgument(
'target',
\Symfony\Component\Console\Input\InputArgument::REQUIRED
);
}
}

View file

@ -0,0 +1,27 @@
<?php
class TestSymfonyStyleCommand extends \Symfony\Component\Console\Command\Command
{
protected function configure()
{
$this->setName('walk:north')
->addOption(
'power',
'p'
)
->addOption(
'deploy:jazz-hands',
'j'
)
->addOption(
'style',
's',
\Symfony\Component\Console\Input\InputOption::VALUE_REQUIRED
)
->addOption(
'target',
't',
\Symfony\Component\Console\Input\InputOption::VALUE_REQUIRED
);
}
}

View file

@ -0,0 +1,100 @@
<?php
namespace Stecman\Component\Symfony\Console\BashCompletion\Tests;
use PHPUnit\Framework\TestCase;
use Stecman\Component\Symfony\Console\BashCompletion\HookFactory;
class HookFactoryTest extends TestCase
{
/**
* @var HookFactory
*/
protected $factory;
protected function setUp()
{
$this->factory = new HookFactory();
}
/**
* @dataProvider generateHookDataProvider
*/
public function testBashSyntax($programPath, $programName, $multiple)
{
if ($this->hasProgram('bash')) {
$script = $this->factory->generateHook('bash', $programPath, $programName, $multiple);
$this->assertSyntaxIsValid($script, 'bash -n', 'BASH hook');
} else {
$this->markTestSkipped("Couldn't detect BASH program to run hook syntax check");
}
}
/**
* @dataProvider generateHookDataProvider
*/
public function testZshSyntax($programPath, $programName, $multiple)
{
if ($this->hasProgram('zsh')) {
$script = $this->factory->generateHook('zsh', $programPath, $programName, $multiple);
$this->assertSyntaxIsValid($script, 'zsh -n', 'ZSH hook');
} else {
$this->markTestSkipped("Couldn't detect ZSH program to run hook syntax check");
}
}
public function generateHookDataProvider()
{
return array(
array('/path/to/myprogram', null, false),
array('/path/to/myprogram', null, true),
array('/path/to/myprogram', 'myprogram', false),
array('/path/to/myprogram', 'myprogram', true),
array('/path/to/my-program', 'my-program', false)
);
}
protected function hasProgram($programName)
{
exec(sprintf(
'command -v %s',
escapeshellarg($programName)
), $output, $return);
return $return === 0;
}
/**
* @param string $code - code to pipe to the syntax checking command
* @param string $syntaxCheckCommand - equivalent to `bash -n`.
* @param string $context - what the syntax check is for
*/
protected function assertSyntaxIsValid($code, $syntaxCheckCommand, $context)
{
$process = proc_open(
escapeshellcmd($syntaxCheckCommand),
array(
0 => array('pipe', 'r'),
1 => array('pipe', 'w'),
2 => array('pipe', 'w')
),
$pipes
);
if (is_resource($process)) {
// Push code into STDIN for the syntax checking process
fwrite($pipes[0], $code);
fclose($pipes[0]);
$output = stream_get_contents($pipes[1]) . stream_get_contents($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
$status = proc_close($process);
$this->assertSame(0, $status, "Syntax check for $context failed:\n$output");
} else {
throw new \RuntimeException("Failed to start process with command '$syntaxCheckCommand'");
}
}
}

View file

@ -0,0 +1,10 @@
<?php
$filename = __DIR__ . '/../vendor/autoload.php';
if (!file_exists($filename)) {
echo 'You must first install the vendors using composer.' . PHP_EOL;
exit(1);
}
require_once $filename;