|
1 <?php |
|
2 |
|
3 /** |
|
4 * @file |
|
5 * Tests for the theme API. |
|
6 */ |
|
7 |
|
8 /** |
|
9 * Unit tests for the Theme API. |
|
10 */ |
|
11 class ThemeTestCase extends DrupalWebTestCase { |
|
12 protected $profile = 'testing'; |
|
13 |
|
14 public static function getInfo() { |
|
15 return array( |
|
16 'name' => 'Theme API', |
|
17 'description' => 'Test low-level theme functions.', |
|
18 'group' => 'Theme', |
|
19 ); |
|
20 } |
|
21 |
|
22 function setUp() { |
|
23 parent::setUp('theme_test'); |
|
24 theme_enable(array('test_theme')); |
|
25 } |
|
26 |
|
27 /** |
|
28 * Test function theme_get_suggestions() for SA-CORE-2009-003. |
|
29 */ |
|
30 function testThemeSuggestions() { |
|
31 // Set the front page as something random otherwise the CLI |
|
32 // test runner fails. |
|
33 variable_set('site_frontpage', 'nobody-home'); |
|
34 $args = array('node', '1', 'edit'); |
|
35 $suggestions = theme_get_suggestions($args, 'page'); |
|
36 $this->assertEqual($suggestions, array('page__node', 'page__node__%', 'page__node__1', 'page__node__edit'), 'Found expected node edit page suggestions'); |
|
37 // Check attack vectors. |
|
38 $args = array('node', '\\1'); |
|
39 $suggestions = theme_get_suggestions($args, 'page'); |
|
40 $this->assertEqual($suggestions, array('page__node', 'page__node__%', 'page__node__1'), 'Removed invalid \\ from suggestions'); |
|
41 $args = array('node', '1/'); |
|
42 $suggestions = theme_get_suggestions($args, 'page'); |
|
43 $this->assertEqual($suggestions, array('page__node', 'page__node__%', 'page__node__1'), 'Removed invalid / from suggestions'); |
|
44 $args = array('node', "1\0"); |
|
45 $suggestions = theme_get_suggestions($args, 'page'); |
|
46 $this->assertEqual($suggestions, array('page__node', 'page__node__%', 'page__node__1'), 'Removed invalid \\0 from suggestions'); |
|
47 // Define path with hyphens to be used to generate suggestions. |
|
48 $args = array('node', '1', 'hyphen-path'); |
|
49 $result = array('page__node', 'page__node__%', 'page__node__1', 'page__node__hyphen_path'); |
|
50 $suggestions = theme_get_suggestions($args, 'page'); |
|
51 $this->assertEqual($suggestions, $result, 'Found expected page suggestions for paths containing hyphens.'); |
|
52 } |
|
53 |
|
54 /** |
|
55 * Ensures preprocess functions run even for suggestion implementations. |
|
56 * |
|
57 * The theme hook used by this test has its base preprocess function in a |
|
58 * separate file, so this test also ensures that that file is correctly loaded |
|
59 * when needed. |
|
60 */ |
|
61 function testPreprocessForSuggestions() { |
|
62 // Test with both an unprimed and primed theme registry. |
|
63 drupal_theme_rebuild(); |
|
64 for ($i = 0; $i < 2; $i++) { |
|
65 $this->drupalGet('theme-test/suggestion'); |
|
66 $this->assertText('Theme hook implementor=test_theme_theme_test__suggestion(). Foo=template_preprocess_theme_test', 'Theme hook suggestion ran with data available from a preprocess function for the base hook.'); |
|
67 } |
|
68 } |
|
69 |
|
70 /** |
|
71 * Ensure page-front template suggestion is added when on front page. |
|
72 */ |
|
73 function testFrontPageThemeSuggestion() { |
|
74 $q = $_GET['q']; |
|
75 // Set $_GET['q'] to node because theme_get_suggestions() will query it to |
|
76 // see if we are on the front page. |
|
77 $_GET['q'] = variable_get('site_frontpage', 'node'); |
|
78 $suggestions = theme_get_suggestions(explode('/', $_GET['q']), 'page'); |
|
79 // Set it back to not annoy the batch runner. |
|
80 $_GET['q'] = $q; |
|
81 $this->assertTrue(in_array('page__front', $suggestions), 'Front page template was suggested.'); |
|
82 } |
|
83 |
|
84 /** |
|
85 * Ensures theme hook_*_alter() implementations can run before anything is rendered. |
|
86 */ |
|
87 function testAlter() { |
|
88 $this->drupalGet('theme-test/alter'); |
|
89 $this->assertText('The altered data is test_theme_theme_test_alter_alter was invoked.', 'The theme was able to implement an alter hook during page building before anything was rendered.'); |
|
90 } |
|
91 |
|
92 /** |
|
93 * Ensures a theme's .info file is able to override a module CSS file from being added to the page. |
|
94 * |
|
95 * @see test_theme.info |
|
96 */ |
|
97 function testCSSOverride() { |
|
98 // Reuse the same page as in testPreprocessForSuggestions(). We're testing |
|
99 // what is output to the HTML HEAD based on what is in a theme's .info file, |
|
100 // so it doesn't matter what page we get, as long as it is themed with the |
|
101 // test theme. First we test with CSS aggregation disabled. |
|
102 variable_set('preprocess_css', 0); |
|
103 $this->drupalGet('theme-test/suggestion'); |
|
104 $this->assertNoText('system.base.css', 'The theme\'s .info file is able to override a module CSS file from being added to the page.'); |
|
105 |
|
106 // Also test with aggregation enabled, simply ensuring no PHP errors are |
|
107 // triggered during drupal_build_css_cache() when a source file doesn't |
|
108 // exist. Then allow remaining tests to continue with aggregation disabled |
|
109 // by default. |
|
110 variable_set('preprocess_css', 1); |
|
111 $this->drupalGet('theme-test/suggestion'); |
|
112 variable_set('preprocess_css', 0); |
|
113 } |
|
114 |
|
115 /** |
|
116 * Ensures the theme registry is rebuilt when modules are disabled/enabled. |
|
117 */ |
|
118 function testRegistryRebuild() { |
|
119 $this->assertIdentical(theme('theme_test_foo', array('foo' => 'a')), 'a', 'The theme registry contains theme_test_foo.'); |
|
120 |
|
121 module_disable(array('theme_test'), FALSE); |
|
122 $this->assertIdentical(theme('theme_test_foo', array('foo' => 'b')), '', 'The theme registry does not contain theme_test_foo, because the module is disabled.'); |
|
123 |
|
124 module_enable(array('theme_test'), FALSE); |
|
125 $this->assertIdentical(theme('theme_test_foo', array('foo' => 'c')), 'c', 'The theme registry contains theme_test_foo again after re-enabling the module.'); |
|
126 } |
|
127 |
|
128 /** |
|
129 * Test the list_themes() function. |
|
130 */ |
|
131 function testListThemes() { |
|
132 $themes = list_themes(); |
|
133 // Check if drupal_theme_access() retrieves enabled themes properly from list_themes(). |
|
134 $this->assertTrue(drupal_theme_access('test_theme'), 'Enabled theme detected'); |
|
135 // Check if list_themes() returns disabled themes. |
|
136 $this->assertTrue(array_key_exists('test_basetheme', $themes), 'Disabled theme detected'); |
|
137 // Check for base theme and subtheme lists. |
|
138 $base_theme_list = array('test_basetheme' => 'Theme test base theme'); |
|
139 $sub_theme_list = array('test_subtheme' => 'Theme test subtheme'); |
|
140 $this->assertIdentical($themes['test_basetheme']->sub_themes, $sub_theme_list, 'Base theme\'s object includes list of subthemes.'); |
|
141 $this->assertIdentical($themes['test_subtheme']->base_themes, $base_theme_list, 'Subtheme\'s object includes list of base themes.'); |
|
142 // Check for theme engine in subtheme. |
|
143 $this->assertIdentical($themes['test_subtheme']->engine, 'phptemplate', 'Subtheme\'s object includes the theme engine.'); |
|
144 // Check for theme engine prefix. |
|
145 $this->assertIdentical($themes['test_basetheme']->prefix, 'phptemplate', 'Base theme\'s object includes the theme engine prefix.'); |
|
146 $this->assertIdentical($themes['test_subtheme']->prefix, 'phptemplate', 'Subtheme\'s object includes the theme engine prefix.'); |
|
147 } |
|
148 |
|
149 /** |
|
150 * Test the theme_get_setting() function. |
|
151 */ |
|
152 function testThemeGetSetting() { |
|
153 $GLOBALS['theme_key'] = 'test_theme'; |
|
154 $this->assertIdentical(theme_get_setting('theme_test_setting'), 'default value', 'theme_get_setting() uses the default theme automatically.'); |
|
155 $this->assertNotEqual(theme_get_setting('subtheme_override', 'test_basetheme'), theme_get_setting('subtheme_override', 'test_subtheme'), 'Base theme\'s default settings values can be overridden by subtheme.'); |
|
156 $this->assertIdentical(theme_get_setting('basetheme_only', 'test_subtheme'), 'base theme value', 'Base theme\'s default settings values are inherited by subtheme.'); |
|
157 } |
|
158 |
|
159 /** |
|
160 * Test the drupal_add_region_content() function. |
|
161 */ |
|
162 function testDrupalAddRegionContent() { |
|
163 $this->drupalGet('theme-test/drupal-add-region-content'); |
|
164 $this->assertText('Hello'); |
|
165 $this->assertText('World'); |
|
166 } |
|
167 } |
|
168 |
|
169 /** |
|
170 * Unit tests for theme_table(). |
|
171 */ |
|
172 class ThemeTableTestCase extends DrupalWebTestCase { |
|
173 public static function getInfo() { |
|
174 return array( |
|
175 'name' => 'Theme Table', |
|
176 'description' => 'Tests built-in theme functions.', |
|
177 'group' => 'Theme', |
|
178 ); |
|
179 } |
|
180 |
|
181 /** |
|
182 * Tableheader.js provides 'sticky' table headers, and is included by default. |
|
183 */ |
|
184 function testThemeTableStickyHeaders() { |
|
185 $header = array('one', 'two', 'three'); |
|
186 $rows = array(array(1,2,3), array(4,5,6), array(7,8,9)); |
|
187 $this->content = theme('table', array('header' => $header, 'rows' => $rows)); |
|
188 $js = drupal_add_js(); |
|
189 $this->assertTrue(isset($js['misc/tableheader.js']), 'tableheader.js was included when $sticky = TRUE.'); |
|
190 $this->assertRaw('sticky-enabled', 'Table has a class of sticky-enabled when $sticky = TRUE.'); |
|
191 drupal_static_reset('drupal_add_js'); |
|
192 } |
|
193 |
|
194 /** |
|
195 * If $sticky is FALSE, no tableheader.js should be included. |
|
196 */ |
|
197 function testThemeTableNoStickyHeaders() { |
|
198 $header = array('one', 'two', 'three'); |
|
199 $rows = array(array(1,2,3), array(4,5,6), array(7,8,9)); |
|
200 $attributes = array(); |
|
201 $caption = NULL; |
|
202 $colgroups = array(); |
|
203 $this->content = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => $attributes, 'caption' => $caption, 'colgroups' => $colgroups, 'sticky' => FALSE)); |
|
204 $js = drupal_add_js(); |
|
205 $this->assertFalse(isset($js['misc/tableheader.js']), 'tableheader.js was not included because $sticky = FALSE.'); |
|
206 $this->assertNoRaw('sticky-enabled', 'Table does not have a class of sticky-enabled because $sticky = FALSE.'); |
|
207 drupal_static_reset('drupal_add_js'); |
|
208 } |
|
209 |
|
210 /** |
|
211 * Tests that the table header is printed correctly even if there are no rows, |
|
212 * and that the empty text is displayed correctly. |
|
213 */ |
|
214 function testThemeTableWithEmptyMessage() { |
|
215 $header = array( |
|
216 t('Header 1'), |
|
217 array( |
|
218 'data' => t('Header 2'), |
|
219 'colspan' => 2, |
|
220 ), |
|
221 ); |
|
222 $this->content = theme('table', array('header' => $header, 'rows' => array(), 'empty' => t('No strings available.'))); |
|
223 $this->assertRaw('<tr class="odd"><td colspan="3" class="empty message">No strings available.</td>', 'Correct colspan was set on empty message.'); |
|
224 $this->assertRaw('<thead><tr><th>Header 1</th>', 'Table header was printed.'); |
|
225 } |
|
226 |
|
227 /** |
|
228 * Tests that the 'no_striping' option works correctly. |
|
229 */ |
|
230 function testThemeTableWithNoStriping() { |
|
231 $rows = array( |
|
232 array( |
|
233 'data' => array(1), |
|
234 'no_striping' => TRUE, |
|
235 ), |
|
236 ); |
|
237 $this->content = theme('table', array('rows' => $rows)); |
|
238 $this->assertNoRaw('class="odd"', 'Odd/even classes were not added because $no_striping = TRUE.'); |
|
239 $this->assertNoRaw('no_striping', 'No invalid no_striping HTML attribute was printed.'); |
|
240 } |
|
241 } |
|
242 |
|
243 /** |
|
244 * Unit tests for theme_item_list(). |
|
245 */ |
|
246 class ThemeItemListUnitTest extends DrupalWebTestCase { |
|
247 public static function getInfo() { |
|
248 return array( |
|
249 'name' => 'Theme item list', |
|
250 'description' => 'Test the theme_item_list() function.', |
|
251 'group' => 'Theme', |
|
252 ); |
|
253 } |
|
254 |
|
255 /** |
|
256 * Test item list rendering. |
|
257 */ |
|
258 function testItemList() { |
|
259 $items = array('a', array('data' => 'b', 'children' => array('c' => 'c', 'd' => 'd', 'e' => 'e')), 'f'); |
|
260 $expected = '<div class="item-list"><ul><li class="first">a</li> |
|
261 <li>b<div class="item-list"><ul><li class="first">c</li> |
|
262 <li>d</li> |
|
263 <li class="last">e</li> |
|
264 </ul></div></li> |
|
265 <li class="last">f</li> |
|
266 </ul></div>'; |
|
267 $output = theme('item_list', array('items' => $items)); |
|
268 $this->assertIdentical($expected, $output, 'Item list is rendered correctly.'); |
|
269 } |
|
270 } |
|
271 |
|
272 /** |
|
273 * Unit tests for theme_links(). |
|
274 */ |
|
275 class ThemeLinksTest extends DrupalWebTestCase { |
|
276 public static function getInfo() { |
|
277 return array( |
|
278 'name' => 'Links', |
|
279 'description' => 'Test the theme_links() function and rendering groups of links.', |
|
280 'group' => 'Theme', |
|
281 ); |
|
282 } |
|
283 |
|
284 /** |
|
285 * Test the use of drupal_pre_render_links() on a nested array of links. |
|
286 */ |
|
287 function testDrupalPreRenderLinks() { |
|
288 // Define the base array to be rendered, containing a variety of different |
|
289 // kinds of links. |
|
290 $base_array = array( |
|
291 '#theme' => 'links', |
|
292 '#pre_render' => array('drupal_pre_render_links'), |
|
293 '#links' => array( |
|
294 'parent_link' => array( |
|
295 'title' => 'Parent link original', |
|
296 'href' => 'parent-link-original', |
|
297 ), |
|
298 ), |
|
299 'first_child' => array( |
|
300 '#theme' => 'links', |
|
301 '#links' => array( |
|
302 // This should be rendered if 'first_child' is rendered separately, |
|
303 // but ignored if the parent is being rendered (since it duplicates |
|
304 // one of the parent's links). |
|
305 'parent_link' => array( |
|
306 'title' => 'Parent link copy', |
|
307 'href' => 'parent-link-copy', |
|
308 ), |
|
309 // This should always be rendered. |
|
310 'first_child_link' => array( |
|
311 'title' => 'First child link', |
|
312 'href' => 'first-child-link', |
|
313 ), |
|
314 ), |
|
315 ), |
|
316 // This should always be rendered as part of the parent. |
|
317 'second_child' => array( |
|
318 '#theme' => 'links', |
|
319 '#links' => array( |
|
320 'second_child_link' => array( |
|
321 'title' => 'Second child link', |
|
322 'href' => 'second-child-link', |
|
323 ), |
|
324 ), |
|
325 ), |
|
326 // This should never be rendered, since the user does not have access to |
|
327 // it. |
|
328 'third_child' => array( |
|
329 '#theme' => 'links', |
|
330 '#links' => array( |
|
331 'third_child_link' => array( |
|
332 'title' => 'Third child link', |
|
333 'href' => 'third-child-link', |
|
334 ), |
|
335 ), |
|
336 '#access' => FALSE, |
|
337 ), |
|
338 ); |
|
339 |
|
340 // Start with a fresh copy of the base array, and try rendering the entire |
|
341 // thing. We expect a single <ul> with appropriate links contained within |
|
342 // it. |
|
343 $render_array = $base_array; |
|
344 $html = drupal_render($render_array); |
|
345 $dom = new DOMDocument(); |
|
346 $dom->loadHTML($html); |
|
347 $this->assertEqual($dom->getElementsByTagName('ul')->length, 1, 'One "ul" tag found in the rendered HTML.'); |
|
348 $list_elements = $dom->getElementsByTagName('li'); |
|
349 $this->assertEqual($list_elements->length, 3, 'Three "li" tags found in the rendered HTML.'); |
|
350 $this->assertEqual($list_elements->item(0)->nodeValue, 'Parent link original', 'First expected link found.'); |
|
351 $this->assertEqual($list_elements->item(1)->nodeValue, 'First child link', 'Second expected link found.'); |
|
352 $this->assertEqual($list_elements->item(2)->nodeValue, 'Second child link', 'Third expected link found.'); |
|
353 $this->assertIdentical(strpos($html, 'Parent link copy'), FALSE, '"Parent link copy" link not found.'); |
|
354 $this->assertIdentical(strpos($html, 'Third child link'), FALSE, '"Third child link" link not found.'); |
|
355 |
|
356 // Now render 'first_child', followed by the rest of the links, and make |
|
357 // sure we get two separate <ul>'s with the appropriate links contained |
|
358 // within each. |
|
359 $render_array = $base_array; |
|
360 $child_html = drupal_render($render_array['first_child']); |
|
361 $parent_html = drupal_render($render_array); |
|
362 // First check the child HTML. |
|
363 $dom = new DOMDocument(); |
|
364 $dom->loadHTML($child_html); |
|
365 $this->assertEqual($dom->getElementsByTagName('ul')->length, 1, 'One "ul" tag found in the rendered child HTML.'); |
|
366 $list_elements = $dom->getElementsByTagName('li'); |
|
367 $this->assertEqual($list_elements->length, 2, 'Two "li" tags found in the rendered child HTML.'); |
|
368 $this->assertEqual($list_elements->item(0)->nodeValue, 'Parent link copy', 'First expected link found.'); |
|
369 $this->assertEqual($list_elements->item(1)->nodeValue, 'First child link', 'Second expected link found.'); |
|
370 // Then check the parent HTML. |
|
371 $dom = new DOMDocument(); |
|
372 $dom->loadHTML($parent_html); |
|
373 $this->assertEqual($dom->getElementsByTagName('ul')->length, 1, 'One "ul" tag found in the rendered parent HTML.'); |
|
374 $list_elements = $dom->getElementsByTagName('li'); |
|
375 $this->assertEqual($list_elements->length, 2, 'Two "li" tags found in the rendered parent HTML.'); |
|
376 $this->assertEqual($list_elements->item(0)->nodeValue, 'Parent link original', 'First expected link found.'); |
|
377 $this->assertEqual($list_elements->item(1)->nodeValue, 'Second child link', 'Second expected link found.'); |
|
378 $this->assertIdentical(strpos($parent_html, 'First child link'), FALSE, '"First child link" link not found.'); |
|
379 $this->assertIdentical(strpos($parent_html, 'Third child link'), FALSE, '"Third child link" link not found.'); |
|
380 } |
|
381 } |
|
382 |
|
383 /** |
|
384 * Functional test for initialization of the theme system in hook_init(). |
|
385 */ |
|
386 class ThemeHookInitTestCase extends DrupalWebTestCase { |
|
387 public static function getInfo() { |
|
388 return array( |
|
389 'name' => 'Theme initialization in hook_init()', |
|
390 'description' => 'Tests that the theme system can be correctly initialized in hook_init().', |
|
391 'group' => 'Theme', |
|
392 ); |
|
393 } |
|
394 |
|
395 function setUp() { |
|
396 parent::setUp('theme_test'); |
|
397 } |
|
398 |
|
399 /** |
|
400 * Test that the theme system can generate output when called by hook_init(). |
|
401 */ |
|
402 function testThemeInitializationHookInit() { |
|
403 $this->drupalGet('theme-test/hook-init'); |
|
404 $this->assertRaw('Themed output generated in hook_init()', 'Themed output generated in hook_init() correctly appears on the page.'); |
|
405 $this->assertRaw('bartik/css/style.css', "The default theme's CSS appears on the page when the theme system is initialized in hook_init()."); |
|
406 } |
|
407 } |
|
408 |
|
409 /** |
|
410 * Tests autocompletion not loading registry. |
|
411 */ |
|
412 class ThemeFastTestCase extends DrupalWebTestCase { |
|
413 public static function getInfo() { |
|
414 return array( |
|
415 'name' => 'Theme fast initialization', |
|
416 'description' => 'Test that autocompletion does not load the registry.', |
|
417 'group' => 'Theme' |
|
418 ); |
|
419 } |
|
420 |
|
421 function setUp() { |
|
422 parent::setUp('theme_test'); |
|
423 $this->account = $this->drupalCreateUser(array('access user profiles')); |
|
424 } |
|
425 |
|
426 /** |
|
427 * Tests access to user autocompletion and verify the correct results. |
|
428 */ |
|
429 function testUserAutocomplete() { |
|
430 $this->drupalLogin($this->account); |
|
431 $this->drupalGet('user/autocomplete/' . $this->account->name); |
|
432 $this->assertText('registry not initialized', 'The registry was not initialized'); |
|
433 } |
|
434 } |
|
435 |
|
436 /** |
|
437 * Tests the markup of core render element types passed to drupal_render(). |
|
438 */ |
|
439 class RenderElementTypesTestCase extends DrupalWebTestCase { |
|
440 public static function getInfo() { |
|
441 return array( |
|
442 'name' => 'Render element types', |
|
443 'description' => 'Tests the markup of core render element types passed to drupal_render().', |
|
444 'group' => 'Theme', |
|
445 ); |
|
446 } |
|
447 |
|
448 /** |
|
449 * Asserts that an array of elements is rendered properly. |
|
450 * |
|
451 * @param array $elements |
|
452 * An array of associative arrays describing render elements and their |
|
453 * expected markup. Each item in $elements must contain the following: |
|
454 * - 'name': This human readable description will be displayed on the test |
|
455 * results page. |
|
456 * - 'value': This is the render element to test. |
|
457 * - 'expected': This is the expected markup for the element in 'value'. |
|
458 */ |
|
459 function assertElements($elements) { |
|
460 foreach($elements as $element) { |
|
461 $this->assertIdentical(drupal_render($element['value']), $element['expected'], '"' . $element['name'] . '" input rendered correctly by drupal_render().'); |
|
462 } |
|
463 } |
|
464 |
|
465 /** |
|
466 * Tests system #type 'container'. |
|
467 */ |
|
468 function testContainer() { |
|
469 $elements = array( |
|
470 // Basic container with no attributes. |
|
471 array( |
|
472 'name' => "#type 'container' with no HTML attributes", |
|
473 'value' => array( |
|
474 '#type' => 'container', |
|
475 'child' => array( |
|
476 '#markup' => 'foo', |
|
477 ), |
|
478 ), |
|
479 'expected' => '<div>foo</div>', |
|
480 ), |
|
481 // Container with a class. |
|
482 array( |
|
483 'name' => "#type 'container' with a class HTML attribute", |
|
484 'value' => array( |
|
485 '#type' => 'container', |
|
486 'child' => array( |
|
487 '#markup' => 'foo', |
|
488 ), |
|
489 '#attributes' => array( |
|
490 'class' => 'bar', |
|
491 ), |
|
492 ), |
|
493 'expected' => '<div class="bar">foo</div>', |
|
494 ), |
|
495 ); |
|
496 |
|
497 $this->assertElements($elements); |
|
498 } |
|
499 |
|
500 /** |
|
501 * Tests system #type 'html_tag'. |
|
502 */ |
|
503 function testHtmlTag() { |
|
504 $elements = array( |
|
505 // Test auto-closure meta tag generation. |
|
506 array( |
|
507 'name' => "#type 'html_tag' auto-closure meta tag generation", |
|
508 'value' => array( |
|
509 '#type' => 'html_tag', |
|
510 '#tag' => 'meta', |
|
511 '#attributes' => array( |
|
512 'name' => 'description', |
|
513 'content' => 'Drupal test', |
|
514 ), |
|
515 ), |
|
516 'expected' => '<meta name="description" content="Drupal test" />' . "\n", |
|
517 ), |
|
518 // Test title tag generation. |
|
519 array( |
|
520 'name' => "#type 'html_tag' title tag generation", |
|
521 'value' => array( |
|
522 '#type' => 'html_tag', |
|
523 '#tag' => 'title', |
|
524 '#value' => 'title test', |
|
525 ), |
|
526 'expected' => '<title>title test</title>' . "\n", |
|
527 ), |
|
528 ); |
|
529 |
|
530 $this->assertElements($elements); |
|
531 } |
|
532 } |
|
533 |
|
534 /** |
|
535 * Tests for the ThemeRegistry class. |
|
536 */ |
|
537 class ThemeRegistryTestCase extends DrupalWebTestCase { |
|
538 public static function getInfo() { |
|
539 return array( |
|
540 'name' => 'ThemeRegistry', |
|
541 'description' => 'Tests the behavior of the ThemeRegistry class', |
|
542 'group' => 'Theme', |
|
543 ); |
|
544 } |
|
545 function setUp() { |
|
546 parent::setUp('theme_test'); |
|
547 } |
|
548 |
|
549 /** |
|
550 * Tests the behavior of the theme registry class. |
|
551 */ |
|
552 function testRaceCondition() { |
|
553 $_SERVER['REQUEST_METHOD'] = 'GET'; |
|
554 $cid = 'test_theme_registry'; |
|
555 |
|
556 // Directly instantiate the theme registry, this will cause a base cache |
|
557 // entry to be written in __construct(). |
|
558 $registry = new ThemeRegistry($cid, 'cache'); |
|
559 |
|
560 $this->assertTrue(cache_get($cid), 'Cache entry was created.'); |
|
561 |
|
562 // Trigger a cache miss for an offset. |
|
563 $this->assertTrue($registry['theme_test_template_test'], 'Offset was returned correctly from the theme registry.'); |
|
564 // This will cause the ThemeRegistry class to write an updated version of |
|
565 // the cache entry when it is destroyed, usually at the end of the request. |
|
566 // Before that happens, manually delete the cache entry we created earlier |
|
567 // so that the new entry is written from scratch. |
|
568 cache_clear_all($cid, 'cache'); |
|
569 |
|
570 // Destroy the class so that it triggers a cache write for the offset. |
|
571 unset($registry); |
|
572 |
|
573 $this->assertTrue(cache_get($cid), 'Cache entry was created.'); |
|
574 |
|
575 // Create a new instance of the class. Confirm that both the offset |
|
576 // requested previously, and one that has not yet been requested are both |
|
577 // available. |
|
578 $registry = new ThemeRegistry($cid, 'cache'); |
|
579 |
|
580 $this->assertTrue($registry['theme_test_template_test'], 'Offset was returned correctly from the theme registry'); |
|
581 $this->assertTrue($registry['theme_test_template_test_2'], 'Offset was returned correctly from the theme registry'); |
|
582 } |
|
583 } |
|
584 |
|
585 /** |
|
586 * Tests for theme debug markup. |
|
587 */ |
|
588 class ThemeDebugMarkupTestCase extends DrupalWebTestCase { |
|
589 |
|
590 public static function getInfo() { |
|
591 return array( |
|
592 'name' => 'Theme debug markup', |
|
593 'description' => 'Tests theme debug markup output.', |
|
594 'group' => 'Theme', |
|
595 ); |
|
596 } |
|
597 |
|
598 function setUp() { |
|
599 parent::setUp('theme_test', 'node'); |
|
600 theme_enable(array('test_theme')); |
|
601 } |
|
602 |
|
603 /** |
|
604 * Tests debug markup added to template output. |
|
605 */ |
|
606 function testDebugOutput() { |
|
607 variable_set('theme_default', 'test_theme'); |
|
608 // Enable the debug output. |
|
609 variable_set('theme_debug', TRUE); |
|
610 |
|
611 $registry = theme_get_registry(); |
|
612 $extension = '.tpl.php'; |
|
613 // Populate array of templates. |
|
614 $templates = drupal_find_theme_templates($registry, $extension, drupal_get_path('theme', 'test_theme')); |
|
615 $templates += drupal_find_theme_templates($registry, $extension, drupal_get_path('module', 'node')); |
|
616 |
|
617 // Create a node and test different features of the debug markup. |
|
618 $node = $this->drupalCreateNode(); |
|
619 $this->drupalGet('node/' . $node->nid); |
|
620 $this->assertRaw('<!-- THEME DEBUG -->', 'Theme debug markup found in theme output when debug is enabled.'); |
|
621 $this->assertRaw("CALL: theme('node')", 'Theme call information found.'); |
|
622 $this->assertRaw('x node--1' . $extension . PHP_EOL . ' * node--page' . $extension . PHP_EOL . ' * node' . $extension, 'Suggested template files found in order and node ID specific template shown as current template.'); |
|
623 $template_filename = $templates['node__1']['path'] . '/' . $templates['node__1']['template'] . $extension; |
|
624 $this->assertRaw("BEGIN OUTPUT from '$template_filename'", 'Full path to current template file found.'); |
|
625 |
|
626 // Create another node and make sure the template suggestions shown in the |
|
627 // debug markup are correct. |
|
628 $node2 = $this->drupalCreateNode(); |
|
629 $this->drupalGet('node/' . $node2->nid); |
|
630 $this->assertRaw('* node--2' . $extension . PHP_EOL . ' * node--page' . $extension . PHP_EOL . ' x node' . $extension, 'Suggested template files found in order and base template shown as current template.'); |
|
631 |
|
632 // Create another node and make sure the template suggestions shown in the |
|
633 // debug markup are correct. |
|
634 $node3 = $this->drupalCreateNode(); |
|
635 $build = array('#theme' => 'node__foo__bar'); |
|
636 $build += node_view($node3); |
|
637 $output = drupal_render($build); |
|
638 $this->assertTrue(strpos($output, "CALL: theme('node__foo__bar')") !== FALSE, 'Theme call information found.'); |
|
639 $this->assertTrue(strpos($output, '* node--foo--bar' . $extension . PHP_EOL . ' * node--foo' . $extension . PHP_EOL . ' * node--3' . $extension . PHP_EOL . ' * node--page' . $extension . PHP_EOL . ' x node' . $extension) !== FALSE, 'Suggested template files found in order and base template shown as current template.'); |
|
640 |
|
641 // Disable theme debug. |
|
642 variable_set('theme_debug', FALSE); |
|
643 |
|
644 $this->drupalGet('node/' . $node->nid); |
|
645 $this->assertNoRaw('<!-- THEME DEBUG -->', 'Theme debug markup not found in theme output when debug is disabled.'); |
|
646 } |
|
647 |
|
648 } |
|
649 |
|
650 /** |
|
651 * Tests module-provided theme engines. |
|
652 */ |
|
653 class ModuleProvidedThemeEngineTestCase extends DrupalWebTestCase { |
|
654 |
|
655 public static function getInfo() { |
|
656 return array( |
|
657 'name' => 'Theme engine test', |
|
658 'description' => 'Tests module-provided theme engines.', |
|
659 'group' => 'Theme', |
|
660 ); |
|
661 } |
|
662 |
|
663 function setUp() { |
|
664 parent::setUp('theme_test'); |
|
665 theme_enable(array('test_theme', 'test_theme_nyan_cat')); |
|
666 } |
|
667 |
|
668 /** |
|
669 * Ensures that the module provided theme engine is found and used by core. |
|
670 */ |
|
671 function testEngineIsFoundAndWorking() { |
|
672 variable_set('theme_default', 'test_theme_nyan_cat'); |
|
673 variable_set('admin_theme', 'test_theme_nyan_cat'); |
|
674 |
|
675 $this->drupalGet('theme-test/engine-info-test'); |
|
676 $this->assertText('Miaou'); |
|
677 } |
|
678 |
|
679 } |