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