[!!!][TASK] Remove support for non namespaced classes in Extbase
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Tests / Unit / Mvc / Controller / ActionControllerTest.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller;
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
18 use TYPO3\CMS\Core\Page\PageRenderer;
19 use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
20 use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
21 use TYPO3\CMS\Extbase\Mvc\Controller\Arguments;
22 use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext;
23 use TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentTypeException;
24 use TYPO3\CMS\Extbase\Mvc\Exception\NoSuchActionException;
25 use TYPO3\CMS\Extbase\Mvc\Request;
26 use TYPO3\CMS\Extbase\Mvc\RequestInterface;
27 use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
28 use TYPO3\CMS\Extbase\Object\ObjectManager;
29 use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
30 use TYPO3\CMS\Extbase\Reflection\ReflectionService;
31 use TYPO3\CMS\Fluid\View\TemplateView;
32 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
33 use TYPO3Fluid\Fluid\View\AbstractTemplateView;
34 use TYPO3Fluid\Fluid\View\TemplateView as FluidTemplateView;
35
36 /**
37 * Test case
38 */
39 class ActionControllerTest extends UnitTestCase
40 {
41 /**
42 * @var \TYPO3\CMS\Extbase\Mvc\Controller\ActionController|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface
43 */
44 protected $actionController;
45
46 /**
47 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
48 */
49 protected $mockObjectManager;
50
51 /**
52 * @var \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder
53 */
54 protected $mockUriBuilder;
55
56 /**
57 * @var \TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfigurationService
58 */
59 protected $mockMvcPropertyMappingConfigurationService;
60
61 /**
62 * @test
63 */
64 public function resolveViewUsesFluidTemplateViewIfTemplateIsAvailable()
65 {
66 $mockControllerContext = $this->createMock(ControllerContext::class);
67 $mockFluidTemplateView = $this->createMock(ViewInterface::class);
68 $mockFluidTemplateView->expects($this->once())->method('setControllerContext')->with($mockControllerContext);
69 $mockFluidTemplateView->expects($this->once())->method('canRender')->with($mockControllerContext)->will($this->returnValue(true));
70 $mockObjectManager = $this->createMock(ObjectManagerInterface::class);
71 $mockObjectManager->expects($this->at(0))->method('get')->with(TemplateView::class)->will($this->returnValue($mockFluidTemplateView));
72 $mockController = $this->getAccessibleMock(ActionController::class, ['buildControllerContext', 'resolveViewObjectName', 'setViewConfiguration'], [], '', false);
73 $mockController->expects($this->once())->method('resolveViewObjectName')->will($this->returnValue(false));
74 $mockController->_set('objectManager', $mockObjectManager);
75 $mockController->_set('controllerContext', $mockControllerContext);
76 $this->assertSame($mockFluidTemplateView, $mockController->_call('resolveView'));
77 }
78
79 /**
80 * @test
81 */
82 public function resolveViewObjectNameUsesViewObjectNamePatternToResolveViewObjectName()
83 {
84 $mockRequest = $this->createMock(Request::class);
85 $mockRequest->expects($this->once())->method('getControllerVendorName')->will($this->returnValue('MyVendor'));
86 $mockRequest->expects($this->once())->method('getControllerExtensionName')->will($this->returnValue('MyPackage'));
87 $mockRequest->expects($this->once())->method('getControllerName')->will($this->returnValue('MyController'));
88 $mockRequest->expects($this->once())->method('getControllerActionName')->will($this->returnValue('MyAction'));
89 $mockRequest->expects($this->atLeastOnce())->method('getFormat')->will($this->returnValue('MyFormat'));
90 $mockObjectManager = $this->createMock(ObjectManagerInterface::class);
91 $mockController = $this->getAccessibleMock(ActionController::class, ['dummy'], [], '', false);
92 $mockController->_set('request', $mockRequest);
93 $mockController->_set('objectManager', $mockObjectManager);
94 $mockController->_set('namespacesViewObjectNamePattern', 'RandomViewObject@vendor\@extension\View\@controller\@action@format');
95 $mockController->_call('resolveViewObjectName');
96 }
97
98 /**
99 * @test
100 */
101 public function resolveViewObjectNameUsesNamespacedViewObjectNamePatternForExtensionsWithVendor()
102 {
103 eval('namespace MyVendor\MyPackage\View\MyController; class MyActionMyFormat {}');
104
105 $mockRequest = $this->createMock(Request::class);
106 $mockRequest->expects($this->once())->method('getControllerExtensionName')->will($this->returnValue('MyPackage'));
107 $mockRequest->expects($this->once())->method('getControllerName')->will($this->returnValue('MyController'));
108 $mockRequest->expects($this->once())->method('getControllerActionName')->will($this->returnValue('MyAction'));
109 $mockRequest->expects($this->once())->method('getControllerVendorName')->will($this->returnValue('MyVendor'));
110 $mockRequest->expects($this->atLeastOnce())->method('getFormat')->will($this->returnValue('MyFormat'));
111 $mockObjectManager = $this->createMock(ObjectManagerInterface::class);
112 $mockController = $this->getAccessibleMock(ActionController::class, ['dummy'], [], '', false);
113 $mockController->_set('request', $mockRequest);
114 $mockController->_set('objectManager', $mockObjectManager);
115
116 $this->assertEquals(
117 'MyVendor\MyPackage\View\MyController\MyActionMyFormat',
118 $mockController->_call('resolveViewObjectName')
119 );
120 }
121
122 /**
123 * @test
124 */
125 public function resolveActionMethodNameReturnsTheCurrentActionMethodNameFromTheRequest()
126 {
127 $mockRequest = $this->createMock(Request::class);
128 $mockRequest->expects($this->once())->method('getControllerActionName')->will($this->returnValue('fooBar'));
129 /** @var \TYPO3\CMS\Extbase\Mvc\Controller\ActionController|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface */
130 $mockController = $this->getAccessibleMock(ActionController::class, ['fooBarAction'], [], '', false);
131 $mockController->_set('request', $mockRequest);
132 $this->assertEquals('fooBarAction', $mockController->_call('resolveActionMethodName'));
133 }
134
135 /**
136 * @test
137 */
138 public function resolveActionMethodNameThrowsAnExceptionIfTheActionDefinedInTheRequestDoesNotExist()
139 {
140 $this->expectException(NoSuchActionException::class);
141 $this->expectExceptionCode(1186669086);
142 $mockRequest = $this->createMock(Request::class);
143 $mockRequest->expects($this->once())->method('getControllerActionName')->will($this->returnValue('fooBar'));
144 /** @var \TYPO3\CMS\Extbase\Mvc\Controller\ActionController|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface */
145 $mockController = $this->getAccessibleMock(ActionController::class, ['otherBarAction'], [], '', false);
146 $mockController->_set('request', $mockRequest);
147 $mockController->_call('resolveActionMethodName');
148 }
149
150 /**
151 * @test
152 */
153 public function initializeActionMethodArgumentsRegistersArgumentsFoundInTheSignatureOfTheCurrentActionMethod()
154 {
155 $mockRequest = $this->createMock(Request::class);
156 $mockArguments = $this->getMockBuilder(Arguments::class)
157 ->setMethods(['addNewArgument', 'removeAll'])
158 ->getMock();
159 $mockArguments->expects($this->at(0))->method('addNewArgument')->with('stringArgument', 'string', true);
160 $mockArguments->expects($this->at(1))->method('addNewArgument')->with('integerArgument', 'integer', true);
161 $mockArguments->expects($this->at(2))->method('addNewArgument')->with('objectArgument', 'F3_Foo_Bar', true);
162 $mockController = $this->getAccessibleMock(ActionController::class, ['fooAction', 'evaluateDontValidateAnnotations'], [], '', false);
163 $methodParameters = [
164 'stringArgument' => [
165 'position' => 0,
166 'byReference' => false,
167 'array' => false,
168 'optional' => false,
169 'allowsNull' => false,
170 'type' => 'string',
171 'hasDefaultValue' => false
172 ],
173 'integerArgument' => [
174 'position' => 1,
175 'byReference' => false,
176 'array' => false,
177 'optional' => false,
178 'allowsNull' => false,
179 'type' => 'integer',
180 'hasDefaultValue' => false
181 ],
182 'objectArgument' => [
183 'position' => 2,
184 'byReference' => false,
185 'array' => false,
186 'optional' => false,
187 'allowsNull' => false,
188 'type' => 'F3_Foo_Bar',
189 'hasDefaultValue' => false
190 ]
191 ];
192 $mockReflectionService = $this->createMock(ReflectionService::class);
193 $mockReflectionService->expects($this->once())->method('getMethodParameters')->with(get_class($mockController), 'fooAction')->will($this->returnValue($methodParameters));
194 $mockController->_set('reflectionService', $mockReflectionService);
195 $mockController->_set('request', $mockRequest);
196 $mockController->_set('arguments', $mockArguments);
197 $mockController->_set('actionMethodName', 'fooAction');
198 $mockController->_call('initializeActionMethodArguments');
199 }
200
201 /**
202 * @test
203 */
204 public function initializeActionMethodArgumentsRegistersOptionalArgumentsAsSuch()
205 {
206 $mockRequest = $this->createMock(Request::class);
207 $mockArguments = $this->createMock(Arguments::class);
208 $mockArguments->expects($this->at(0))->method('addNewArgument')->with('arg1', 'string', true);
209 $mockArguments->expects($this->at(1))->method('addNewArgument')->with('arg2', 'array', false, [21]);
210 $mockArguments->expects($this->at(2))->method('addNewArgument')->with('arg3', 'string', false, 42);
211 $mockController = $this->getAccessibleMock(ActionController::class, ['fooAction', 'evaluateDontValidateAnnotations'], [], '', false);
212 $methodParameters = [
213 'arg1' => [
214 'position' => 0,
215 'byReference' => false,
216 'array' => false,
217 'optional' => false,
218 'allowsNull' => false,
219 'type' => 'string',
220 'hasDefaultValue' => false
221 ],
222 'arg2' => [
223 'position' => 1,
224 'byReference' => false,
225 'array' => true,
226 'optional' => true,
227 'defaultValue' => [21],
228 'allowsNull' => false,
229 'hasDefaultValue' => true
230 ],
231 'arg3' => [
232 'position' => 2,
233 'byReference' => false,
234 'array' => false,
235 'optional' => true,
236 'defaultValue' => 42,
237 'allowsNull' => false,
238 'type' => 'string',
239 'hasDefaultValue' => true
240 ]
241 ];
242 $mockReflectionService = $this->createMock(ReflectionService::class);
243 $mockReflectionService->expects($this->once())->method('getMethodParameters')->with(get_class($mockController), 'fooAction')->will($this->returnValue($methodParameters));
244 $mockController->_set('reflectionService', $mockReflectionService);
245 $mockController->_set('request', $mockRequest);
246 $mockController->_set('arguments', $mockArguments);
247 $mockController->_set('actionMethodName', 'fooAction');
248 $mockController->_call('initializeActionMethodArguments');
249 }
250
251 /**
252 * @test
253 */
254 public function initializeActionMethodArgumentsThrowsExceptionIfDataTypeWasNotSpecified()
255 {
256 $this->expectException(InvalidArgumentTypeException::class);
257 $this->expectExceptionCode(1253175643);
258 $mockRequest = $this->createMock(Request::class);
259 $mockArguments = $this->createMock(Arguments::class);
260 $mockController = $this->getAccessibleMock(ActionController::class, ['fooAction'], [], '', false);
261 $methodParameters = [
262 'arg1' => [
263 'position' => 0,
264 'byReference' => false,
265 'array' => false,
266 'optional' => false,
267 'allowsNull' => false
268 ]
269 ];
270 $mockReflectionService = $this->createMock(ReflectionService::class);
271 $mockReflectionService->expects($this->once())->method('getMethodParameters')->with(get_class($mockController), 'fooAction')->will($this->returnValue($methodParameters));
272 $mockController->_set('reflectionService', $mockReflectionService);
273 $mockController->_set('request', $mockRequest);
274 $mockController->_set('arguments', $mockArguments);
275 $mockController->_set('actionMethodName', 'fooAction');
276 $mockController->_call('initializeActionMethodArguments');
277 }
278
279 /**
280 * @test
281 * @dataProvider templateRootPathDataProvider
282 * @param array $configuration
283 * @param array $expected
284 */
285 public function setViewConfigurationResolvesTemplateRootPathsForTemplateRootPath($configuration, $expected)
286 {
287 /** @var ActionController|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface $mockController */
288 $mockController = $this->getAccessibleMock(ActionController::class, ['dummy'], [], '', false);
289 /** @var ConfigurationManagerInterface|\PHPUnit_Framework_MockObject_MockObject $mockConfigurationManager */
290 $mockConfigurationManager = $this->createMock(ConfigurationManagerInterface::class);
291 $mockConfigurationManager->expects($this->any())->method('getConfiguration')->will($this->returnValue($configuration));
292 $mockController->injectConfigurationManager($mockConfigurationManager);
293 $mockController->_set('request', $this->createMock(Request::class), ['getControllerExtensionKey']);
294 $view = $this->getMockBuilder(ViewInterface::class)
295 ->setMethods(['setControllerContext', 'assign', 'assignMultiple', 'canRender', 'render', 'initializeView', 'setTemplateRootPaths'])
296 ->getMock();
297 $view->expects($this->once())->method('setTemplateRootPaths')->with($expected);
298 $mockController->_call('setViewConfiguration', $view);
299 }
300
301 /**
302 * @return array
303 */
304 public function templateRootPathDataProvider()
305 {
306 return [
307 'text keys' => [
308 [
309 'view' => [
310 'templateRootPaths' => [
311 'default' => 'some path',
312 'extended' => 'some other path'
313 ]
314 ]
315 ],
316 [
317 'extended' => 'some other path',
318 'default' => 'some path'
319 ]
320 ],
321 'numerical keys' => [
322 [
323 'view' => [
324 'templateRootPaths' => [
325 '10' => 'some path',
326 '20' => 'some other path',
327 '15' => 'intermediate specific path'
328 ]
329 ]
330 ],
331 [
332 '20' => 'some other path',
333 '15' => 'intermediate specific path',
334 '10' => 'some path'
335 ]
336 ],
337 'mixed keys' => [
338 [
339 'view' => [
340 'templateRootPaths' => [
341 '10' => 'some path',
342 'very_specific' => 'some other path',
343 '15' => 'intermediate specific path'
344 ]
345 ]
346 ],
347 [
348 '15' => 'intermediate specific path',
349 'very_specific' => 'some other path',
350 '10' => 'some path'
351 ]
352 ],
353 ];
354 }
355
356 /**
357 * @test
358 * @dataProvider layoutRootPathDataProvider
359 *
360 * @param array $configuration
361 * @param array $expected
362 */
363 public function setViewConfigurationResolvesLayoutRootPathsForLayoutRootPath($configuration, $expected)
364 {
365 /** @var ActionController|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface $mockController */
366 $mockController = $this->getAccessibleMock(ActionController::class, ['dummy'], [], '', false);
367 /** @var ConfigurationManagerInterface|\PHPUnit_Framework_MockObject_MockObject $mockConfigurationManager */
368 $mockConfigurationManager = $this->createMock(ConfigurationManagerInterface::class);
369 $mockConfigurationManager->expects($this->any())->method('getConfiguration')->will($this->returnValue($configuration));
370 $mockController->injectConfigurationManager($mockConfigurationManager);
371 $mockController->_set('request', $this->createMock(Request::class), ['getControllerExtensionKey']);
372 $view = $this->getMockBuilder(ViewInterface::class)
373 ->setMethods(['setControllerContext', 'assign', 'assignMultiple', 'canRender', 'render', 'initializeView', 'setlayoutRootPaths'])
374 ->getMock();
375 $view->expects($this->once())->method('setlayoutRootPaths')->with($expected);
376 $mockController->_call('setViewConfiguration', $view);
377 }
378
379 /**
380 * @return array
381 */
382 public function layoutRootPathDataProvider()
383 {
384 return [
385 'text keys' => [
386 [
387 'view' => [
388 'layoutRootPaths' => [
389 'default' => 'some path',
390 'extended' => 'some other path'
391 ]
392 ]
393 ],
394 [
395 'extended' => 'some other path',
396 'default' => 'some path'
397 ]
398 ],
399 'numerical keys' => [
400 [
401 'view' => [
402 'layoutRootPaths' => [
403 '10' => 'some path',
404 '20' => 'some other path',
405 '15' => 'intermediate specific path'
406 ]
407 ]
408 ],
409 [
410 '20' => 'some other path',
411 '15' => 'intermediate specific path',
412 '10' => 'some path'
413 ]
414 ],
415 'mixed keys' => [
416 [
417 'view' => [
418 'layoutRootPaths' => [
419 '10' => 'some path',
420 'very_specific' => 'some other path',
421 '15' => 'intermediate specific path'
422 ]
423 ]
424 ],
425 [
426 '15' => 'intermediate specific path',
427 'very_specific' => 'some other path',
428 '10' => 'some path'
429 ]
430 ],
431 ];
432 }
433
434 /**
435 * @test
436 * @dataProvider partialRootPathDataProvider
437 *
438 * @param array $configuration
439 * @param array $expected
440 */
441 public function setViewConfigurationResolvesPartialRootPathsForPartialRootPath($configuration, $expected)
442 {
443 /** @var ActionController|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface $mockController */
444 $mockController = $this->getAccessibleMock(ActionController::class, ['dummy'], [], '', false);
445 /** @var ConfigurationManagerInterface|\PHPUnit_Framework_MockObject_MockObject $mockConfigurationManager */
446 $mockConfigurationManager = $this->createMock(ConfigurationManagerInterface::class);
447 $mockConfigurationManager->expects($this->any())->method('getConfiguration')->will($this->returnValue($configuration));
448 $mockController->injectConfigurationManager($mockConfigurationManager);
449 $mockController->_set('request', $this->createMock(Request::class), ['getControllerExtensionKey']);
450 $view = $this->getMockBuilder(ViewInterface::class)
451 ->setMethods(['setControllerContext', 'assign', 'assignMultiple', 'canRender', 'render', 'initializeView', 'setpartialRootPaths'])
452 ->getMock();
453 $view->expects($this->once())->method('setpartialRootPaths')->with($expected);
454 $mockController->_call('setViewConfiguration', $view);
455 }
456
457 /**
458 * @return array
459 */
460 public function partialRootPathDataProvider()
461 {
462 return [
463 'text keys' => [
464 [
465 'view' => [
466 'partialRootPaths' => [
467 'default' => 'some path',
468 'extended' => 'some other path'
469 ]
470 ]
471 ],
472 [
473 'extended' => 'some other path',
474 'default' => 'some path'
475 ]
476 ],
477 'numerical keys' => [
478 [
479 'view' => [
480 'partialRootPaths' => [
481 '10' => 'some path',
482 '20' => 'some other path',
483 '15' => 'intermediate specific path'
484 ]
485 ]
486 ],
487 [
488 '20' => 'some other path',
489 '15' => 'intermediate specific path',
490 '10' => 'some path'
491 ]
492 ],
493 'mixed keys' => [
494 [
495 'view' => [
496 'partialRootPaths' => [
497 '10' => 'some path',
498 'very_specific' => 'some other path',
499 '15' => 'intermediate specific path'
500 ]
501 ]
502 ],
503 [
504 '15' => 'intermediate specific path',
505 'very_specific' => 'some other path',
506 '10' => 'some path'
507 ]
508 ],
509 ];
510 }
511
512 /**
513 * @param FluidTemplateView $viewMock
514 * @param string|null $expectedHeader
515 * @param string|null $expectedFooter
516 * @test
517 * @dataProvider headerAssetDataProvider
518 */
519 public function rendersAndAssignsAssetsFromViewIntoPageRenderer($viewMock, $expectedHeader, $expectedFooter)
520 {
521 $this->mockObjectManager = $this->getMockBuilder(ObjectManager::class)->setMethods(['get'])->getMock();
522 $pageRendererMock = $this->getMockBuilder(PageRenderer::class)->setMethods(['addHeaderData', 'addFooterData'])->getMock();
523 if (!$viewMock instanceof FluidTemplateView) {
524 $this->mockObjectManager->expects($this->never())->method('get');
525 } else {
526 $this->mockObjectManager->expects($this->any())->method('get')->with(PageRenderer::class)->willReturn($pageRendererMock);
527 }
528 if (!empty(trim($expectedHeader ?? ''))) {
529 $pageRendererMock->expects($this->once())->method('addHeaderData')->with($expectedHeader);
530 } else {
531 $pageRendererMock->expects($this->never())->method('addHeaderData');
532 }
533 if (!empty(trim($expectedFooter ?? ''))) {
534 $pageRendererMock->expects($this->once())->method('addFooterData')->with($expectedFooter);
535 } else {
536 $pageRendererMock->expects($this->never())->method('addFooterData');
537 }
538 $requestMock = $this->getMockBuilder(RequestInterface::class)->getMockForAbstractClass();
539 $subject = new ActionController();
540 $viewProperty = new \ReflectionProperty($subject, 'view');
541 $viewProperty->setAccessible(true);
542 $viewProperty->setValue($subject, $viewMock);
543 $objectManagerProperty = new \ReflectionProperty($subject, 'objectManager');
544 $objectManagerProperty->setAccessible(true);
545 $objectManagerProperty->setValue($subject, $this->mockObjectManager);
546
547 $method = new \ReflectionMethod($subject, 'renderAssetsForRequest');
548 $method->setAccessible(true);
549 $method->invokeArgs($subject, [$requestMock]);
550 }
551
552 /**
553 * @return array
554 */
555 public function headerAssetDataProvider()
556 {
557 $viewWithHeaderData = $this->getMockBuilder(FluidTemplateView::class)->setMethods(['renderSection'])->disableOriginalConstructor()->getMock();
558 $viewWithHeaderData->expects($this->at(0))->method('renderSection')->with('HeaderAssets', $this->anything(), true)->willReturn('custom-header-data');
559 $viewWithHeaderData->expects($this->at(1))->method('renderSection')->with('FooterAssets', $this->anything(), true)->willReturn(null);
560 $viewWithFooterData = $this->getMockBuilder(FluidTemplateView::class)->setMethods(['renderSection'])->disableOriginalConstructor()->getMock();
561 $viewWithFooterData->expects($this->at(0))->method('renderSection')->with('HeaderAssets', $this->anything(), true)->willReturn(null);
562 $viewWithFooterData->expects($this->at(1))->method('renderSection')->with('FooterAssets', $this->anything(), true)->willReturn('custom-footer-data');
563 $viewWithBothData = $this->getMockBuilder(FluidTemplateView::class)->setMethods(['renderSection'])->disableOriginalConstructor()->getMock();
564 $viewWithBothData->expects($this->at(0))->method('renderSection')->with('HeaderAssets', $this->anything(), true)->willReturn('custom-header-data');
565 $viewWithBothData->expects($this->at(1))->method('renderSection')->with('FooterAssets', $this->anything(), true)->willReturn('custom-footer-data');
566 $invalidView = $this->getMockBuilder(AbstractTemplateView::class)->disableOriginalConstructor()->getMockForAbstractClass();
567 return [
568 [$viewWithHeaderData, 'custom-header-data', null],
569 [$viewWithFooterData, null, 'custom-footer-data'],
570 [$viewWithBothData, 'custom-header-data', 'custom-footer-data'],
571 [$invalidView, null, null]
572 ];
573 }
574 }