‪TYPO3CMS  10.4
ActionControllerTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Prophecy\Argument;
34 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
35 use TYPO3Fluid\Fluid\View\AbstractTemplateView;
36 use TYPO3Fluid\Fluid\View\TemplateView as FluidTemplateView;
37 
41 class ‪ActionControllerTest extends UnitTestCase
42 {
46  protected ‪$resetSingletonInstances = true;
47 
51  protected ‪$actionController;
52 
56  protected ‪$mockObjectManager;
57 
61  protected ‪$mockUriBuilder;
62 
67 
72  {
73  $mockRequest = $this->createMock(Request::class);
74  $mockRequest->expects(self::once())->method('getControllerActionName')->willReturn('fooBar');
76  $mockController = $this->getAccessibleMock(ActionController::class, ['fooBarAction'], [], '', false);
77  $mockController->_set('request', $mockRequest);
78  self::assertEquals('fooBarAction', $mockController->_call('resolveActionMethodName'));
79  }
80 
85  {
86  $this->expectException(NoSuchActionException::class);
87  $this->expectExceptionCode(1186669086);
88  $mockRequest = $this->createMock(Request::class);
89  $mockRequest->expects(self::once())->method('getControllerActionName')->willReturn('fooBar');
91  $mockController = $this->getAccessibleMock(ActionController::class, ['otherBarAction'], [], '', false);
92  $mockController->_set('request', $mockRequest);
93  $mockController->_call('resolveActionMethodName');
94  }
95 
102  {
103  $mockRequest = $this->createMock(Request::class);
104  $mockArguments = $this->getMockBuilder(Arguments::class)
105  ->setMethods(['addNewArgument', 'removeAll'])
106  ->getMock();
107  $mockArguments->expects(self::exactly(3))->method('addNewArgument')
108  ->withConsecutive(
109  ['stringArgument', 'string', true],
110  ['integerArgument', 'integer', true],
111  ['objectArgument', 'F3_Foo_Bar', true]
112  );
113  $mockController = $this->getAccessibleMock(ActionController::class, ['fooAction', 'evaluateDontValidateAnnotations'], [], '', false);
114 
115  $classSchemaMethod = new Method(
116  'fooAction',
117  [
118  'params' => [
119  'stringArgument' => [
120  'position' => 0,
121  'byReference' => false,
122  'array' => false,
123  'optional' => false,
124  'allowsNull' => false,
125  'type' => 'string',
126  'hasDefaultValue' => false
127  ],
128  'integerArgument' => [
129  'position' => 1,
130  'byReference' => false,
131  'array' => false,
132  'optional' => false,
133  'allowsNull' => false,
134  'type' => 'integer',
135  'hasDefaultValue' => false
136  ],
137  'objectArgument' => [
138  'position' => 2,
139  'byReference' => false,
140  'array' => false,
141  'optional' => false,
142  'allowsNull' => false,
143  'type' => 'F3_Foo_Bar',
144  'hasDefaultValue' => false
145  ]
146  ]
147  ],
148  get_class($mockController)
149  );
150 
151  $classSchemaMock = $this->createMock(ClassSchema::class);
152  $classSchemaMock
153  ->expects(self::any())
154  ->method('getMethod')
155  ->with('fooAction')
156  ->willReturn($classSchemaMethod);
157 
158  $mockReflectionService = $this->createMock(ReflectionService::class);
159  $mockReflectionService
160  ->expects(self::any())
161  ->method('getClassSchema')
162  ->with(get_class($mockController))
163  ->willReturn($classSchemaMock);
164  $mockController->_set('reflectionService', $mockReflectionService);
165  $mockController->_set('request', $mockRequest);
166  $mockController->_set('arguments', $mockArguments);
167  $mockController->_set('actionMethodName', 'fooAction');
168  $mockController->_call('initializeActionMethodArguments');
169  }
170 
175  {
176  $mockRequest = $this->createMock(Request::class);
177  $mockArguments = $this->createMock(Arguments::class);
178  $mockArguments->expects(self::exactly(3))->method('addNewArgument')
179  ->withConsecutive(
180  ['arg1', 'string', true],
181  ['arg2', 'array', false, [21]],
182  ['arg3', 'string', false, 42]
183  );
184  $mockController = $this->getAccessibleMock(ActionController::class, ['fooAction', 'evaluateDontValidateAnnotations'], [], '', false);
185 
186  $classSchemaMethod = new ‪Method(
187  'fooAction',
188  [
189  'params' => [
190  'arg1' => [
191  'position' => 0,
192  'byReference' => false,
193  'array' => false,
194  'optional' => false,
195  'allowsNull' => false,
196  'type' => 'string',
197  'hasDefaultValue' => false
198  ],
199  'arg2' => [
200  'position' => 1,
201  'byReference' => false,
202  'array' => true,
203  'optional' => true,
204  'defaultValue' => [21],
205  'allowsNull' => false,
206  'hasDefaultValue' => true
207  ],
208  'arg3' => [
209  'position' => 2,
210  'byReference' => false,
211  'array' => false,
212  'optional' => true,
213  'defaultValue' => 42,
214  'allowsNull' => false,
215  'type' => 'string',
216  'hasDefaultValue' => true
217  ]
218  ]
219  ],
220  get_class($mockController)
221  );
222 
223  $classSchemaMock = $this->createMock(ClassSchema::class);
224  $classSchemaMock
225  ->expects(self::any())
226  ->method('getMethod')
227  ->with('fooAction')
228  ->willReturn($classSchemaMethod);
229 
230  $mockReflectionService = $this->createMock(ReflectionService::class);
231  $mockReflectionService
232  ->expects(self::any())
233  ->method('getClassSchema')
234  ->with(get_class($mockController))
235  ->willReturn($classSchemaMock);
236  $mockController->_set('reflectionService', $mockReflectionService);
237  $mockController->_set('request', $mockRequest);
238  $mockController->_set('arguments', $mockArguments);
239  $mockController->_set('actionMethodName', 'fooAction');
240  $mockController->_call('initializeActionMethodArguments');
241  }
242 
247  {
248  $this->expectException(InvalidArgumentTypeException::class);
249  $this->expectExceptionCode(1253175643);
250  $mockRequest = $this->createMock(Request::class);
251  $mockArguments = $this->createMock(Arguments::class);
252  $mockController = $this->getAccessibleMock(ActionController::class, ['fooAction'], [], '', false);
253 
254  $classSchemaMethod = new ‪Method(
255  'fooAction',
256  [
257  'params' => [
258  'arg1' => [
259  'position' => 0,
260  'byReference' => false,
261  'array' => false,
262  'optional' => false,
263  'allowsNull' => false
264  ]
265  ]
266  ],
267  get_class($mockController)
268  );
269 
270  $classSchemaMock = $this->createMock(ClassSchema::class);
271  $classSchemaMock
272  ->expects(self::any())
273  ->method('getMethod')
274  ->with('fooAction')
275  ->willReturn($classSchemaMethod);
276 
277  $mockReflectionService = $this->createMock(ReflectionService::class);
278  $mockReflectionService
279  ->expects(self::any())
280  ->method('getClassSchema')
281  ->with(get_class($mockController))
282  ->willReturn($classSchemaMock);
283  $mockController->_set('reflectionService', $mockReflectionService);
284  $mockController->_set('request', $mockRequest);
285  $mockController->_set('arguments', $mockArguments);
286  $mockController->_set('actionMethodName', 'fooAction');
287  $mockController->_call('initializeActionMethodArguments');
288  }
289 
296  public function ‪setViewConfigurationResolvesTemplateRootPathsForTemplateRootPath($configuration, $expected)
297  {
299  $mockController = $this->getAccessibleMock(ActionController::class, ['dummy'], [], '', false);
301  $mockConfigurationManager = $this->createMock(ConfigurationManagerInterface::class);
302  $mockConfigurationManager->expects(self::any())->method('getConfiguration')->willReturn($configuration);
303  $mockController->injectConfigurationManager($mockConfigurationManager);
304  $mockController->_set('request', $this->createMock(Request::class), ['getControllerExtensionKey']);
305  $view = $this->getMockBuilder(ViewInterface::class)
306  ->setMethods(['setControllerContext', 'assign', 'assignMultiple', 'canRender', 'render', 'initializeView', 'setTemplateRootPaths'])
307  ->getMock();
308  $view->expects(self::once())->method('setTemplateRootPaths')->with($expected);
309  $mockController->_call('setViewConfiguration', $view);
310  }
311 
315  public function ‪templateRootPathDataProvider()
316  {
317  return [
318  'text keys' => [
319  [
320  'view' => [
321  'templateRootPaths' => [
322  'default' => 'some path',
323  'extended' => 'some other path'
324  ]
325  ]
326  ],
327  [
328  'extended' => 'some other path',
329  'default' => 'some path'
330  ]
331  ],
332  'numerical keys' => [
333  [
334  'view' => [
335  'templateRootPaths' => [
336  '10' => 'some path',
337  '20' => 'some other path',
338  '15' => 'intermediate specific path'
339  ]
340  ]
341  ],
342  [
343  '20' => 'some other path',
344  '15' => 'intermediate specific path',
345  '10' => 'some path'
346  ]
347  ],
348  'mixed keys' => [
349  [
350  'view' => [
351  'templateRootPaths' => [
352  '10' => 'some path',
353  'very_specific' => 'some other path',
354  '15' => 'intermediate specific path'
355  ]
356  ]
357  ],
358  [
359  '15' => 'intermediate specific path',
360  'very_specific' => 'some other path',
361  '10' => 'some path'
362  ]
363  ],
364  ];
365  }
366 
374  public function ‪setViewConfigurationResolvesLayoutRootPathsForLayoutRootPath($configuration, $expected)
375  {
377  $mockController = $this->getAccessibleMock(ActionController::class, ['dummy'], [], '', false);
379  $mockConfigurationManager = $this->createMock(ConfigurationManagerInterface::class);
380  $mockConfigurationManager->expects(self::any())->method('getConfiguration')->willReturn($configuration);
381  $mockController->injectConfigurationManager($mockConfigurationManager);
382  $mockController->_set('request', $this->createMock(Request::class), ['getControllerExtensionKey']);
383  $view = $this->getMockBuilder(ViewInterface::class)
384  ->setMethods(['setControllerContext', 'assign', 'assignMultiple', 'canRender', 'render', 'initializeView', 'setlayoutRootPaths'])
385  ->getMock();
386  $view->expects(self::once())->method('setlayoutRootPaths')->with($expected);
387  $mockController->_call('setViewConfiguration', $view);
388  }
389 
393  public function ‪layoutRootPathDataProvider()
394  {
395  return [
396  'text keys' => [
397  [
398  'view' => [
399  'layoutRootPaths' => [
400  'default' => 'some path',
401  'extended' => 'some other path'
402  ]
403  ]
404  ],
405  [
406  'extended' => 'some other path',
407  'default' => 'some path'
408  ]
409  ],
410  'numerical keys' => [
411  [
412  'view' => [
413  'layoutRootPaths' => [
414  '10' => 'some path',
415  '20' => 'some other path',
416  '15' => 'intermediate specific path'
417  ]
418  ]
419  ],
420  [
421  '20' => 'some other path',
422  '15' => 'intermediate specific path',
423  '10' => 'some path'
424  ]
425  ],
426  'mixed keys' => [
427  [
428  'view' => [
429  'layoutRootPaths' => [
430  '10' => 'some path',
431  'very_specific' => 'some other path',
432  '15' => 'intermediate specific path'
433  ]
434  ]
435  ],
436  [
437  '15' => 'intermediate specific path',
438  'very_specific' => 'some other path',
439  '10' => 'some path'
440  ]
441  ],
442  ];
443  }
444 
452  public function ‪setViewConfigurationResolvesPartialRootPathsForPartialRootPath($configuration, $expected)
453  {
455  $mockController = $this->getAccessibleMock(ActionController::class, ['dummy'], [], '', false);
457  $mockConfigurationManager = $this->createMock(ConfigurationManagerInterface::class);
458  $mockConfigurationManager->expects(self::any())->method('getConfiguration')->willReturn($configuration);
459  $mockController->injectConfigurationManager($mockConfigurationManager);
460  $mockController->_set('request', $this->createMock(Request::class), ['getControllerExtensionKey']);
461  $view = $this->getMockBuilder(ViewInterface::class)
462  ->setMethods(['setControllerContext', 'assign', 'assignMultiple', 'canRender', 'render', 'initializeView', 'setpartialRootPaths'])
463  ->getMock();
464  $view->expects(self::once())->method('setpartialRootPaths')->with($expected);
465  $mockController->_call('setViewConfiguration', $view);
466  }
467 
471  public function ‪partialRootPathDataProvider()
472  {
473  return [
474  'text keys' => [
475  [
476  'view' => [
477  'partialRootPaths' => [
478  'default' => 'some path',
479  'extended' => 'some other path'
480  ]
481  ]
482  ],
483  [
484  'extended' => 'some other path',
485  'default' => 'some path'
486  ]
487  ],
488  'numerical keys' => [
489  [
490  'view' => [
491  'partialRootPaths' => [
492  '10' => 'some path',
493  '20' => 'some other path',
494  '15' => 'intermediate specific path'
495  ]
496  ]
497  ],
498  [
499  '20' => 'some other path',
500  '15' => 'intermediate specific path',
501  '10' => 'some path'
502  ]
503  ],
504  'mixed keys' => [
505  [
506  'view' => [
507  'partialRootPaths' => [
508  '10' => 'some path',
509  'very_specific' => 'some other path',
510  '15' => 'intermediate specific path'
511  ]
512  ]
513  ],
514  [
515  '15' => 'intermediate specific path',
516  'very_specific' => 'some other path',
517  '10' => 'some path'
518  ]
519  ],
520  ];
521  }
522 
530  public function ‪rendersAndAssignsAssetsFromViewIntoPageRenderer($viewMock, $expectedHeader, $expectedFooter)
531  {
532  $pageRenderer = $this->prophesize(PageRenderer::class);
533  GeneralUtility::setSingletonInstance(PageRenderer::class, $pageRenderer->reveal());
534  if (!empty(trim($expectedHeader ?? ''))) {
535  $pageRenderer->addHeaderData($expectedHeader)->shouldBeCalled();
536  } else {
537  $pageRenderer->addHeaderData(Argument::any())->shouldNotBeCalled();
538  }
539  if (!empty(trim($expectedFooter ?? ''))) {
540  $pageRenderer->addFooterData($expectedFooter)->shouldBeCalled();
541  } else {
542  $pageRenderer->addFooterData(Argument::any())->shouldNotBeCalled();
543  }
544  $requestMock = $this->getMockBuilder(RequestInterface::class)->getMockForAbstractClass();
545  $subject = new ActionController('');
546  $viewProperty = new \ReflectionProperty($subject, 'view');
547  $viewProperty->setAccessible(true);
548  $viewProperty->setValue($subject, $viewMock);
549 
550  $method = new \ReflectionMethod($subject, 'renderAssetsForRequest');
551  $method->setAccessible(true);
552  $method->invokeArgs($subject, [$requestMock]);
553  }
554 
558  public function ‪headerAssetDataProvider()
559  {
560  $viewWithHeaderData = $this->getMockBuilder(FluidTemplateView::class)->setMethods(['renderSection'])->disableOriginalConstructor()->getMock();
561  $viewWithHeaderData->expects(self::exactly(2))->method('renderSection')
562  ->withConsecutive(
563  ['HeaderAssets', self::anything(), true],
564  ['FooterAssets', self::anything(), true]
565  )
566  ->willReturnOnConsecutiveCalls('custom-header-data', null);
567  $viewWithFooterData = $this->getMockBuilder(FluidTemplateView::class)->setMethods(['renderSection'])->disableOriginalConstructor()->getMock();
568  $viewWithFooterData->expects(self::exactly(2))->method('renderSection')
569  ->withConsecutive(
570  ['HeaderAssets', self::anything(), true],
571  ['FooterAssets', self::anything(), true]
572  )
573  ->willReturnOnConsecutiveCalls(null, 'custom-footer-data');
574  $viewWithBothData = $this->getMockBuilder(FluidTemplateView::class)->setMethods(['renderSection'])->disableOriginalConstructor()->getMock();
575  $viewWithBothData->expects(self::exactly(2))->method('renderSection')
576  ->withConsecutive(
577  ['HeaderAssets', self::anything(), true],
578  ['FooterAssets', self::anything(), true]
579  )
580  ->willReturnOnConsecutiveCalls('custom-header-data', 'custom-footer-data');
581  $invalidView = $this->getMockBuilder(AbstractTemplateView::class)->disableOriginalConstructor()->getMockForAbstractClass();
582  return [
583  [$viewWithHeaderData, 'custom-header-data', null],
584  [$viewWithFooterData, null, 'custom-footer-data'],
585  [$viewWithBothData, 'custom-header-data', 'custom-footer-data'],
586  [$invalidView, null, null]
587  ];
588  }
589 }
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest\setViewConfigurationResolvesLayoutRootPathsForLayoutRootPath
‪setViewConfigurationResolvesLayoutRootPathsForLayoutRootPath($configuration, $expected)
Definition: ActionControllerTest.php:369
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller
Definition: ActionControllerTest.php:18
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest\$mockObjectManager
‪TYPO3 CMS Extbase Object ObjectManagerInterface $mockObjectManager
Definition: ActionControllerTest.php:53
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest\$mockUriBuilder
‪TYPO3 CMS Extbase Mvc Web Routing UriBuilder $mockUriBuilder
Definition: ActionControllerTest.php:57
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest\layoutRootPathDataProvider
‪array layoutRootPathDataProvider()
Definition: ActionControllerTest.php:388
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest\$mockMvcPropertyMappingConfigurationService
‪TYPO3 CMS Extbase Mvc Controller MvcPropertyMappingConfigurationService $mockMvcPropertyMappingConfigurationService
Definition: ActionControllerTest.php:61
‪TYPO3\CMS\Extbase\Mvc\Controller\Arguments
Definition: Arguments.php:27
‪TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentTypeException
Definition: InvalidArgumentTypeException.php:26
‪TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
Definition: ConfigurationManagerInterface.php:28
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest\setViewConfigurationResolvesPartialRootPathsForPartialRootPath
‪setViewConfigurationResolvesPartialRootPathsForPartialRootPath($configuration, $expected)
Definition: ActionControllerTest.php:447
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest\$actionController
‪TYPO3 CMS Extbase Mvc Controller ActionController PHPUnit Framework MockObject MockObject TYPO3 TestingFramework Core AccessibleObjectInterface $actionController
Definition: ActionControllerTest.php:49
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest\headerAssetDataProvider
‪array headerAssetDataProvider()
Definition: ActionControllerTest.php:553
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest\templateRootPathDataProvider
‪array templateRootPathDataProvider()
Definition: ActionControllerTest.php:310
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest\setViewConfigurationResolvesTemplateRootPathsForTemplateRootPath
‪setViewConfigurationResolvesTemplateRootPathsForTemplateRootPath($configuration, $expected)
Definition: ActionControllerTest.php:291
‪TYPO3\CMS\Extbase\Reflection\ReflectionService
Definition: ReflectionService.php:31
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest\rendersAndAssignsAssetsFromViewIntoPageRenderer
‪rendersAndAssignsAssetsFromViewIntoPageRenderer($viewMock, $expectedHeader, $expectedFooter)
Definition: ActionControllerTest.php:525
‪TYPO3\CMS\Core\Page\PageRenderer
Definition: PageRenderer.php:42
‪TYPO3\CMS\Extbase\Reflection\ClassSchema
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest\partialRootPathDataProvider
‪array partialRootPathDataProvider()
Definition: ActionControllerTest.php:466
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest\$resetSingletonInstances
‪bool $resetSingletonInstances
Definition: ActionControllerTest.php:45
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest\resolveActionMethodNameReturnsTheCurrentActionMethodNameFromTheRequest
‪resolveActionMethodNameReturnsTheCurrentActionMethodNameFromTheRequest()
Definition: ActionControllerTest.php:66
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest\resolveActionMethodNameThrowsAnExceptionIfTheActionDefinedInTheRequestDoesNotExist
‪resolveActionMethodNameThrowsAnExceptionIfTheActionDefinedInTheRequestDoesNotExist()
Definition: ActionControllerTest.php:79
‪TYPO3\CMS\Extbase\Mvc\View\ViewInterface
Definition: ViewInterface.php:24
‪TYPO3\CMS\Extbase\Reflection\ClassSchema\Method
Definition: Method.php:27
‪TYPO3\CMS\Extbase\Mvc\RequestInterface
Definition: RequestInterface.php:22
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest\initializeActionMethodArgumentsRegistersArgumentsFoundInTheSignatureOfTheCurrentActionMethod
‪initializeActionMethodArgumentsRegistersArgumentsFoundInTheSignatureOfTheCurrentActionMethod()
Definition: ActionControllerTest.php:96
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest\initializeActionMethodArgumentsThrowsExceptionIfDataTypeWasNotSpecified
‪initializeActionMethodArgumentsThrowsExceptionIfDataTypeWasNotSpecified()
Definition: ActionControllerTest.php:241
‪TYPO3\CMS\Extbase\Mvc\Controller\ActionController
Definition: ActionController.php:55
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest
Definition: ActionControllerTest.php:42
‪TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller\ActionControllerTest\initializeActionMethodArgumentsRegistersOptionalArgumentsAsSuch
‪initializeActionMethodArgumentsRegistersOptionalArgumentsAsSuch()
Definition: ActionControllerTest.php:169
‪TYPO3\CMS\Extbase\Mvc\Exception\NoSuchActionException
Definition: NoSuchActionException.php:26
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Extbase\Mvc\Request
Definition: Request.php:31