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); } } }