[TASK] typo3/testing-framework now flushes runtime caches
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Tests / Unit / Controller / TypoScriptFrontendControllerTest.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Frontend\Tests\Unit\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\Context\Context;
19 use TYPO3\CMS\Core\Http\ServerRequestFactory;
20 use TYPO3\CMS\Core\Page\PageRenderer;
21 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
22 use TYPO3\CMS\Frontend\Page\PageRepository;
23 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
24
25 /**
26 * Test case
27 */
28 class TypoScriptFrontendControllerTest extends UnitTestCase
29 {
30 /**
31 * @var bool Reset singletons created by subject
32 */
33 protected $resetSingletonInstances = true;
34
35 /**
36 * @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface|TypoScriptFrontendController
37 */
38 protected $subject;
39
40 protected function setUp()
41 {
42 $this->subject = $this->getAccessibleMock(TypoScriptFrontendController::class, ['dummy'], [], '', false);
43 $this->subject->_set('context', new Context());
44 $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] = '170928423746123078941623042360abceb12341234231';
45
46 $pageRepository = $this->getMockBuilder(PageRepository::class)->getMock();
47 $this->subject->sys_page = $pageRepository;
48
49 $pageRenderer = $this->getMockBuilder(PageRenderer::class)->getMock();
50 $this->subject->_set('pageRenderer', $pageRenderer);
51 }
52
53 /**
54 * Tests concerning rendering content
55 */
56
57 /**
58 * @test
59 */
60 public function headerAndFooterMarkersAreReplacedDuringIntProcessing()
61 {
62 $GLOBALS['TSFE'] = $this->setupTsfeMockForHeaderFooterReplacementCheck();
63 $GLOBALS['TSFE']->INTincScript();
64 $this->assertContains('headerData', $GLOBALS['TSFE']->content);
65 $this->assertContains('footerData', $GLOBALS['TSFE']->content);
66 }
67
68 /**
69 * This is the callback that mimics a USER_INT extension
70 */
71 public function INTincScript_processCallback()
72 {
73 $GLOBALS['TSFE']->additionalHeaderData[] = 'headerData';
74 $GLOBALS['TSFE']->additionalFooterData[] = 'footerData';
75 }
76
77 /**
78 * Setup a \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController object only for testing the header and footer
79 * replacement during USER_INT rendering
80 *
81 * @return \PHPUnit_Framework_MockObject_MockObject|TypoScriptFrontendController
82 */
83 protected function setupTsfeMockForHeaderFooterReplacementCheck()
84 {
85 /** @var \PHPUnit_Framework_MockObject_MockObject|TypoScriptFrontendController $tsfe */
86 $tsfe = $this->getMockBuilder(TypoScriptFrontendController::class)
87 ->setMethods([
88 'INTincScript_process',
89 'INTincScript_loadJSCode',
90 'setAbsRefPrefix',
91 'regeneratePageTitle'
92 ])->disableOriginalConstructor()
93 ->getMock();
94 $tsfe->expects($this->exactly(2))->method('INTincScript_process')->will($this->returnCallback([$this, 'INTincScript_processCallback']));
95 $tsfe->content = file_get_contents(__DIR__ . '/Fixtures/renderedPage.html');
96 $config = [
97 'INTincScript_ext' => [
98 'divKey' => '679b52796e75d474ccbbed486b6837ab',
99 ],
100 'INTincScript' => [
101 'INT_SCRIPT.679b52796e75d474ccbbed486b6837ab' => [],
102 ]
103 ];
104 $tsfe->config = $config;
105
106 return $tsfe;
107 }
108
109 /**
110 * Tests concerning sL
111 */
112
113 /**
114 * @test
115 */
116 public function localizationReturnsUnchangedStringIfNotLocallangLabel()
117 {
118 $string = $this->getUniqueId();
119 $this->subject->page = [];
120 $this->subject->settingLanguage();
121 $this->assertEquals($string, $this->subject->sL($string));
122 }
123
124 /**
125 * Tests concerning getSysDomainCache
126 */
127
128 /**
129 * @return array
130 */
131 public function getSysDomainCacheDataProvider()
132 {
133 return [
134 'typo3.org' => [
135 'typo3.org',
136 ],
137 'foo.bar' => [
138 'foo.bar',
139 ],
140 'example.com' => [
141 'example.com',
142 ],
143 ];
144 }
145
146 /**
147 * @return array
148 */
149 public function baseUrlWrapHandlesDifferentUrlsDataProvider()
150 {
151 return [
152 'without base url' => [
153 '',
154 'fileadmin/user_uploads/image.jpg',
155 'fileadmin/user_uploads/image.jpg'
156 ],
157 'with base url' => [
158 'http://www.google.com/',
159 'fileadmin/user_uploads/image.jpg',
160 'http://www.google.com/fileadmin/user_uploads/image.jpg'
161 ],
162 'without base url but with url prepended with a forward slash' => [
163 '',
164 '/fileadmin/user_uploads/image.jpg',
165 '/fileadmin/user_uploads/image.jpg',
166 ],
167 'with base url but with url prepended with a forward slash' => [
168 'http://www.google.com/',
169 '/fileadmin/user_uploads/image.jpg',
170 '/fileadmin/user_uploads/image.jpg',
171 ],
172 ];
173 }
174
175 /**
176 * @dataProvider baseUrlWrapHandlesDifferentUrlsDataProvider
177 * @test
178 * @param string $baseUrl
179 * @param string $url
180 * @param string $expected
181 */
182 public function baseUrlWrapHandlesDifferentUrls($baseUrl, $url, $expected)
183 {
184 $this->subject->baseUrl = $baseUrl;
185 $this->assertSame($expected, $this->subject->baseUrlWrap($url));
186 }
187
188 /**
189 * @return array
190 */
191 public function initializeSearchWordDataBuildsCorrectRegexDataProvider()
192 {
193 return [
194 'one simple search word' => [
195 ['test'],
196 false,
197 'test',
198 ],
199 'one simple search word with standalone words' => [
200 ['test'],
201 true,
202 '[[:space:]]test[[:space:]]',
203 ],
204 'two simple search words' => [
205 ['test', 'test2'],
206 false,
207 'test|test2',
208 ],
209 'two simple search words with standalone words' => [
210 ['test', 'test2'],
211 true,
212 '[[:space:]]test[[:space:]]|[[:space:]]test2[[:space:]]',
213 ],
214 'word with regex chars' => [
215 ['A \\ word with / a bunch of [] regex () chars .*'],
216 false,
217 'A \\\\ word with \\/ a bunch of \\[\\] regex \\(\\) chars \\.\\*',
218 ],
219 ];
220 }
221
222 /**
223 * @test
224 * @dataProvider initializeSearchWordDataBuildsCorrectRegexDataProvider
225 *
226 * @param array $searchWordGetParameters The values that should be loaded in the sword_list GET parameter.
227 * @param bool $enableStandaloneSearchWords If TRUE the sword_standAlone option will be enabled.
228 * @param string $expectedRegex The expected regex after processing the search words.
229 */
230 public function initializeSearchWordDataBuildsCorrectRegex(array $searchWordGetParameters, $enableStandaloneSearchWords, $expectedRegex)
231 {
232 $_GET['sword_list'] = $searchWordGetParameters;
233 $_SERVER['HTTP_HOST'] = 'localhost';
234 $_SERVER['SCRIPT_NAME'] = '/index.php';
235
236 $this->subject->page = [];
237 if ($enableStandaloneSearchWords) {
238 $this->subject->config = ['config' => ['sword_standAlone' => 1]];
239 }
240
241 $request = ServerRequestFactory::fromGlobals();
242 $this->subject->preparePageContentGeneration($request);
243 $this->assertEquals($this->subject->sWordRegEx, $expectedRegex);
244 }
245
246 /**
247 * @test
248 * @dataProvider splitLinkVarsDataProvider
249 *
250 * @param $string
251 * @param $expected
252 */
253 public function splitLinkVarsStringSplitsStringByComma($string, $expected)
254 {
255 $this->assertEquals($expected, $this->subject->_callRef('splitLinkVarsString', $string));
256 }
257
258 /**
259 * @return array
260 */
261 public function splitLinkVarsDataProvider()
262 {
263 return [
264 [
265 'L',
266 ['L']
267 ],
268 [
269 'L,a',
270 [
271 'L',
272 'a'
273 ]
274 ],
275 [
276 'L, a',
277 [
278 'L',
279 'a'
280 ]
281 ],
282 [
283 'L , a',
284 [
285 'L',
286 'a'
287 ]
288 ],
289 [
290 ' L, a ',
291 [
292 'L',
293 'a'
294 ]
295 ],
296 [
297 'L(1)',
298 [
299 'L(1)'
300 ]
301 ],
302 [
303 'L(1),a',
304 [
305 'L(1)',
306 'a'
307 ]
308 ],
309 [
310 'L(1) , a',
311 [
312 'L(1)',
313 'a'
314 ]
315 ],
316 [
317 'a,L(1)',
318 [
319 'a',
320 'L(1)'
321 ]
322 ],
323 [
324 'L(1),a(2-3)',
325 [
326 'L(1)',
327 'a(2-3)'
328 ]
329 ],
330 [
331 'L(1),a((2-3))',
332 [
333 'L(1)',
334 'a((2-3))'
335 ]
336 ],
337 [
338 'L(1),a(a{2,4})',
339 [
340 'L(1)',
341 'a(a{2,4})'
342 ]
343 ],
344 [
345 'L(1),a(/a{2,4}\,()/)',
346 [
347 'L(1)',
348 'a(/a{2,4}\,()/)'
349 ]
350 ],
351 [
352 'L,a , b(c) , dd(/g{1,2}/), eee(, ()f) , 2',
353 [
354 'L',
355 'a',
356 'b(c)',
357 'dd(/g{1,2}/)',
358 'eee(, ()f)',
359 '2'
360 ]
361 ]
362 ];
363 }
364
365 /**
366 * @test
367 * @dataProvider calculateLinkVarsDataProvider
368 * @param string $linkVars
369 * @param array $getVars
370 * @param string $expected
371 */
372 public function calculateLinkVarsConsidersCorrectVariables(string $linkVars, array $getVars, string $expected)
373 {
374 $this->subject->config['config']['linkVars'] = $linkVars;
375 $this->subject->calculateLinkVars($getVars);
376 $this->assertEquals($expected, $this->subject->linkVars);
377 }
378
379 public function calculateLinkVarsDataProvider(): array
380 {
381 return [
382 'simple variable' => [
383 'L',
384 [
385 'L' => 1
386 ],
387 '&L=1'
388 ],
389 'missing variable' => [
390 'L',
391 [
392 ],
393 ''
394 ],
395 'restricted variables' => [
396 'L(1-3),bar(3),foo(array),blub(array)',
397 [
398 'L' => 1,
399 'bar' => 2,
400 'foo' => [ 1, 2, 'f' => [ 4, 5 ] ],
401 'blub' => 123
402 ],
403 '&L=1&foo[0]=1&foo[1]=2&foo[f][0]=4&foo[f][1]=5'
404 ],
405 'nested variables' => [
406 'bar|foo(1-2)',
407 [
408 'bar' => [
409 'foo' => 1,
410 'unused' => 'never'
411 ]
412 ],
413 '&bar[foo]=1'
414 ],
415 ];
416 }
417
418 /**
419 * @test
420 */
421 public function initializeSearchWordDataDoesNothingWithNullValue()
422 {
423 $subject = $this->getAccessibleMock(TypoScriptFrontendController::class, ['dummy'], [], '', false);
424 $subject->_call('initializeSearchWordData', null);
425 $this->assertEquals('', $subject->sWordRegEx);
426 $this->assertEquals('', $subject->sWordList);
427 }
428
429 /**
430 * @test
431 */
432 public function initializeSearchWordDataDoesNothingWithEmptyStringValue()
433 {
434 $subject = $this->getAccessibleMock(TypoScriptFrontendController::class, ['dummy'], [], '', false);
435 $subject->_call('initializeSearchWordData', '');
436 $this->assertEquals('', $subject->sWordRegEx);
437 $this->assertEquals('', $subject->sWordList);
438 }
439
440 /**
441 * @test
442 */
443 public function initializeSearchWordDataDoesNothingWithEmptyArrayValue()
444 {
445 $subject = $this->getAccessibleMock(TypoScriptFrontendController::class, ['dummy'], [], '', false);
446 $subject->_call('initializeSearchWordData', []);
447 $this->assertEquals('', $subject->sWordRegEx);
448 $this->assertEquals([], $subject->sWordList);
449 }
450
451 /**
452 * @test
453 */
454 public function initializeSearchWordDataFillsProperRegexpWithArray()
455 {
456 $subject = $this->getAccessibleMock(TypoScriptFrontendController::class, ['dummy'], [], '', false);
457 $subject->_call('initializeSearchWordData', ['stop', 'word']);
458 $this->assertEquals('stop|word', $subject->sWordRegEx);
459 $this->assertEquals(['stop', 'word'], $subject->sWordList);
460 }
461
462 /**
463 * @test
464 */
465 public function initializeSearchWordDataFillsProperRegexpWithArrayAndStandaloneOption()
466 {
467 $subject = $this->getAccessibleMock(TypoScriptFrontendController::class, ['dummy'], [], '', false);
468 $subject->config['config']['sword_standAlone'] = 1;
469 $subject->_call('initializeSearchWordData', ['stop', 'word']);
470 $this->assertEquals('[[:space:]]stop[[:space:]]|[[:space:]]word[[:space:]]', $subject->sWordRegEx);
471 $this->assertEquals(['stop', 'word'], $subject->sWordList);
472 }
473 }