Upgraded drupal core with security updates
[yaffs-website] / web / core / modules / system / src / Tests / Theme / FunctionsTest.php
1 <?php
2
3 namespace Drupal\system\Tests\Theme;
4
5 use Drupal\Component\Serialization\Json;
6 use Drupal\Component\Utility\Html;
7 use Drupal\Component\Utility\SafeMarkup;
8 use Drupal\Core\Session\UserSession;
9 use Drupal\Core\Url;
10 use Drupal\simpletest\WebTestBase;
11
12 /**
13  * Tests for common theme functions.
14  *
15  * @group Theme
16  */
17 class FunctionsTest extends WebTestBase {
18
19   /**
20    * Modules to enable.
21    *
22    * @var array
23    */
24   public static $modules = ['router_test'];
25
26   /**
27    * Tests item-list.html.twig.
28    */
29   public function testItemList() {
30     // Verify that empty items produce no output.
31     $variables = [];
32     $expected = '';
33     $this->assertThemeOutput('item_list', $variables, $expected, 'Empty %callback generates no output.');
34
35     // Verify that empty items with title produce no output.
36     $variables = [];
37     $variables['title'] = 'Some title';
38     $expected = '';
39     $this->assertThemeOutput('item_list', $variables, $expected, 'Empty %callback with title generates no output.');
40
41     // Verify that empty items produce the empty string.
42     $variables = [];
43     $variables['empty'] = 'No items found.';
44     $expected = '<div class="item-list">No items found.</div>';
45     $this->assertThemeOutput('item_list', $variables, $expected, 'Empty %callback generates empty string.');
46
47     // Verify that empty items produce the empty string with title.
48     $variables = [];
49     $variables['title'] = 'Some title';
50     $variables['empty'] = 'No items found.';
51     $expected = '<div class="item-list"><h3>Some title</h3>No items found.</div>';
52     $this->assertThemeOutput('item_list', $variables, $expected, 'Empty %callback generates empty string with title.');
53
54     // Verify that title set to 0 is output.
55     $variables = [];
56     $variables['title'] = 0;
57     $variables['empty'] = 'No items found.';
58     $expected = '<div class="item-list"><h3>0</h3>No items found.</div>';
59     $this->assertThemeOutput('item_list', $variables, $expected, '%callback with title set to 0 generates a title.');
60
61     // Verify that title set to a render array is output.
62     $variables = [];
63     $variables['title'] = [
64       '#markup' => '<span>Render array</span>',
65     ];
66     $variables['empty'] = 'No items found.';
67     $expected = '<div class="item-list"><h3><span>Render array</span></h3>No items found.</div>';
68     $this->assertThemeOutput('item_list', $variables, $expected, '%callback with title set to a render array generates a title.');
69
70     // Verify that empty text is not displayed when there are list items.
71     $variables = [];
72     $variables['title'] = 'Some title';
73     $variables['empty'] = 'No items found.';
74     $variables['items'] = ['Un', 'Deux', 'Trois'];
75     $expected = '<div class="item-list"><h3>Some title</h3><ul><li>Un</li><li>Deux</li><li>Trois</li></ul></div>';
76     $this->assertThemeOutput('item_list', $variables, $expected, '%callback does not print empty text when there are list items.');
77
78     // Verify nested item lists.
79     $variables = [];
80     $variables['title'] = 'Some title';
81     $variables['attributes'] = [
82       'id' => 'parentlist',
83     ];
84     $variables['items'] = [
85       // A plain string value forms an own item.
86       'a',
87       // Items can be fully-fledged render arrays with their own attributes.
88       [
89         '#wrapper_attributes' => [
90           'id' => 'item-id-b',
91         ],
92         '#markup' => 'b',
93         'childlist' => [
94           '#theme' => 'item_list',
95           '#attributes' => ['id' => 'blist'],
96           '#list_type' => 'ol',
97           '#items' => [
98             'ba',
99             [
100               '#markup' => 'bb',
101               '#wrapper_attributes' => ['class' => ['item-class-bb']],
102             ],
103           ],
104         ],
105       ],
106       // However, items can also be child #items.
107       [
108         '#markup' => 'c',
109         'childlist' => [
110           '#attributes' => ['id' => 'clist'],
111           'ca',
112           [
113             '#markup' => 'cb',
114             '#wrapper_attributes' => ['class' => ['item-class-cb']],
115             'children' => [
116               'cba',
117               'cbb',
118             ],
119           ],
120           'cc',
121         ],
122       ],
123       // Use #markup to be able to specify #wrapper_attributes.
124       [
125         '#markup' => 'd',
126         '#wrapper_attributes' => ['id' => 'item-id-d'],
127       ],
128       // An empty item with attributes.
129       [
130         '#wrapper_attributes' => ['id' => 'item-id-e'],
131       ],
132       // Lastly, another plain string item.
133       'f',
134     ];
135
136     $inner_b = '<div class="item-list"><ol id="blist">';
137     $inner_b .= '<li>ba</li>';
138     $inner_b .= '<li class="item-class-bb">bb</li>';
139     $inner_b .= '</ol></div>';
140
141     $inner_cb = '<div class="item-list"><ul>';
142     $inner_cb .= '<li>cba</li>';
143     $inner_cb .= '<li>cbb</li>';
144     $inner_cb .= '</ul></div>';
145
146     $inner_c = '<div class="item-list"><ul id="clist">';
147     $inner_c .= '<li>ca</li>';
148     $inner_c .= '<li class="item-class-cb">cb' . $inner_cb . '</li>';
149     $inner_c .= '<li>cc</li>';
150     $inner_c .= '</ul></div>';
151
152     $expected = '<div class="item-list">';
153     $expected .= '<h3>Some title</h3>';
154     $expected .= '<ul id="parentlist">';
155     $expected .= '<li>a</li>';
156     $expected .= '<li id="item-id-b">b' . $inner_b . '</li>';
157     $expected .= '<li>c' . $inner_c . '</li>';
158     $expected .= '<li id="item-id-d">d</li>';
159     $expected .= '<li id="item-id-e"></li>';
160     $expected .= '<li>f</li>';
161     $expected .= '</ul></div>';
162
163     $this->assertThemeOutput('item_list', $variables, $expected);
164   }
165
166   /**
167    * Tests links.html.twig.
168    */
169   public function testLinks() {
170     // Turn off the query for the
171     // \Drupal\Core\Utility\LinkGeneratorInterface::generate() method to compare
172     // the active link correctly.
173     $original_query = \Drupal::request()->query->all();
174     \Drupal::request()->query->replace([]);
175     // Verify that empty variables produce no output.
176     $variables = [];
177     $expected = '';
178     $this->assertThemeOutput('links', $variables, $expected, 'Empty %callback generates no output.');
179
180     $variables = [];
181     $variables['heading'] = 'Some title';
182     $expected = '';
183     $this->assertThemeOutput('links', $variables, $expected, 'Empty %callback with heading generates no output.');
184
185     // Verify that a list of links is properly rendered.
186     $variables = [];
187     $variables['attributes'] = ['id' => 'somelinks'];
188     $variables['links'] = [
189       'a link' => [
190         'title' => 'A <link>',
191         'url' => Url::fromUri('base:a/link'),
192       ],
193       'plain text' => [
194         'title' => 'Plain "text"',
195       ],
196       'html text' => [
197         'title' => SafeMarkup::format('<span class="unescaped">@text</span>', ['@text' => 'potentially unsafe text that <should> be escaped']),
198       ],
199       'front page' => [
200         'title' => 'Front page',
201         'url' => Url::fromRoute('<front>'),
202       ],
203       'router-test' => [
204         'title' => 'Test route',
205         'url' => Url::fromRoute('router_test.1'),
206       ],
207       'query-test' => [
208         'title' => 'Query test route',
209         'url' => Url::fromRoute('router_test.1'),
210         'query' => [
211           'key' => 'value',
212         ]
213       ],
214     ];
215
216     $expected_links = '';
217     $expected_links .= '<ul id="somelinks">';
218     $expected_links .= '<li class="a-link"><a href="' . Url::fromUri('base:a/link')->toString() . '">' . Html::escape('A <link>') . '</a></li>';
219     $expected_links .= '<li class="plain-text">' . Html::escape('Plain "text"') . '</li>';
220     $expected_links .= '<li class="html-text"><span class="unescaped">' . Html::escape('potentially unsafe text that <should> be escaped') . '</span></li>';
221     $expected_links .= '<li class="front-page"><a href="' . Url::fromRoute('<front>')->toString() . '">' . Html::escape('Front page') . '</a></li>';
222     $expected_links .= '<li class="router-test"><a href="' . \Drupal::urlGenerator()->generate('router_test.1') . '">' . Html::escape('Test route') . '</a></li>';
223     $query = ['key' => 'value'];
224     $expected_links .= '<li class="query-test"><a href="' . \Drupal::urlGenerator()->generate('router_test.1', $query) . '">' . Html::escape('Query test route') . '</a></li>';
225     $expected_links .= '</ul>';
226
227     // Verify that passing a string as heading works.
228     $variables['heading'] = 'Links heading';
229     $expected_heading = '<h2>Links heading</h2>';
230     $expected = $expected_heading . $expected_links;
231     $this->assertThemeOutput('links', $variables, $expected);
232
233     // Restore the original request's query.
234     \Drupal::request()->query->replace($original_query);
235
236     // Verify that passing an array as heading works (core support).
237     $variables['heading'] = [
238       'text' => 'Links heading',
239       'level' => 'h3',
240       'attributes' => ['class' => ['heading']],
241     ];
242     $expected_heading = '<h3 class="heading">Links heading</h3>';
243     $expected = $expected_heading . $expected_links;
244     $this->assertThemeOutput('links', $variables, $expected);
245
246     // Verify that passing attributes for the heading works.
247     $variables['heading'] = ['text' => 'Links heading', 'level' => 'h3', 'attributes' => ['id' => 'heading']];
248     $expected_heading = '<h3 id="heading">Links heading</h3>';
249     $expected = $expected_heading . $expected_links;
250     $this->assertThemeOutput('links', $variables, $expected);
251
252     // Verify that passing attributes for the links work.
253     $variables['links']['plain text']['attributes'] = [
254       'class' => ['a/class'],
255     ];
256     $expected_links = '';
257     $expected_links .= '<ul id="somelinks">';
258     $expected_links .= '<li class="a-link"><a href="' . Url::fromUri('base:a/link')->toString() . '">' . Html::escape('A <link>') . '</a></li>';
259     $expected_links .= '<li class="plain-text"><span class="a/class">' . Html::escape('Plain "text"') . '</span></li>';
260     $expected_links .= '<li class="html-text"><span class="unescaped">' . Html::escape('potentially unsafe text that <should> be escaped') . '</span></li>';
261     $expected_links .= '<li class="front-page"><a href="' . Url::fromRoute('<front>')->toString() . '">' . Html::escape('Front page') . '</a></li>';
262     $expected_links .= '<li class="router-test"><a href="' . \Drupal::urlGenerator()->generate('router_test.1') . '">' . Html::escape('Test route') . '</a></li>';
263     $query = ['key' => 'value'];
264     $expected_links .= '<li class="query-test"><a href="' . \Drupal::urlGenerator()->generate('router_test.1', $query) . '">' . Html::escape('Query test route') . '</a></li>';
265     $expected_links .= '</ul>';
266     $expected = $expected_heading . $expected_links;
267     $this->assertThemeOutput('links', $variables, $expected);
268
269     // Verify the data- attributes for setting the "active" class on links.
270     \Drupal::currentUser()->setAccount(new UserSession(['uid' => 1]));
271     $variables['set_active_class'] = TRUE;
272     $expected_links = '';
273     $expected_links .= '<ul id="somelinks">';
274     $expected_links .= '<li class="a-link"><a href="' . Url::fromUri('base:a/link')->toString() . '">' . Html::escape('A <link>') . '</a></li>';
275     $expected_links .= '<li class="plain-text"><span class="a/class">' . Html::escape('Plain "text"') . '</span></li>';
276     $expected_links .= '<li class="html-text"><span class="unescaped">' . Html::escape('potentially unsafe text that <should> be escaped') . '</span></li>';
277     $expected_links .= '<li data-drupal-link-system-path="&lt;front&gt;" class="front-page"><a href="' . Url::fromRoute('<front>')->toString() . '" data-drupal-link-system-path="&lt;front&gt;">' . Html::escape('Front page') . '</a></li>';
278     $expected_links .= '<li data-drupal-link-system-path="router_test/test1" class="router-test"><a href="' . \Drupal::urlGenerator()->generate('router_test.1') . '" data-drupal-link-system-path="router_test/test1">' . Html::escape('Test route') . '</a></li>';
279     $query = ['key' => 'value'];
280     $encoded_query = Html::escape(Json::encode($query));
281     $expected_links .= '<li data-drupal-link-query="' . $encoded_query . '" data-drupal-link-system-path="router_test/test1" class="query-test"><a href="' . \Drupal::urlGenerator()->generate('router_test.1', $query) . '" data-drupal-link-query="' . $encoded_query . '" data-drupal-link-system-path="router_test/test1">' . Html::escape('Query test route') . '</a></li>';
282     $expected_links .= '</ul>';
283     $expected = $expected_heading . $expected_links;
284     $this->assertThemeOutput('links', $variables, $expected);
285   }
286
287   /**
288    * Tests links.html.twig using links with indexed keys.
289    */
290   public function testIndexedKeyedLinks() {
291     // Turn off the query for the
292     // \Drupal\Core\Utility\LinkGeneratorInterface::generate() method to compare
293     // the active link correctly.
294     $original_query = \Drupal::request()->query->all();
295     \Drupal::request()->query->replace([]);
296     // Verify that empty variables produce no output.
297     $variables = [];
298     $expected = '';
299     $this->assertThemeOutput('links', $variables, $expected, 'Empty %callback generates no output.');
300
301     $variables = [];
302     $variables['heading'] = 'Some title';
303     $expected = '';
304     $this->assertThemeOutput('links', $variables, $expected, 'Empty %callback with heading generates no output.');
305
306     // Verify that a list of links is properly rendered.
307     $variables = [];
308     $variables['attributes'] = ['id' => 'somelinks'];
309     $variables['links'] = [
310       [
311         'title' => 'A <link>',
312         'url' => Url::fromUri('base:a/link'),
313       ],
314       [
315         'title' => 'Plain "text"',
316       ],
317       [
318         'title' => SafeMarkup::format('<span class="unescaped">@text</span>', ['@text' => 'potentially unsafe text that <should> be escaped']),
319       ],
320       [
321         'title' => 'Front page',
322         'url' => Url::fromRoute('<front>'),
323       ],
324       [
325         'title' => 'Test route',
326         'url' => Url::fromRoute('router_test.1'),
327       ],
328       [
329         'title' => 'Query test route',
330         'url' => Url::fromRoute('router_test.1'),
331         'query' => [
332           'key' => 'value',
333         ]
334       ],
335     ];
336
337     $expected_links = '';
338     $expected_links .= '<ul id="somelinks">';
339     $expected_links .= '<li><a href="' . Url::fromUri('base:a/link')->toString() . '">' . Html::escape('A <link>') . '</a></li>';
340     $expected_links .= '<li>' . Html::escape('Plain "text"') . '</li>';
341     $expected_links .= '<li><span class="unescaped">' . Html::escape('potentially unsafe text that <should> be escaped') . '</span></li>';
342     $expected_links .= '<li><a href="' . Url::fromRoute('<front>')->toString() . '">' . Html::escape('Front page') . '</a></li>';
343     $expected_links .= '<li><a href="' . \Drupal::urlGenerator()->generate('router_test.1') . '">' . Html::escape('Test route') . '</a></li>';
344     $query = ['key' => 'value'];
345     $expected_links .= '<li><a href="' . \Drupal::urlGenerator()->generate('router_test.1', $query) . '">' . Html::escape('Query test route') . '</a></li>';
346     $expected_links .= '</ul>';
347
348     // Verify that passing a string as heading works.
349     $variables['heading'] = 'Links heading';
350     $expected_heading = '<h2>Links heading</h2>';
351     $expected = $expected_heading . $expected_links;
352     $this->assertThemeOutput('links', $variables, $expected);
353
354     // Restore the original request's query.
355     \Drupal::request()->query->replace($original_query);
356
357     // Verify that passing an array as heading works (core support).
358     $variables['heading'] = [
359       'text' => 'Links heading',
360       'level' => 'h3',
361       'attributes' => ['class' => ['heading']],
362     ];
363     $expected_heading = '<h3 class="heading">Links heading</h3>';
364     $expected = $expected_heading . $expected_links;
365     $this->assertThemeOutput('links', $variables, $expected);
366
367     // Verify that passing attributes for the heading works.
368     $variables['heading'] = ['text' => 'Links heading', 'level' => 'h3', 'attributes' => ['id' => 'heading']];
369     $expected_heading = '<h3 id="heading">Links heading</h3>';
370     $expected = $expected_heading . $expected_links;
371     $this->assertThemeOutput('links', $variables, $expected);
372
373     // Verify that passing attributes for the links work.
374     $variables['links'][1]['attributes'] = [
375       'class' => ['a/class'],
376     ];
377     $expected_links = '';
378     $expected_links .= '<ul id="somelinks">';
379     $expected_links .= '<li><a href="' . Url::fromUri('base:a/link')->toString() . '">' . Html::escape('A <link>') . '</a></li>';
380     $expected_links .= '<li><span class="a/class">' . Html::escape('Plain "text"') . '</span></li>';
381     $expected_links .= '<li><span class="unescaped">' . Html::escape('potentially unsafe text that <should> be escaped') . '</span></li>';
382     $expected_links .= '<li><a href="' . Url::fromRoute('<front>')->toString() . '">' . Html::escape('Front page') . '</a></li>';
383     $expected_links .= '<li><a href="' . \Drupal::urlGenerator()->generate('router_test.1') . '">' . Html::escape('Test route') . '</a></li>';
384     $query = ['key' => 'value'];
385     $expected_links .= '<li><a href="' . \Drupal::urlGenerator()->generate('router_test.1', $query) . '">' . Html::escape('Query test route') . '</a></li>';
386     $expected_links .= '</ul>';
387     $expected = $expected_heading . $expected_links;
388     $this->assertThemeOutput('links', $variables, $expected);
389
390     // Verify the data- attributes for setting the "active" class on links.
391     \Drupal::currentUser()->setAccount(new UserSession(['uid' => 1]));
392     $variables['set_active_class'] = TRUE;
393     $expected_links = '';
394     $expected_links .= '<ul id="somelinks">';
395     $expected_links .= '<li><a href="' . Url::fromUri('base:a/link')->toString() . '">' . Html::escape('A <link>') . '</a></li>';
396     $expected_links .= '<li><span class="a/class">' . Html::escape('Plain "text"') . '</span></li>';
397     $expected_links .= '<li><span class="unescaped">' . Html::escape('potentially unsafe text that <should> be escaped') . '</span></li>';
398     $expected_links .= '<li data-drupal-link-system-path="&lt;front&gt;"><a href="' . Url::fromRoute('<front>')->toString() . '" data-drupal-link-system-path="&lt;front&gt;">' . Html::escape('Front page') . '</a></li>';
399     $expected_links .= '<li data-drupal-link-system-path="router_test/test1"><a href="' . \Drupal::urlGenerator()->generate('router_test.1') . '" data-drupal-link-system-path="router_test/test1">' . Html::escape('Test route') . '</a></li>';
400     $query = ['key' => 'value'];
401     $encoded_query = Html::escape(Json::encode($query));
402     $expected_links .= '<li data-drupal-link-query="' . $encoded_query . '" data-drupal-link-system-path="router_test/test1"><a href="' . \Drupal::urlGenerator()->generate('router_test.1', $query) . '" data-drupal-link-query="' . $encoded_query . '" data-drupal-link-system-path="router_test/test1">' . Html::escape('Query test route') . '</a></li>';
403     $expected_links .= '</ul>';
404     $expected = $expected_heading . $expected_links;
405     $this->assertThemeOutput('links', $variables, $expected);
406   }
407
408   /**
409    * Test the use of drupal_pre_render_links() on a nested array of links.
410    */
411   public function testDrupalPreRenderLinks() {
412     // Define the base array to be rendered, containing a variety of different
413     // kinds of links.
414     $base_array = [
415       '#theme' => 'links',
416       '#pre_render' => ['drupal_pre_render_links'],
417       '#links' => [
418         'parent_link' => [
419           'title' => 'Parent link original',
420           'url' => Url::fromRoute('router_test.1'),
421         ],
422       ],
423       'first_child' => [
424         '#theme' => 'links',
425         '#links' => [
426           // This should be rendered if 'first_child' is rendered separately,
427           // but ignored if the parent is being rendered (since it duplicates
428           // one of the parent's links).
429           'parent_link' => [
430             'title' => 'Parent link copy',
431             'url' => Url::fromRoute('router_test.6'),
432           ],
433           // This should always be rendered.
434           'first_child_link' => [
435             'title' => 'First child link',
436             'url' => Url::fromRoute('router_test.7'),
437           ],
438         ],
439       ],
440       // This should always be rendered as part of the parent.
441       'second_child' => [
442         '#theme' => 'links',
443         '#links' => [
444           'second_child_link' => [
445             'title' => 'Second child link',
446             'url' => Url::fromRoute('router_test.8'),
447           ],
448         ],
449       ],
450       // This should never be rendered, since the user does not have access to
451       // it.
452       'third_child' => [
453         '#theme' => 'links',
454         '#links' => [
455           'third_child_link' => [
456             'title' => 'Third child link',
457             'url' => Url::fromRoute('router_test.9'),
458           ],
459         ],
460         '#access' => FALSE,
461       ],
462     ];
463
464     // Start with a fresh copy of the base array, and try rendering the entire
465     // thing. We expect a single <ul> with appropriate links contained within
466     // it.
467     $render_array = $base_array;
468     $html = \Drupal::service('renderer')->renderRoot($render_array);
469     $dom = new \DOMDocument();
470     $dom->loadHTML($html);
471     $this->assertEqual($dom->getElementsByTagName('ul')->length, 1, 'One "ul" tag found in the rendered HTML.');
472     $list_elements = $dom->getElementsByTagName('li');
473     $this->assertEqual($list_elements->length, 3, 'Three "li" tags found in the rendered HTML.');
474     $this->assertEqual($list_elements->item(0)->nodeValue, 'Parent link original', 'First expected link found.');
475     $this->assertEqual($list_elements->item(1)->nodeValue, 'First child link', 'Second expected link found.');
476     $this->assertEqual($list_elements->item(2)->nodeValue, 'Second child link', 'Third expected link found.');
477     $this->assertIdentical(strpos($html, 'Parent link copy'), FALSE, '"Parent link copy" link not found.');
478     $this->assertIdentical(strpos($html, 'Third child link'), FALSE, '"Third child link" link not found.');
479
480     // Now render 'first_child', followed by the rest of the links, and make
481     // sure we get two separate <ul>'s with the appropriate links contained
482     // within each.
483     $render_array = $base_array;
484     $child_html = \Drupal::service('renderer')->renderRoot($render_array['first_child']);
485     $parent_html = \Drupal::service('renderer')->renderRoot($render_array);
486     // First check the child HTML.
487     $dom = new \DOMDocument();
488     $dom->loadHTML($child_html);
489     $this->assertEqual($dom->getElementsByTagName('ul')->length, 1, 'One "ul" tag found in the rendered child HTML.');
490     $list_elements = $dom->getElementsByTagName('li');
491     $this->assertEqual($list_elements->length, 2, 'Two "li" tags found in the rendered child HTML.');
492     $this->assertEqual($list_elements->item(0)->nodeValue, 'Parent link copy', 'First expected link found.');
493     $this->assertEqual($list_elements->item(1)->nodeValue, 'First child link', 'Second expected link found.');
494     // Then check the parent HTML.
495     $dom = new \DOMDocument();
496     $dom->loadHTML($parent_html);
497     $this->assertEqual($dom->getElementsByTagName('ul')->length, 1, 'One "ul" tag found in the rendered parent HTML.');
498     $list_elements = $dom->getElementsByTagName('li');
499     $this->assertEqual($list_elements->length, 2, 'Two "li" tags found in the rendered parent HTML.');
500     $this->assertEqual($list_elements->item(0)->nodeValue, 'Parent link original', 'First expected link found.');
501     $this->assertEqual($list_elements->item(1)->nodeValue, 'Second child link', 'Second expected link found.');
502     $this->assertIdentical(strpos($parent_html, 'First child link'), FALSE, '"First child link" link not found.');
503     $this->assertIdentical(strpos($parent_html, 'Third child link'), FALSE, '"Third child link" link not found.');
504   }
505
506   /**
507    * Tests theme_image().
508    */
509   public function testImage() {
510     // Test that data URIs work with theme_image().
511     $variables = [];
512     $variables['uri'] = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
513     $variables['alt'] = 'Data URI image of a red dot';
514     $expected = '<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Data URI image of a red dot" />' . "\n";
515     $this->assertThemeOutput('image', $variables, $expected);
516   }
517
518 }