1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14: namespace Cake\TestSuite;
15:
16: use Cake\Console\CommandRunner;
17: use Cake\Console\ConsoleInput;
18: use Cake\Console\ConsoleIo;
19: use Cake\Console\Exception\StopException;
20: use Cake\Core\Configure;
21: use Cake\TestSuite\Constraint\Console\ContentsContain;
22: use Cake\TestSuite\Constraint\Console\ContentsContainRow;
23: use Cake\TestSuite\Constraint\Console\ContentsEmpty;
24: use Cake\TestSuite\Constraint\Console\ContentsNotContain;
25: use Cake\TestSuite\Constraint\Console\ContentsRegExp;
26: use Cake\TestSuite\Constraint\Console\ExitCode;
27: use Cake\TestSuite\Stub\ConsoleOutput;
28:
29: 30: 31: 32:
33: trait ConsoleIntegrationTestTrait
34: {
35: 36: 37: 38: 39:
40: protected $_useCommandRunner = false;
41:
42: 43: 44: 45: 46:
47: protected $_exitCode;
48:
49: 50: 51: 52: 53:
54: protected $_out;
55:
56: 57: 58: 59: 60:
61: protected $_err;
62:
63: 64: 65: 66: 67:
68: protected $_in;
69:
70: 71: 72: 73: 74: 75: 76:
77: public function exec($command, array $input = [])
78: {
79: $runner = $this->makeRunner();
80:
81: $this->_out = new ConsoleOutput();
82: $this->_err = new ConsoleOutput();
83: $this->_in = $this->getMockBuilder(ConsoleInput::class)
84: ->disableOriginalConstructor()
85: ->setMethods(['read'])
86: ->getMock();
87:
88: $i = 0;
89: foreach ($input as $in) {
90: $this->_in
91: ->expects($this->at($i++))
92: ->method('read')
93: ->will($this->returnValue($in));
94: }
95:
96: $args = $this->commandStringToArgs("cake $command");
97: $io = new ConsoleIo($this->_out, $this->_err, $this->_in);
98:
99: try {
100: $this->_exitCode = $runner->run($args, $io);
101: } catch (StopException $exception) {
102: $this->_exitCode = $exception->getCode();
103: }
104: }
105:
106: 107: 108: 109: 110: 111:
112: public function cleanupConsoleTrait()
113: {
114: $this->_exitCode = null;
115: $this->_out = null;
116: $this->_err = null;
117: $this->_in = null;
118: $this->_useCommandRunner = false;
119: }
120:
121: 122: 123: 124: 125: 126:
127: public function useCommandRunner()
128: {
129: $this->_useCommandRunner = true;
130: }
131:
132: 133: 134: 135: 136: 137: 138:
139: public function assertExitCode($expected, $message = '')
140: {
141: $this->assertThat($expected, new ExitCode($this->_exitCode), $message);
142: }
143:
144: 145: 146: 147: 148: 149:
150: public function assertOutputEmpty($message = '')
151: {
152: $this->assertThat(null, new ContentsEmpty($this->_out->messages(), 'output'), $message);
153: }
154:
155: 156: 157: 158: 159: 160: 161:
162: public function assertOutputContains($expected, $message = '')
163: {
164: $this->assertThat($expected, new ContentsContain($this->_out->messages(), 'output'), $message);
165: }
166: 167: 168: 169: 170: 171: 172:
173: public function assertOutputNotContains($expected, $message = '')
174: {
175: $this->assertThat($expected, new ContentsNotContain($this->_out->messages(), 'output'), $message);
176: }
177:
178: 179: 180: 181: 182: 183: 184:
185: public function assertOutputRegExp($pattern, $message = '')
186: {
187: $this->assertThat($pattern, new ContentsRegExp($this->_out->messages(), 'output'), $message);
188: }
189:
190: 191: 192: 193: 194: 195: 196:
197: protected function assertOutputContainsRow(array $row, $message = '')
198: {
199: $this->assertThat($row, new ContentsContainRow($this->_out->messages(), 'output'), $message);
200: }
201:
202: 203: 204: 205: 206: 207: 208:
209: public function assertErrorContains($expected, $message = '')
210: {
211: $this->assertThat($expected, new ContentsContain($this->_err->messages(), 'error output'), $message);
212: }
213:
214: 215: 216: 217: 218: 219: 220:
221: public function assertErrorRegExp($pattern, $message = '')
222: {
223: $this->assertThat($pattern, new ContentsRegExp($this->_err->messages(), 'error output'), $message);
224: }
225:
226: 227: 228: 229: 230: 231:
232: public function assertErrorEmpty($message = '')
233: {
234: $this->assertThat(null, new ContentsEmpty($this->_err->messages(), 'error output'), $message);
235: }
236:
237: 238: 239: 240: 241:
242: protected function makeRunner()
243: {
244: if ($this->_useCommandRunner) {
245: $applicationClassName = Configure::read('App.namespace') . '\Application';
246:
247: return new CommandRunner(new $applicationClassName(CONFIG));
248: }
249:
250: return new LegacyCommandRunner();
251: }
252:
253: 254: 255: 256: 257: 258:
259: protected function commandStringToArgs($command)
260: {
261: $charCount = strlen($command);
262: $argv = [];
263: $arg = '';
264: $inDQuote = false;
265: $inSQuote = false;
266: for ($i = 0; $i < $charCount; $i++) {
267: $char = substr($command, $i, 1);
268:
269:
270: if ($char === ' ' && !$inDQuote && !$inSQuote) {
271: if (strlen($arg)) {
272: $argv[] = $arg;
273: }
274: $arg = '';
275: continue;
276: }
277:
278:
279: if ($inSQuote && $char === "'") {
280: $inSQuote = false;
281: continue;
282: }
283:
284:
285: if ($inDQuote && $char === '"') {
286: $inDQuote = false;
287: continue;
288: }
289:
290:
291: if ($char === '"' && !$inSQuote) {
292: $inDQuote = true;
293: continue;
294: }
295:
296:
297: if ($char === "'" && !$inDQuote) {
298: $inSQuote = true;
299: continue;
300: }
301:
302: $arg .= $char;
303: }
304: $argv[] = $arg;
305:
306: return $argv;
307: }
308: }
309: