627b903cb6ab15d39fe285249fab7930844094ff
[yaffs-website] / web / core / tests / Drupal / KernelTests / Core / Theme / ThemeRenderAndAutoescapeTest.php
1 <?php
2
3 /**
4  * @file
5  * Contains \Drupal\KernelTests\Core\Theme\ThemeRenderAndAutoescapeTest.
6  */
7
8 namespace Drupal\KernelTests\Core\Theme;
9
10 use Drupal\Component\Utility\Html;
11 use Drupal\Core\GeneratedLink;
12 use Drupal\Core\Link;
13 use Drupal\Core\Render\RenderContext;
14 use Drupal\Core\Render\Markup;
15 use Drupal\Core\Url;
16 use Drupal\KernelTests\KernelTestBase;
17
18 /**
19  * Tests the theme_render_and_autoescape() function.
20  *
21  * @group Theme
22  */
23 class ThemeRenderAndAutoescapeTest extends KernelTestBase {
24
25   /**
26    * {@inheritdoc}
27    */
28   public static $modules = ['system'];
29
30   /**
31    * {@inheritdoc}
32    */
33   protected function setUp() {
34     parent::setUp();
35
36     \Drupal::service('router.builder')->rebuild();
37   }
38
39   /**
40    * @dataProvider providerTestThemeRenderAndAutoescape
41    */
42   public function testThemeRenderAndAutoescape($arg, $expected) {
43     if (is_array($arg) && isset($arg['#type']) && $arg['#type'] === 'link') {
44       $arg = Link::createFromRoute($arg['#title'], $arg['#url']);
45     }
46
47     $context = new RenderContext();
48     // Use a closure here since we need to render with a render context.
49     $theme_render_and_autoescape = function () use ($arg) {
50       return theme_render_and_autoescape($arg);
51     };
52     /** @var \Drupal\Core\Render\RendererInterface $renderer */
53     $renderer = \Drupal::service('renderer');
54     $output = $renderer->executeInRenderContext($context, $theme_render_and_autoescape);
55     $this->assertEquals($expected, $output);
56     $this->assertInternalType('string', $output);
57   }
58
59   /**
60    * Provide test examples.
61    */
62   public function providerTestThemeRenderAndAutoescape() {
63     return [
64       'empty string unchanged' => ['', ''],
65       'simple string unchanged' => ['ab', 'ab'],
66       'int (scalar) cast to string' => [111, '111'],
67       'float (scalar) cast to string' => [2.10, '2.10'],
68       '> is escaped' => ['>', '&gt;'],
69       'Markup EM tag is unchanged' => [Markup::create('<em>hi</em>'), '<em>hi</em>'],
70       'Markup SCRIPT tag is unchanged' => [Markup::create('<script>alert("hi");</script>'), '<script>alert("hi");</script>'],
71       'EM tag in string is escaped' => ['<em>hi</em>', Html::escape('<em>hi</em>')],
72       'type link render array is rendered' => [['#type' => 'link', '#title' => 'Text', '#url' => '<none>'], '<a href="">Text</a>'],
73       'type markup with EM tags is rendered' => [['#markup' => '<em>hi</em>'], '<em>hi</em>'],
74       'SCRIPT tag in string is escaped' => [
75         '<script>alert(123)</script>',
76         Html::escape('<script>alert(123)</script>')
77       ],
78       'type plain_text render array EM tag is escaped' => [['#plain_text' => '<em>hi</em>'], Html::escape('<em>hi</em>')],
79       'type hidden render array is rendered' => [['#type' => 'hidden', '#name' => 'foo', '#value' => 'bar'], "<input type=\"hidden\" name=\"foo\" value=\"bar\" />\n"],
80     ];
81   }
82
83   /**
84    * Ensures invalid content is handled correctly.
85    */
86   public function testThemeEscapeAndRenderNotPrintable() {
87     $this->setExpectedException(\Exception::class);
88     theme_render_and_autoescape(new NonPrintable());
89   }
90
91   /**
92    * Ensure cache metadata is bubbled when using theme_render_and_autoescape().
93    */
94   public function testBubblingMetadata() {
95     $link = new GeneratedLink();
96     $link->setGeneratedLink('<a href="http://example.com"></a>');
97     $link->addCacheTags(['foo']);
98     $link->addAttachments(['library' => ['system/base']]);
99
100     $context = new RenderContext();
101     // Use a closure here since we need to render with a render context.
102     $theme_render_and_autoescape = function () use ($link) {
103       return theme_render_and_autoescape($link);
104     };
105     /** @var \Drupal\Core\Render\RendererInterface $renderer */
106     $renderer = \Drupal::service('renderer');
107     $output = $renderer->executeInRenderContext($context, $theme_render_and_autoescape);
108     $this->assertEquals('<a href="http://example.com"></a>', $output);
109     /** @var \Drupal\Core\Render\BubbleableMetadata $metadata */
110     $metadata = $context->pop();
111     $this->assertEquals(['foo'], $metadata->getCacheTags());
112     $this->assertEquals(['library' => ['system/base']], $metadata->getAttachments());
113   }
114
115   /**
116    * Ensure cache metadata is bubbled when using theme_render_and_autoescape().
117    */
118   public function testBubblingMetadataWithRenderable() {
119     $link = new Link('', Url::fromRoute('<current>'));
120
121     $context = new RenderContext();
122     // Use a closure here since we need to render with a render context.
123     $theme_render_and_autoescape = function () use ($link) {
124       return theme_render_and_autoescape($link);
125     };
126     /** @var \Drupal\Core\Render\RendererInterface $renderer */
127     $renderer = \Drupal::service('renderer');
128     $output = $renderer->executeInRenderContext($context, $theme_render_and_autoescape);
129     $this->assertEquals('<a href="/' . urlencode('<none>') . '"></a>', $output);
130     /** @var \Drupal\Core\Render\BubbleableMetadata $metadata */
131     $metadata = $context->pop();
132     $this->assertEquals(['route'], $metadata->getCacheContexts());
133   }
134
135 }
136
137 class NonPrintable { }