1+ <?php
2+ namespace Codeception \Command ;
3+
4+ use Codeception \AbstractGuy ;
5+ use Codeception \Event \Suite ;
6+ use Codeception \Scenario ;
7+ use Codeception \SuiteManager ;
8+ use Codeception \TestCase \Cept ;
9+ use Symfony \Component \Console \Input \InputArgument ;
10+ use Symfony \Component \Console \Input \InputInterface ;
11+ use Symfony \Component \Console \Input \InputOption ;
12+ use Symfony \Component \Console \Output \OutputInterface ;
13+
14+ class Console extends Base {
15+
16+ protected $ test ;
17+ protected $ codecept ;
18+ protected $ suite ;
19+
20+
21+ protected function configure ()
22+ {
23+ $ this ->setDefinition (array (
24+ new InputArgument ('suite ' , InputArgument::REQUIRED , 'suite to be executed ' ),
25+ new InputOption ('config ' , 'c ' , InputOption::VALUE_OPTIONAL , 'Use custom path for config ' ),
26+ new InputOption ('colors ' , '' , InputOption::VALUE_NONE , 'Use colors in output ' ),
27+ ));
28+ parent ::configure ();
29+ }
30+
31+ public function getDescription ()
32+ {
33+ return 'Launches interactive test console ' ;
34+ }
35+
36+ public function execute (InputInterface $ input , OutputInterface $ output )
37+ {
38+ $ suiteName = $ input ->getArgument ('suite ' );
39+ $ this ->output = $ output ;
40+
41+ $ config = \Codeception \Configuration::config ($ input ->getOption ('config ' ));
42+ $ settings = \Codeception \Configuration::suiteSettings ($ suiteName , $ config );
43+
44+ $ options = $ input ->getOptions ();
45+ $ options ['debug ' ] = true ;
46+ $ options ['steps ' ] = true ;
47+
48+ $ this ->codecept = new \Codeception \Codecept ($ options );
49+ $ dispatcher = $ this ->codecept ->getDispatcher ();
50+ $ suiteManager = new SuiteManager ($ dispatcher , $ suiteName , $ settings );
51+ $ this ->suite = $ suiteManager ->getSuite ();
52+ $ this ->test = new Cept ($ dispatcher , array ('name ' => 'interactive ' , 'file ' => 'interactive ' ));
53+
54+ $ guy = $ settings ['class_name ' ];
55+ $ scenario = new Scenario ($ this ->test );
56+ $ I = new $ guy ($ scenario );
57+
58+ $ this ->listenToSignals ();
59+
60+ $ output ->writeln ("<info>Interactive console started for suite $ suiteName</info> " );
61+ $ output ->writeln ("<info>Try Codeception commands without writing a test</info> " );
62+ $ output ->writeln ("<info>type 'exit' to leave console</info> " );
63+
64+ $ dispatcher ->dispatch ('suite.before ' , new Suite ($ this ->suite , $ this ->codecept ->getResult (), $ settings ));
65+ $ dispatcher ->dispatch ('test.parsed ' , new \Codeception \Event \Test ($ this ->test ));
66+ $ dispatcher ->dispatch ('test.before ' , new \Codeception \Event \Test ($ this ->test ));
67+
68+ $ output ->writeln ("\n\n\$I = new {$ settings ['class_name ' ]}( \$scenario); " );
69+ $ scenario ->run ();
70+
71+ $ this ->executeCommands ($ output , $ I , $ settings ['bootstrap ' ]);
72+ $ dispatcher ->dispatch ('test.after ' , new \Codeception \Event \Test ($ this ->test ));
73+ $ dispatcher ->dispatch ('suite.after ' , new Suite ($ this ->suite ));
74+
75+ $ output ->writeln ("<info>Bye-bye!</info> " );
76+ }
77+
78+
79+ protected function executeCommands (OutputInterface $ output , AbstractGuy $ I , $ bootstrap )
80+ {
81+ $ dialog = $ this ->getHelperSet ()->get ('dialog ' );
82+
83+ if (file_exists ($ bootstrap )) require $ bootstrap ;
84+
85+ do {
86+ $ command = $ dialog ->ask ($ output , '$I-> ' );
87+ if ($ command == 'exit ' ) return ;
88+ if ($ command == '' ) continue ;
89+ try {
90+ eval ("\$I-> $ command; " );
91+ } catch (\PHPUnit_Framework_AssertionFailedError $ fail ) {
92+ $ output ->writeln ("<error>fail</error> " .$ fail ->getMessage ());
93+ } catch (\Exception $ e ) {
94+ $ output ->writeln ("<error>error</error> " .$ e ->getMessage ());
95+ }
96+
97+ } while (true );
98+ }
99+
100+ protected function listenToSignals ()
101+ {
102+ if (function_exists ('pcntl_signal ' )) {
103+ declare (ticks = 1 );
104+ pcntl_signal (SIGINT , function () {});
105+ pcntl_signal (SIGTERM , function () {});
106+ }
107+ }
108+
109+ }
0 commit comments