[BUGFIX] CLI argument handling chokes on = use
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Tests / Unit / MVC / CLI / RequestBuilderTest.php
1 <?php
2 /* *
3 * This script belongs to the Extbase framework. *
4 * *
5 * It is free software; you can redistribute it and/or modify it under *
6 * the terms of the GNU Lesser General Public License as published by the *
7 * Free Software Foundation, either version 3 of the License, or (at your *
8 * option) any later version. *
9 * *
10 * This script is distributed in the hope that it will be useful, but *
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- *
12 * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser *
13 * General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU Lesser General Public *
16 * License along with the script. *
17 * If not, see http://www.gnu.org/licenses/lgpl.html *
18 * *
19 * The TYPO3 project - inspiring people to share! *
20 * */
21
22 /**
23 * Testcase for the MVC CLI Request Builder
24 */
25 class Tx_Extbase_Tests_Unit_MVC_CLI_RequestBuilderTest extends Tx_Extbase_Tests_Unit_BaseTestCase {
26
27 /**
28 * @var Tx_Extbase_MVC_CLI_RequestBuilder
29 */
30 protected $requestBuilder;
31
32 /**
33 * @var Tx_Extbase_MVC_CLI_Request
34 */
35 protected $request;
36
37 /**
38 * @var Tx_Extbase_Object_ObjectManagerInterface
39 */
40 protected $mockObjectManager;
41
42 /**
43 * @var Tx_Extbase_MVC_CLI_Command
44 */
45 protected $mockCommand;
46
47 /**
48 * @var Tx_Extbase_MVC_CLI_CommandManager
49 */
50 protected $mockCommandManager;
51
52 /**
53 * @var Tx_Extbase_Reflection_Service
54 */
55 protected $mockReflectionService;
56
57 /**
58 * Sets up this test case
59 *
60 * @author Robert Lemke <robert@typo3.org>
61 */
62 public function setUp() {
63 $this->request = $this->getAccessibleMock('Tx_Extbase_MVC_CLI_Request', array('dummy'));
64
65 $this->mockObjectManager = $this->getMock('Tx_Extbase_Object_ObjectManagerInterface');
66 $this->mockObjectManager->expects($this->any())->method('get')->with('Tx_Extbase_MVC_CLI_Request')->will($this->returnValue($this->request));
67
68 $this->mockCommand = $this->getMock('Tx_Extbase_MVC_CLI_Command', array(), array(), '', FALSE);
69 $this->mockCommand->expects($this->any())->method('getControllerClassName')->will($this->returnValue('Tx_SomeExtensionName_Command_DefaultCommandController'));
70 $this->mockCommand->expects($this->any())->method('getControllerCommandName')->will($this->returnValue('list'));
71
72 $this->mockCommandManager = $this->getMock('Tx_Extbase_MVC_CLI_CommandManager');
73 $this->mockCommandManager->expects($this->any())->method('getCommandByIdentifier')->with('some_extension_name:default:list')->will($this->returnValue($this->mockCommand));
74
75 $this->mockReflectionService = $this->getMock('Tx_Extbase_Reflection_Service');
76
77 $this->requestBuilder = new Tx_Extbase_MVC_CLI_RequestBuilder();
78 $this->requestBuilder->injectObjectManager($this->mockObjectManager);
79 $this->requestBuilder->injectReflectionService($this->mockReflectionService);
80 $this->requestBuilder->injectCommandManager($this->mockCommandManager);
81 }
82
83 /**
84 * Checks if a CLI request specifying a package, controller and action name results in the expected request object
85 *
86 * @test
87 * @author Robert Lemke <robert@typo3.org>
88 */
89 public function cliAccessWithExtensionControllerAndActionNameBuildsCorrectRequest() {
90 $this->mockReflectionService->expects($this->once())->method('getMethodParameters')->will($this->returnValue(array()));
91
92 $request = $this->requestBuilder->build('some_extension_name:default:list');
93 $this->assertSame('Tx_SomeExtensionName_Command_DefaultCommandController', $request->getControllerObjectName());
94 $this->assertSame('list', $request->getControllerCommandName(), 'The CLI request specifying a package, controller and action name did not return a request object pointing to the expected action.');
95 }
96
97 /**
98 * @test
99 * @author Robert Lemke <robert@typo3.org>
100 * @author Bastian Waidelich <bastian@typo3.org>
101 */
102 public function ifCommandCantBeResolvedTheHelpScreenIsShown() {
103 // The following call is only made to satisfy PHPUnit. For some weird reason PHPUnit complains that the
104 // mocked method ("getObjectNameByClassName") does not exist _if the mock object is not used_.
105 $this->mockCommandManager->getCommandByIdentifier('some_extension_name:default:list');
106 $mockCommandManager = $this->getMock('Tx_Extbase_MVC_CLI_CommandManager');
107 $mockCommandManager->expects($this->any())->method('getCommandByIdentifier')->with('test:default:list')->will($this->throwException(new Tx_Extbase_MVC_Exception_NoSuchCommand()));
108 $this->requestBuilder->injectCommandManager($mockCommandManager);
109
110 $request = $this->requestBuilder->build('test:default:list');
111 $this->assertSame('Tx_Extbase_Command_HelpCommandController', $request->getControllerObjectName());
112 }
113
114 /**
115 * @test
116 */
117 public function argumentWithValueSeparatedByEqualSignBuildsCorrectRequest() {
118 $methodParameters = array(
119 'testArgument' => array('optional' => FALSE, 'type' => 'string')
120 );
121 $this->mockReflectionService->expects($this->once())->method('getMethodParameters')->with('Tx_SomeExtensionName_Command_DefaultCommandController', 'listCommand')->will($this->returnValue($methodParameters));
122
123 $request = $this->requestBuilder->build('some_extension_name:default:list --test-argument=value');
124 $this->assertTrue($request->hasArgument('testArgument'), 'The given "testArgument" was not found in the built request.');
125 $this->assertSame($request->getArgument('testArgument'), 'value', 'The "testArgument" had not the given value.');
126 }
127
128 /**
129 * Checks if a CLI request specifying some "console style" (--my-argument=value) arguments results in the expected request object
130 *
131 * @test
132 * @author Andreas Förthner <andreas.foerthner@netlogix.de>
133 */
134 public function cliAccessWithExtensionControllerActionAndArgumentsBuildsCorrectRequest() {
135 $methodParameters = array(
136 'testArgument' => array('optional' => FALSE, 'type' => 'string'),
137 'testArgument2' => array('optional' => FALSE, 'type' => 'string')
138 );
139 $this->mockReflectionService->expects($this->once())->method('getMethodParameters')->with('Tx_SomeExtensionName_Command_DefaultCommandController', 'listCommand')->will($this->returnValue($methodParameters));
140
141 $request = $this->requestBuilder->build('some_extension_name:default:list --test-argument=value --test-argument2=value2');
142 $this->assertTrue($request->hasArgument('testArgument'), 'The given "testArgument" was not found in the built request.');
143 $this->assertTrue($request->hasArgument('testArgument2'), 'The given "testArgument2" was not found in the built request.');
144 $this->assertEquals($request->getArgument('testArgument'), 'value', 'The "testArgument" had not the given value.');
145 $this->assertEquals($request->getArgument('testArgument2'), 'value2', 'The "testArgument2" had not the given value.');
146 }
147
148 /**
149 * Checks if a CLI request specifying some "console style" (--my-argument =value) arguments with spaces between name and value results in the expected request object
150 *
151 * @test
152 * @author Andreas Förthner <andreas.foerthner@netlogix.de>
153 */
154 public function checkIfCLIAccesWithPackageControllerActionAndArgumentsToleratesSpaces() {
155 $methodParameters = array(
156 'testArgument' => array('optional' => FALSE, 'type' => 'string'),
157 'testArgument2' => array('optional' => FALSE, 'type' => 'string'),
158 'testArgument3' => array('optional' => FALSE, 'type' => 'string'),
159 'testArgument4' => array('optional' => FALSE, 'type' => 'string')
160 );
161 $this->mockReflectionService->expects($this->once())->method('getMethodParameters')->with('Tx_SomeExtensionName_Command_DefaultCommandController', 'listCommand')->will($this->returnValue($methodParameters));
162
163 $request = $this->requestBuilder->build('some_extension_name:default:list --test-argument= value --test-argument2 =value2 --test-argument3 = value3 --test-argument4=value4');
164 $this->assertTrue($request->hasArgument('testArgument'), 'The given "testArgument" was not found in the built request.');
165 $this->assertTrue($request->hasArgument('testArgument2'), 'The given "testArgument2" was not found in the built request.');
166 $this->assertTrue($request->hasArgument('testArgument3'), 'The given "testArgument3" was not found in the built request.');
167 $this->assertTrue($request->hasArgument('testArgument4'), 'The given "testArgument4" was not found in the built request.');
168 $this->assertSame($request->getArgument('testArgument'), 'value', 'The "testArgument" had not the given value.');
169 $this->assertSame($request->getArgument('testArgument2'), 'value2', 'The "testArgument2" had not the given value.');
170 $this->assertSame($request->getArgument('testArgument3'), 'value3', 'The "testArgument3" had not the given value.');
171 $this->assertSame($request->getArgument('testArgument4'), 'value4', 'The "testArgument4" had not the given value.');
172 }
173
174 /**
175 * Checks if a CLI request specifying some short "console style" (-c value or -c=value or -c = value) arguments results in the expected request object
176 *
177 * @test
178 * @author Andreas Förthner <andreas.foerthner@netlogix.de>
179 */
180 public function CLIAccesWithShortArgumentsBuildsCorrectRequest() {
181 $methodParameters = array(
182 'a' => array('optional' => FALSE, 'type' => 'string'),
183 'd' => array('optional' => FALSE, 'type' => 'string'),
184 'f' => array('optional' => FALSE, 'type' => 'string'),
185 );
186 $this->mockReflectionService->expects($this->once())->method('getMethodParameters')->with('Tx_SomeExtensionName_Command_DefaultCommandController', 'listCommand')->will($this->returnValue($methodParameters));
187
188 $request = $this->requestBuilder->build('some_extension_name:default:list -d valued -f=valuef -a = valuea');
189 $this->assertTrue($request->hasArgument('d'), 'The given "d" was not found in the built request.');
190 $this->assertTrue($request->hasArgument('f'), 'The given "f" was not found in the built request.');
191 $this->assertTrue($request->hasArgument('a'), 'The given "a" was not found in the built request.');
192 $this->assertSame($request->getArgument('d'), 'valued', 'The "d" had not the given value.');
193 $this->assertSame($request->getArgument('f'), 'valuef', 'The "f" had not the given value.');
194 $this->assertSame($request->getArgument('a'), 'valuea', 'The "a" had not the given value.');
195 }
196
197 /**
198 * Checks if a CLI request specifying some mixed "console style" (-c or --my-argument -f=value) arguments with and
199 * without values results in the expected request object
200 *
201 * @test
202 * @author Andreas Förthner <andreas.foerthner@netlogix.de>
203 */
204 public function CLIAccesWithArgumentsWithAndWithoutValuesBuildsCorrectRequest() {
205 $methodParameters = array(
206 'testArgument' => array('optional' => FALSE, 'type' => 'string'),
207 'testArgument2' => array('optional' => FALSE, 'type' => 'string'),
208 'testArgument3' => array('optional' => FALSE, 'type' => 'string'),
209 'testArgument4' => array('optional' => FALSE, 'type' => 'string'),
210 'testArgument5' => array('optional' => FALSE, 'type' => 'string'),
211 'testArgument6' => array('optional' => FALSE, 'type' => 'string'),
212 'testArgument7' => array('optional' => FALSE, 'type' => 'string'),
213 'f' => array('optional' => FALSE, 'type' => 'string'),
214 'd' => array('optional' => FALSE, 'type' => 'string'),
215 'a' => array('optional' => FALSE, 'type' => 'string'),
216 'c' => array('optional' => FALSE, 'type' => 'string'),
217 'j' => array('optional' => FALSE, 'type' => 'string'),
218 'k' => array('optional' => FALSE, 'type' => 'string'),
219 'm' => array('optional' => FALSE, 'type' => 'string'),
220 );
221 $this->mockReflectionService->expects($this->once())->method('getMethodParameters')->with('Tx_SomeExtensionName_Command_DefaultCommandController', 'listCommand')->will($this->returnValue($methodParameters));
222
223 $request = $this->requestBuilder->build('some_extension_name:default:list --test-argument=value --test-argument2= value2 -k --test-argument-3 = value3 --test-argument4=value4 -f valuef -d=valued -a = valuea -c --testArgument7 --test-argument5 = 5 --test-argument6 -j kjk -m');
224 $this->assertTrue($request->hasArgument('testArgument'), 'The given "testArgument" was not found in the built request.');
225 $this->assertTrue($request->hasArgument('testArgument2'), 'The given "testArgument2" was not found in the built request.');
226 $this->assertTrue($request->hasArgument('k'), 'The given "k" was not found in the built request.');
227 $this->assertTrue($request->hasArgument('testArgument3'), 'The given "testArgument3" was not found in the built request.');
228 $this->assertTrue($request->hasArgument('testArgument4'), 'The given "testArgument4" was not found in the built request.');
229 $this->assertTrue($request->hasArgument('f'), 'The given "f" was not found in the built request.');
230 $this->assertTrue($request->hasArgument('d'), 'The given "d" was not found in the built request.');
231 $this->assertTrue($request->hasArgument('a'), 'The given "a" was not found in the built request.');
232 $this->assertTrue($request->hasArgument('c'), 'The given "d" was not found in the built request.');
233 $this->assertTrue($request->hasArgument('testArgument7'), 'The given "testArgument7" was not found in the built request.');
234 $this->assertTrue($request->hasArgument('testArgument5'), 'The given "testArgument5" was not found in the built request.');
235 $this->assertTrue($request->hasArgument('testArgument6'), 'The given "testArgument6" was not found in the built request.');
236 $this->assertTrue($request->hasArgument('j'), 'The given "j" was not found in the built request.');
237 $this->assertTrue($request->hasArgument('m'), 'The given "m" was not found in the built request.');
238 $this->assertSame($request->getArgument('testArgument'), 'value', 'The "testArgument" had not the given value.');
239 $this->assertSame($request->getArgument('testArgument2'), 'value2', 'The "testArgument2" had not the given value.');
240 $this->assertSame($request->getArgument('testArgument3'), 'value3', 'The "testArgument3" had not the given value.');
241 $this->assertSame($request->getArgument('testArgument4'), 'value4', 'The "testArgument4" had not the given value.');
242 $this->assertSame($request->getArgument('f'), 'valuef', 'The "f" had not the given value.');
243 $this->assertSame($request->getArgument('d'), 'valued', 'The "d" had not the given value.');
244 $this->assertSame($request->getArgument('a'), 'valuea', 'The "a" had not the given value.');
245 $this->assertSame($request->getArgument('testArgument5'), '5', 'The "testArgument4" had not the given value.');
246 $this->assertSame($request->getArgument('j'), 'kjk', 'The "j" had not the given value.');
247 }
248
249 /**
250 * @test
251 * @author Robert Lemke <robert@typo3.org>
252 */
253 public function insteadOfNamedArgumentsTheArgumentsCanBePassedUnnamedInTheCorrectOrder() {
254 $methodParameters = array(
255 'testArgument1' => array('optional' => FALSE, 'type' => 'string'),
256 'testArgument2' => array('optional' => FALSE, 'type' => 'string'),
257 );
258 $this->mockReflectionService->expects($this->exactly(2))->method('getMethodParameters')->with('Tx_SomeExtensionName_Command_DefaultCommandController', 'listCommand')->will($this->returnValue($methodParameters));
259
260 $request = $this->requestBuilder->build('some_extension_name:default:list --test-argument1 firstArgumentValue --test-argument2 secondArgumentValue');
261 $this->assertSame('firstArgumentValue', $request->getArgument('testArgument1'));
262 $this->assertSame('secondArgumentValue', $request->getArgument('testArgument2'));
263
264 $request = $this->requestBuilder->build('some_extension_name:default:list firstArgumentValue secondArgumentValue');
265 $this->assertSame('firstArgumentValue', $request->getArgument('testArgument1'));
266 $this->assertSame('secondArgumentValue', $request->getArgument('testArgument2'));
267 }
268
269 /**
270 * @test
271 * @author Karsten Dambekalns <karsten@typo3.org>
272 */
273 public function argumentsAreDetectedAfterOptions() {
274 $methodParameters = array(
275 'some' => array('optional' => TRUE, 'type' => 'boolean'),
276 'option' => array('optional' => TRUE, 'type' => 'string'),
277 'argument1' => array('optional' => FALSE, 'type' => 'string'),
278 'argument2' => array('optional' => FALSE, 'type' => 'string'),
279 );
280 $this->mockReflectionService->expects($this->once())->method('getMethodParameters')->with('Tx_SomeExtensionName_Command_DefaultCommandController', 'listCommand')->will($this->returnValue($methodParameters));
281
282 $request = $this->requestBuilder->build('some_extension_name:default:list --some -option=value file1 file2');
283 $this->assertSame('list', $request->getControllerCommandName());
284 $this->assertTrue($request->getArgument('some'));
285 $this->assertSame('file1', $request->getArgument('argument1'));
286 $this->assertSame('file2', $request->getArgument('argument2'));
287 }
288
289 /**
290 * @test
291 * @author Robert Lemke <robert@typo3.org>
292 */
293 public function exceedingArgumentsMayBeSpecified() {
294 $methodParameters = array(
295 'testArgument1' => array('optional' => FALSE, 'type' => 'string'),
296 'testArgument2' => array('optional' => FALSE, 'type' => 'string'),
297 );
298 $this->mockReflectionService->expects($this->once())->method('getMethodParameters')->with('Tx_SomeExtensionName_Command_DefaultCommandController', 'listCommand')->will($this->returnValue($methodParameters));
299
300 $expectedArguments = array('testArgument1' => 'firstArgumentValue', 'testArgument2' => 'secondArgumentValue');
301
302 $request = $this->requestBuilder->build('some_extension_name:default:list --test-argument1=firstArgumentValue --test-argument2 secondArgumentValue exceedingArgument1');
303 $this->assertEquals($expectedArguments, $request->getArguments());
304 $this->assertEquals(array('exceedingArgument1'), $request->getExceedingArguments());
305 }
306
307 /**
308 * @test
309 * @expectedException Tx_Extbase_MVC_Exception_InvalidArgumentMixing
310 * @author Robert Lemke <robert@typo3.org>
311 */
312 public function ifNamedArgumentsAreUsedAllRequiredArgumentsMustBeNamed() {
313 $methodParameters = array(
314 'testArgument1' => array('optional' => FALSE, 'type' => 'string'),
315 'testArgument2' => array('optional' => FALSE, 'type' => 'string'),
316 );
317 $this->mockReflectionService->expects($this->once())->method('getMethodParameters')->with('Tx_SomeExtensionName_Command_DefaultCommandController', 'listCommand')->will($this->returnValue($methodParameters));
318
319 $this->requestBuilder->build('some_extension_name:default:list --test-argument1 firstArgumentValue secondArgumentValue');
320 }
321
322 /**
323 * @test
324 * @expectedException Tx_Extbase_MVC_Exception_InvalidArgumentMixing
325 * @author Robert Lemke <robert@typo3.org>
326 */
327 public function ifUnnamedArgumentsAreUsedAllRequiredArgumentsMustBeUnnamed() {
328 $methodParameters = array(
329 'requiredArgument1' => array('optional' => FALSE, 'type' => 'string'),
330 'requiredArgument2' => array('optional' => FALSE, 'type' => 'string'),
331 );
332 $this->mockReflectionService->expects($this->once())->method('getMethodParameters')->with('Tx_SomeExtensionName_Command_DefaultCommandController', 'listCommand')->will($this->returnValue($methodParameters));
333
334 $this->requestBuilder->build('some_extension_name:default:list firstArgumentValue --required-argument2 secondArgumentValue');
335 }
336
337 /**
338 * @test
339 * @author Robert Lemke <robert@typo3.org>
340 */
341 public function booleanOptionsAreConsideredEvenIfAnUnnamedArgumentFollows() {
342 $methodParameters = array(
343 'requiredArgument1' => array('optional' => FALSE, 'type' => 'string'),
344 'requiredArgument2' => array('optional' => FALSE, 'type' => 'string'),
345 'booleanOption' => array('optional' => TRUE, 'type' => 'boolean'),
346 );
347 $this->mockReflectionService->expects($this->once())->method('getMethodParameters')->with('Tx_SomeExtensionName_Command_DefaultCommandController', 'listCommand')->will($this->returnValue($methodParameters));
348
349 $expectedArguments = array('requiredArgument1' => 'firstArgumentValue', 'requiredArgument2' => 'secondArgumentValue', 'booleanOption' => TRUE);
350
351 $request = $this->requestBuilder->build('some_extension_name:default:list --booleanOption firstArgumentValue secondArgumentValue');
352 $this->assertEquals($expectedArguments, $request->getArguments());
353 }
354
355 /**
356 * @test
357 * @author Robert Lemke <robert@typo3.org>
358 */
359 public function booleanOptionsCanHaveOnlyCertainValuesIfTheValueIsAssignedWithoutEqualSign() {
360 $methodParameters = array(
361 'b1' => array('optional' => TRUE, 'type' => 'boolean'),
362 'b2' => array('optional' => TRUE, 'type' => 'boolean'),
363 'b3' => array('optional' => TRUE, 'type' => 'boolean'),
364 'b4' => array('optional' => TRUE, 'type' => 'boolean'),
365 'b5' => array('optional' => TRUE, 'type' => 'boolean'),
366 'b6' => array('optional' => TRUE, 'type' => 'boolean'),
367 );
368 $this->mockReflectionService->expects($this->once())->method('getMethodParameters')->with('Tx_SomeExtensionName_Command_DefaultCommandController', 'listCommand')->will($this->returnValue($methodParameters));
369
370 $expectedArguments = array('b1' => TRUE, 'b2' => TRUE, 'b3' => TRUE, 'b4' => FALSE, 'b5' => FALSE, 'b6' => FALSE);
371
372 $request = $this->requestBuilder->build('some_extension_name:default:list --b2 y --b1 1 --b3 true --b4 false --b5 n --b6 0');
373 $this->assertEquals($expectedArguments, $request->getArguments());
374 }
375 }
376
377 ?>