[FOLLOWUP][BUGFIX] Only write out one shortcut tag
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Functional / Page / PageRendererTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Functional\Page;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 /**
18 * Test case
19 */
20 class PageRendererTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
21
22 /**
23 * @test
24 */
25 public function pageRendererRendersInsertsMainContentStringsInOutput() {
26 $subject = new \TYPO3\CMS\Core\Page\PageRenderer();
27 $subject->setCharSet('utf-8');
28 $subject->setLanguage('default');
29
30 $prologueString = $expectedPrologueString = '<?xml version="1.0" encoding="utf-8" ?>';
31 $subject->setXmlPrologAndDocType($prologueString);
32
33 $title = $this->getUniqueId('aTitle-');
34 $subject->setTitle($title);
35 $expectedTitleString = '<title>' . $title . '</title>';
36
37 $charset = 'utf-8';
38 $subject->setCharSet($charset);
39 $expectedCharsetString = '<meta http-equiv="Content-Type" content="text/html; charset=' . $charset . '" />';
40
41 $favouriteIcon = 'http://google.com/favicon.ico';
42 $subject->setFavIcon($favouriteIcon);
43 $expectedFavouriteIconPartOne = '<link rel="shortcut icon" href="' . $favouriteIcon . '" />';
44
45 $baseUrl = 'http://google.com/';
46 $subject->setBaseUrl($baseUrl);
47 $expectedBaseUrlString = '<base href="' . $baseUrl . '" />';
48
49 $metaTag = $expectedMetaTagString = '<meta name="author" content="Anna Lyse">';
50 $subject->addMetaTag($metaTag);
51
52 $inlineComment = $this->getUniqueId('comment');
53 $subject->addInlineComment($inlineComment);
54 $expectedInlineCommentString = '<!-- ' . LF . $inlineComment . '-->';
55
56 $headerData = $expectedHeaderData = '<tag method="private" name="test" />';
57 $subject->addHeaderData($headerData);
58
59 $subject->addJsLibrary('test', 'fileadmin/test.js', 'text/javascript', FALSE, FALSE, 'wrapBeforeXwrapAfter', FALSE, 'X');
60 $expectedJsLibraryRegExp = '#wrapBefore<script src="fileadmin/test\\.(js|\\d+\\.js|js\\?\\d+)" type="text/javascript"></script>wrapAfter#';
61
62 $subject->addJsFile('fileadmin/test.js', 'text/javascript', FALSE, FALSE, 'wrapBeforeXwrapAfter', FALSE, 'X');
63 $expectedJsFileRegExp = '#wrapBefore<script src="fileadmin/test\\.(js|\\d+\\.js|js\\?\\d+)" type="text/javascript"></script>wrapAfter#';
64
65 $jsInlineCode = $expectedJsInlineCodeString = 'var x = "' . $this->getUniqueId('jsInline-') . '"';
66 $subject->addJsInlineCode($this->getUniqueId(), $jsInlineCode);
67
68 $extOnReadyCode = $expectedExtOnReadyCodePartOne = $this->getUniqueId('extOnReady-');
69 $expectedExtOnReadyCodePartTwo = 'Ext.onReady(function() {';
70 $subject->loadExtJS();
71 $subject->addExtOnReadyCode($extOnReadyCode);
72
73 $cssFile = $this->getUniqueId('cssFile-');
74 $expectedCssFileString = 'wrapBefore<link rel="stylesheet" type="text/css" href="' . $cssFile . '" media="print" />wrapAfter';
75 $subject->addCssFile($cssFile, 'stylesheet', 'print', '', TRUE, FALSE, 'wrapBeforeXwrapAfter', FALSE, 'X');
76
77 $expectedCssInlineBlockOnTopString = '/*general3*/' . LF . 'h1 {margin:20px;}' . LF . '/*general2*/' . LF . 'body {margin:20px;}';
78 $subject->addCssInlineBlock('general2', 'body {margin:20px;}');
79 $subject->addCssInlineBlock('general3', 'h1 {margin:20px;}', NULL, TRUE);
80
81 $expectedLoadPrototypeRegExp = '#<script src="contrib/prototype/prototype\\.(js|\\d+\\.js|js\\?\\d+)" type="text/javascript"></script>#';
82 $subject->loadPrototype();
83
84 $subject->loadScriptaculous('slider,controls');
85 $expectedScriptaculousMain = '<script src="contrib/scriptaculous/scriptaculous.js" type="text/javascript"></script>';
86 $expectedScriptaculousEffects = '<script src="contrib/scriptaculous/effects.js" type="text/javascript"></script>';
87 $expectedScriptaculousControls = '<script src="contrib/scriptaculous/controls.js" type="text/javascript"></script>';
88 $expectedScriptaculousSlider = '<script src="contrib/scriptaculous/slider.js" type="text/javascript"></script>';
89
90 $subject->loadJquery();
91 $expectedJqueryRegExp = '#<script src="contrib/jquery/jquery-' . \TYPO3\CMS\Core\Page\PageRenderer::JQUERY_VERSION_LATEST . '\\.min\\.(js|\\d+\\.js|js\\?\\d+)" type="text/javascript"></script>#';
92 $expectedJqueryStatement = 'var TYPO3 = TYPO3 || {}; TYPO3.jQuery = jQuery.noConflict(true);';
93
94 $subject->loadExtJS(TRUE, TRUE, 'jquery');
95 $expectedExtJsRegExp = '#<script src="contrib/extjs/adapter/jquery/ext-jquery-adapter\\.(js|\\d+\\.js|js\\?\\d+)" type="text/javascript"></script>' . LF . '<script src="contrib/extjs/ext-all\\.(js|\\d+\\.js|js\\?\\d+)" type="text/javascript"></script>#m';
96
97 $expectedBodyContent = $this->getUniqueId('ABCDE-');
98 $subject->setBodyContent($expectedBodyContent);
99
100 $renderedString = $subject->render();
101
102 $this->assertContains($expectedPrologueString, $renderedString);
103 $this->assertContains($expectedTitleString, $renderedString);
104 $this->assertContains($expectedCharsetString, $renderedString);
105 $this->assertContains($expectedFavouriteIconPartOne, $renderedString);
106 $this->assertContains($expectedBaseUrlString, $renderedString);
107 $this->assertContains($expectedMetaTagString, $renderedString);
108 $this->assertContains($expectedInlineCommentString, $renderedString);
109 $this->assertContains($expectedHeaderData, $renderedString);
110 $this->assertRegExp($expectedJsLibraryRegExp, $renderedString);
111 $this->assertRegExp($expectedJsFileRegExp, $renderedString);
112 $this->assertContains($expectedJsInlineCodeString, $renderedString);
113 $this->assertContains($expectedExtOnReadyCodePartOne, $renderedString);
114 $this->assertContains($expectedExtOnReadyCodePartTwo, $renderedString);
115 $this->assertContains($expectedCssFileString, $renderedString);
116 $this->assertContains($expectedCssInlineBlockOnTopString, $renderedString);
117 $this->assertRegExp($expectedLoadPrototypeRegExp, $renderedString);
118 $this->assertContains($expectedScriptaculousMain, $renderedString);
119 $this->assertContains($expectedScriptaculousEffects, $renderedString);
120 $this->assertContains($expectedScriptaculousControls, $renderedString);
121 $this->assertContains($expectedScriptaculousSlider, $renderedString);
122 $this->assertRegExp($expectedJqueryRegExp, $renderedString);
123 $this->assertContains($expectedJqueryStatement, $renderedString);
124 $this->assertRegExp($expectedExtJsRegExp, $renderedString);
125 $this->assertContains($expectedBodyContent, $renderedString);
126 }
127
128 /**
129 * @test
130 */
131 public function pageRendererRendersFooterValues() {
132 $subject = new \TYPO3\CMS\Core\Page\PageRenderer();
133 $subject->setCharSet('utf-8');
134 $subject->setLanguage('default');
135
136 $subject->enableMoveJsFromHeaderToFooter();
137
138 $footerData = $expectedFooterData = '<tag method="private" name="test" />';
139 $subject->addFooterData($footerData);
140
141 $expectedJsFooterLibraryRegExp = '#wrapBefore<script src="fileadmin/test\\.(js|\\d+\\.js|js\\?\\d+)" type="text/javascript"></script>wrapAfter#';
142 $subject->addJsFooterLibrary('test', 'fileadmin/test.js', 'text/javascript', FALSE, FALSE, 'wrapBeforeXwrapAfter', FALSE, 'X');
143
144 $expectedJsFooterRegExp = '#wrapBefore<script src="fileadmin/test\\.(js|\\d+\\.js|js\\?\\d+)" type="text/javascript"></script>wrapAfter#';
145 $subject->addJsFooterFile('fileadmin/test.js', 'text/javascript', FALSE, FALSE, 'wrapBeforeXwrapAfter', FALSE, 'X');
146
147 $jsFooterInlineCode = $expectedJsFooterInlineCodeString = 'var x = "' . $this->getUniqueId('jsFooterInline-') . '"';
148 $subject->addJsFooterInlineCode($this->getUniqueId(), $jsFooterInlineCode);
149
150 // Bunch of label tests
151 $subject->loadExtJS();
152 $subject->addInlineLanguageLabel('myKey', 'myValue');
153 $subject->addInlineLanguageLabelArray(array(
154 'myKeyArray1' => 'myValueArray1',
155 'myKeyArray2' => 'myValueArray2'
156 ));
157 $subject->addInlineLanguageLabelArray(array(
158 'myKeyArray3' => 'myValueArray3'
159 ));
160 $expectedInlineLabelReturnValue = 'TYPO3.lang = {"myKey":"myValue","myKeyArray1":"myValueArray1","myKeyArray2":"myValueArray2","myKeyArray3":"myValueArray3"';
161
162 $subject->addInlineLanguageLabelFile('EXT:lang/locallang_core.xlf');
163 $expectedLanguageLabel1 = 'labels.beUser';
164 $expectedLanguageLabel2 = 'labels.feUser';
165
166 // Bunch of inline settings test
167 $subject->addInlineSetting('myApp', 'myKey', 'myValue');
168 $subject->addInlineSettingArray('myApp', array(
169 'myKey1' => 'myValue1',
170 'myKey2' => 'myValue2'
171 ));
172 $subject->addInlineSettingArray('myApp', array(
173 'myKey3' => 'myValue3'
174 ));
175 $expectedInlineSettingsReturnValue = 'TYPO3.settings = {"myApp":{"myKey":"myValue","myKey1":"myValue1","myKey2":"myValue2","myKey3":"myValue3"}';
176
177 $renderedString = $subject->render(\TYPO3\CMS\Core\Page\PageRenderer::PART_FOOTER);
178
179 $this->assertContains($expectedFooterData, $renderedString);
180 $this->assertRegExp($expectedJsFooterLibraryRegExp, $renderedString);
181 $this->assertRegExp($expectedJsFooterRegExp, $renderedString);
182 $this->assertContains($expectedJsFooterInlineCodeString, $renderedString);
183 $this->assertContains($expectedInlineLabelReturnValue, $renderedString);
184 $this->assertContains($expectedLanguageLabel1, $renderedString);
185 $this->assertContains($expectedLanguageLabel2, $renderedString);
186 $this->assertContains($expectedInlineSettingsReturnValue, $renderedString);
187 }
188
189 /**
190 * @test
191 */
192 public function isScriptaculousLoadedCompressedIfConfiguredAndClientIsCapable() {
193 $subject = new \TYPO3\CMS\Core\Page\PageRenderer();
194
195 $_SERVER['HTTP_ACCEPT_ENCODING'] = 'gzip,deflate';
196 $GLOBALS['TYPO3_CONF_VARS']['BE']['compressionLevel'] = '5';
197 $subject->loadScriptaculous('slider,controls');
198 $subject->enableCompressJavascript();
199 $out = $subject->render();
200 $this->assertRegExp('#<script src="[^"]*/typo3temp/compressor/scriptaculous-[a-f0-9]+.js.gzip" type="text/javascript"></script>#', $out);
201 $this->assertRegExp('#<script src="[^"]*/typo3temp/compressor/effects-[a-f0-9]+.js.gzip" type="text/javascript"></script>#', $out);
202 $this->assertRegExp('#<script src="[^"]*/typo3temp/compressor/controls-[a-f0-9]+.js.gzip" type="text/javascript"></script>#', $out);
203 $this->assertRegExp('#<script src="[^"]*/typo3temp/compressor/slider-[a-f0-9]+.js.gzip" type="text/javascript"></script>#', $out);
204 }
205
206 /**
207 * @test
208 */
209 public function isScriptaculousNotLoadedCompressedIfClientCannotHandleCompression() {
210 $subject = new \TYPO3\CMS\Core\Page\PageRenderer();
211
212 $_SERVER['HTTP_ACCEPT_ENCODING'] = '';
213 $GLOBALS['TYPO3_CONF_VARS']['BE']['compressionLevel'] = '5';
214 $subject->loadScriptaculous('slider,controls');
215 $subject->enableCompressJavascript();
216 $out = $subject->render();
217 $this->assertRegExp('#<script src="[^"]*/typo3temp/compressor/scriptaculous-[a-f0-9]+.js" type="text/javascript"></script>#', $out);
218 $this->assertRegExp('#<script src="[^"]*/typo3temp/compressor/effects-[a-f0-9]+.js" type="text/javascript"></script>#', $out);
219 $this->assertRegExp('#<script src="[^"]*/typo3temp/compressor/controls-[a-f0-9]+.js" type="text/javascript"></script>#', $out);
220 $this->assertRegExp('#<script src="[^"]*/typo3temp/compressor/slider-[a-f0-9]+.js" type="text/javascript"></script>#', $out);
221 }
222
223 /**
224 * @test
225 */
226 public function isScriptaculousNotLoadedCompressedIfCompressionIsNotConfigured() {
227 $subject = new \TYPO3\CMS\Core\Page\PageRenderer();
228
229 $_SERVER['HTTP_ACCEPT_ENCODING'] = 'gzip,deflate';
230 $GLOBALS['TYPO3_CONF_VARS']['BE']['compressionLevel'] = '';
231 $subject->loadScriptaculous('slider,controls');
232 $subject->enableCompressJavascript();
233 $out = $subject->render();
234 $this->assertRegExp('#<script src="[^"]*/typo3temp/compressor/scriptaculous-[a-f0-9]+.js" type="text/javascript"></script>#', $out);
235 $this->assertRegExp('#<script src="[^"]*/typo3temp/compressor/effects-[a-f0-9]+.js" type="text/javascript"></script>#', $out);
236 $this->assertRegExp('#<script src="[^"]*/typo3temp/compressor/controls-[a-f0-9]+.js" type="text/javascript"></script>#', $out);
237 $this->assertRegExp('#<script src="[^"]*/typo3temp/compressor/slider-[a-f0-9]+.js" type="text/javascript"></script>#', $out);
238 }
239
240 /**
241 * @test
242 */
243 public function loadJqueryRespectsGivenNamespace() {
244 $subject = new \TYPO3\CMS\Core\Page\PageRenderer();
245
246 $expectedRegExp = '#<script src="contrib/jquery/jquery-' . \TYPO3\CMS\Core\Page\PageRenderer::JQUERY_VERSION_LATEST . '\\.min\\.(js|\\d+\\.js|js\\?\\d+)" type="text/javascript"></script>#';
247 $expectedStatement = 'var TYPO3 = TYPO3 || {}; TYPO3.MyNameSpace = jQuery.noConflict(true);';
248 $subject->loadJquery(NULL, NULL, 'MyNameSpace');
249 $out = $subject->render();
250 $this->assertRegExp($expectedRegExp, $out);
251 $this->assertContains($expectedStatement, $out);
252 }
253
254 /**
255 * @test
256 */
257 public function loadJqueryWithDefaultNoConflictModeDoesNotSetNamespace() {
258 $subject = new \TYPO3\CMS\Core\Page\PageRenderer();
259
260 $expectedRegExp = '#<script src="contrib/jquery/jquery-' . \TYPO3\CMS\Core\Page\PageRenderer::JQUERY_VERSION_LATEST . '\\.min\\.(js|\\d+\\.js|js\\?\\d+)" type="text/javascript"></script>#';
261 $expectedStatement = 'jQuery.noConflict();';
262 $subject->loadJquery(NULL, NULL, \TYPO3\CMS\Core\Page\PageRenderer::JQUERY_NAMESPACE_DEFAULT_NOCONFLICT);
263 $out = $subject->render();
264 $this->assertRegExp($expectedRegExp, $out);
265 $this->assertContains($expectedStatement, $out);
266 $this->assertNotContains('var TYPO3 = TYPO3 || {}; TYPO3.', $out);
267 }
268
269 /**
270 * @test
271 */
272 public function loadJqueryWithNamespaceNoneDoesNotIncludeNoConflictHandling() {
273 $subject = new \TYPO3\CMS\Core\Page\PageRenderer();
274
275 $expectedRegExp = '#<script src="contrib/jquery/jquery-' . \TYPO3\CMS\Core\Page\PageRenderer::JQUERY_VERSION_LATEST . '\\.min\\.(js|\\d+\\.js|js\\?\\d+)" type="text/javascript"></script>#';
276 $subject->loadJquery(NULL, NULL, \TYPO3\CMS\Core\Page\PageRenderer::JQUERY_NAMESPACE_NONE);
277 $out = $subject->render();
278 $this->assertRegExp($expectedRegExp, $out);
279 $this->assertNotContains('jQuery.noConflict', $out);
280 }
281
282 /**
283 * @test
284 */
285 public function loadJqueryLoadsTheLatestJqueryVersionInNoConflictModeUncompressedInDebugMode() {
286 $subject = new \TYPO3\CMS\Core\Page\PageRenderer();
287
288 $expectedRegExp = '#<script src="contrib/jquery/jquery-' . \TYPO3\CMS\Core\Page\PageRenderer::JQUERY_VERSION_LATEST . '\\.(js|\\d+\\.js|js\\?\\d+)" type="text/javascript"></script>#';
289 $expectedStatement = 'var TYPO3 = TYPO3 || {}; TYPO3.jQuery = jQuery.noConflict(true);';
290 $subject->loadJquery();
291 $subject->enableDebugMode();
292 $out = $subject->render();
293 $this->assertRegExp($expectedRegExp, $out);
294 $this->assertContains($expectedStatement, $out);
295 }
296
297 /**
298 * @return array
299 */
300 public function loadJqueryFromSourceDataProvider() {
301 return array(
302 'google with version number' => array(
303 '1.6.3',
304 'google',
305 '#<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.js" type="text/javascript"></script>#'
306 ),
307 'msn with version number' => array(
308 '1.6.3',
309 'msn',
310 '#<script src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.3.js" type="text/javascript"></script>#'
311 ),
312 'jquery with version number' => array(
313 '1.6.3',
314 'jquery',
315 '#<script src="http://code.jquery.com/jquery-1.6.3.js" type="text/javascript"></script>#'
316 ),
317 'jquery with custom URL' => array(
318 '1.6.3',
319 'http://my.cool.cdn/foo/jquery.js',
320 '#<script src="http://my.cool.cdn/foo/jquery.js" type="text/javascript"></script>#'
321 ),
322 );
323 }
324
325 /**
326 * @dataProvider loadJqueryFromSourceDataProvider
327 * @test
328 */
329 public function isJqueryLoadedFromSourceUncompressedIfDebugModeIsEnabled($version, $source, $regex) {
330 $subject = new \TYPO3\CMS\Core\Page\PageRenderer();
331
332 $subject->loadJquery($version, $source);
333 $subject->enableDebugMode();
334 $out = $subject->render();
335 $this->assertRegExp($regex, $out);
336 }
337
338 /**
339 * @test
340 */
341 public function isJqueryLoadedMinifiedFromGoogleByDefault() {
342 $subject = new \TYPO3\CMS\Core\Page\PageRenderer();
343
344 $expectedRegex = '#<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js" type="text/javascript"></script>#';
345 $subject->loadJquery('1.6.3', 'google');
346 $out = $subject->render();
347 $this->assertRegExp($expectedRegex, $out);
348 }
349
350 /**
351 * @test
352 */
353 public function loadExtJsInDebugLoadsDebugExtJs() {
354 $subject = new \TYPO3\CMS\Core\Page\PageRenderer();
355
356 $expectedRegExp = '#<script src="contrib/extjs/ext-all-debug\\.(js|\\d+\\.js|js\\?\\d+)" type="text/javascript"></script>#';
357 $subject->loadExtJS(TRUE, TRUE, 'jquery');
358 $subject->enableExtJsDebug();
359 $out = $subject->render();
360 $this->assertRegExp($expectedRegExp, $out);
361 }
362
363 /**
364 * @test
365 */
366 public function loadExtCoreLoadsExtCore() {
367 $subject = new \TYPO3\CMS\Core\Page\PageRenderer();
368
369 $expectedRegExp = '#<script src="contrib/extjs/ext-core\\.(js|\\d+\\.js|js\\?\\d+)" type="text/javascript"></script>#';
370 $subject->loadExtCore();
371 $out = $subject->render();
372 $this->assertRegExp($expectedRegExp, $out);
373 }
374
375 /**
376 * @test
377 */
378 public function loadExtCoreInDebugLoadsDebugExtCore() {
379 $subject = new \TYPO3\CMS\Core\Page\PageRenderer();
380
381 $expectedRegExp = '#<script src="contrib/extjs/ext-core-debug\\.(js|\\d+\\.js|js\\?\\d+)" type="text/javascript"></script>#';
382 $subject->loadExtCore();
383 $subject->enableExtCoreDebug();
384 $out = $subject->render();
385 $this->assertRegExp($expectedRegExp, $out);
386 }
387
388 }