rebuild(); } /** * @dataProvider providerTestThemeRenderAndAutoescape */ public function testThemeRenderAndAutoescape($arg, $expected) { if (is_array($arg) && isset($arg['#type']) && $arg['#type'] === 'link') { $arg = Link::createFromRoute($arg['#title'], $arg['#url']); } $context = new RenderContext(); // Use a closure here since we need to render with a render context. $theme_render_and_autoescape = function () use ($arg) { return theme_render_and_autoescape($arg); }; /** @var \Drupal\Core\Render\RendererInterface $renderer */ $renderer = \Drupal::service('renderer'); $output = $renderer->executeInRenderContext($context, $theme_render_and_autoescape); $this->assertEquals($expected, $output); $this->assertInternalType('string', $output); } /** * Provide test examples. */ public function providerTestThemeRenderAndAutoescape() { return [ 'empty string unchanged' => ['', ''], 'simple string unchanged' => ['ab', 'ab'], 'int (scalar) cast to string' => [111, '111'], 'float (scalar) cast to string' => [2.10, '2.10'], '> is escaped' => ['>', '>'], 'Markup EM tag is unchanged' => [Markup::create('hi'), 'hi'], 'Markup SCRIPT tag is unchanged' => [Markup::create(''), ''], 'EM tag in string is escaped' => ['hi', Html::escape('hi')], 'type link render array is rendered' => [['#type' => 'link', '#title' => 'Text', '#url' => ''], 'Text'], 'type markup with EM tags is rendered' => [['#markup' => 'hi'], 'hi'], 'SCRIPT tag in string is escaped' => [ '', Html::escape(''), ], 'type plain_text render array EM tag is escaped' => [['#plain_text' => 'hi'], Html::escape('hi')], 'type hidden render array is rendered' => [['#type' => 'hidden', '#name' => 'foo', '#value' => 'bar'], "\n"], ]; } /** * Ensures invalid content is handled correctly. */ public function testThemeEscapeAndRenderNotPrintable() { $this->setExpectedException(\Exception::class); theme_render_and_autoescape(new NonPrintable()); } /** * Ensure cache metadata is bubbled when using theme_render_and_autoescape(). */ public function testBubblingMetadata() { $link = new GeneratedLink(); $link->setGeneratedLink(''); $link->addCacheTags(['foo']); $link->addAttachments(['library' => ['system/base']]); $context = new RenderContext(); // Use a closure here since we need to render with a render context. $theme_render_and_autoescape = function () use ($link) { return theme_render_and_autoescape($link); }; /** @var \Drupal\Core\Render\RendererInterface $renderer */ $renderer = \Drupal::service('renderer'); $output = $renderer->executeInRenderContext($context, $theme_render_and_autoescape); $this->assertEquals('', $output); /** @var \Drupal\Core\Render\BubbleableMetadata $metadata */ $metadata = $context->pop(); $this->assertEquals(['foo'], $metadata->getCacheTags()); $this->assertEquals(['library' => ['system/base']], $metadata->getAttachments()); } /** * Ensure cache metadata is bubbled when using theme_render_and_autoescape(). */ public function testBubblingMetadataWithRenderable() { $link = new Link('', Url::fromRoute('')); $context = new RenderContext(); // Use a closure here since we need to render with a render context. $theme_render_and_autoescape = function () use ($link) { return theme_render_and_autoescape($link); }; /** @var \Drupal\Core\Render\RendererInterface $renderer */ $renderer = \Drupal::service('renderer'); $output = $renderer->executeInRenderContext($context, $theme_render_and_autoescape); $this->assertEquals('', $output); /** @var \Drupal\Core\Render\BubbleableMetadata $metadata */ $metadata = $context->pop(); $this->assertEquals(['route'], $metadata->getCacheContexts()); } } class NonPrintable {}