setDefinition([
new InputArgument('suite', InputArgument::REQUIRED, 'suite to be executed'),
new InputOption('colors', '', InputOption::VALUE_NONE, 'Use colors in output'),
]);
parent::configure();
}
public function getDescription()
{
return 'Launches interactive test console';
}
public function execute(InputInterface $input, OutputInterface $output)
{
$suiteName = $input->getArgument('suite');
$this->output = $output;
$config = Configuration::config();
$settings = Configuration::suiteSettings($suiteName, $config);
$options = $input->getOptions();
$options['debug'] = true;
$options['silent'] = true;
$options['interactive'] = false;
$options['colors'] = true;
Debug::setOutput(new Output($options));
$this->codecept = new Codecept($options);
$dispatcher = $this->codecept->getDispatcher();
$suiteManager = new SuiteManager($dispatcher, $suiteName, $settings);
$suiteManager->initialize();
$this->suite = $suiteManager->getSuite();
$moduleContainer = $suiteManager->getModuleContainer();
$this->actions = array_keys($moduleContainer->getActions());
$this->test = new Cept(null, null);
$this->test->getMetadata()->setServices([
'dispatcher' => $dispatcher,
'modules' => $moduleContainer
]);
$scenario = new Scenario($this->test);
if (!$settings['actor']) {
throw new ConfigurationException("Interactive shell can't be started without an actor");
}
if (isset($config["namespace"])) {
$settings['actor'] = $config["namespace"] .'\\' . $settings['actor'];
}
$actor = $settings['actor'];
$I = new $actor($scenario);
$this->listenToSignals();
$output->writeln("Interactive console started for suite $suiteName");
$output->writeln("Try Codeception commands without writing a test");
$output->writeln("type 'exit' to leave console");
$output->writeln("type 'actions' to see all available actions for this suite");
$suiteEvent = new SuiteEvent($this->suite, $this->codecept->getResult(), $settings);
$dispatcher->dispatch(Events::SUITE_BEFORE, $suiteEvent);
$dispatcher->dispatch(Events::TEST_PARSED, new TestEvent($this->test));
$dispatcher->dispatch(Events::TEST_BEFORE, new TestEvent($this->test));
$output->writeln("\n\n\$I = new {$settings['actor']}(\$scenario);");
$this->executeCommands($input, $output, $I, $settings['bootstrap']);
$dispatcher->dispatch(Events::TEST_AFTER, new TestEvent($this->test));
$dispatcher->dispatch(Events::SUITE_AFTER, new SuiteEvent($this->suite));
$output->writeln("Bye-bye!");
}
protected function executeCommands(InputInterface $input, OutputInterface $output, $I, $bootstrap)
{
$dialog = new QuestionHelper();
if (file_exists($bootstrap)) {
require $bootstrap;
}
do {
$question = new Question("\$I->");
$question->setAutocompleterValues($this->actions);
$command = $dialog->ask($input, $output, $question);
if ($command == 'actions') {
$output->writeln("" . implode(' ', $this->actions));
continue;
}
if ($command == 'exit') {
return;
}
if ($command == '') {
continue;
}
try {
$value = eval("return \$I->$command;");
if ($value && !is_object($value)) {
codecept_debug($value);
}
} catch (\PHPUnit_Framework_AssertionFailedError $fail) {
$output->writeln("fail " . $fail->getMessage());
} catch (\Exception $e) {
$output->writeln("error " . $e->getMessage());
}
} while (true);
}
protected function listenToSignals()
{
if (function_exists('pcntl_signal')) {
declare (ticks = 1);
pcntl_signal(SIGINT, SIG_IGN);
pcntl_signal(SIGTERM, SIG_IGN);
}
}
}