ThemeRenderAndAutoescapeTest.php

Same filename in other branches
  1. 9 core/tests/Drupal/KernelTests/Core/Theme/ThemeRenderAndAutoescapeTest.php
  2. 8.9.x core/tests/Drupal/KernelTests/Core/Theme/ThemeRenderAndAutoescapeTest.php
  3. 11.x core/tests/Drupal/KernelTests/Core/Theme/ThemeRenderAndAutoescapeTest.php

Namespace

Drupal\KernelTests\Core\Theme

File

core/tests/Drupal/KernelTests/Core/Theme/ThemeRenderAndAutoescapeTest.php

View source
<?php

declare (strict_types=1);
namespace Drupal\KernelTests\Core\Theme;

use Drupal\Component\Utility\Html;
use Drupal\Core\GeneratedLink;
use Drupal\Core\Link;
use Drupal\Core\Render\RenderContext;
use Drupal\Core\Render\Markup;
use Drupal\Core\Url;
use Drupal\KernelTests\KernelTestBase;

/**
 * Tests the theme_render_and_autoescape() function.
 *
 * @group Theme
 * @group legacy
 * @group #slow
 */
class ThemeRenderAndAutoescapeTest extends KernelTestBase {
    
    /**
     * {@inheritdoc}
     */
    protected static $modules = [
        'system',
    ];
    
    /**
     * {@inheritdoc}
     */
    protected function setUp() : void {
        parent::setUp();
        $this->expectDeprecation('theme_render_and_autoescape() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. There is no replacement. Theme engines must handle escaping by themselves. See https://www.drupal.org/node/3336253');
    }
    
    /**
     * @dataProvider providerTestThemeRenderAndAutoescape
     */
    public function testThemeRenderAndAutoescape($arg, $expected) : void {
        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->assertIsString($output);
    }
    
    /**
     * Provide test examples.
     */
    public static function providerTestThemeRenderAndAutoescape() {
        return [
            'empty string unchanged' => [
                '',
                '',
            ],
            'simple string unchanged' => [
                'ab',
                'ab',
            ],
            'int (scalar) cast to string' => [
                111,
                '111',
            ],
            'float (scalar) cast to string' => [
                2.1,
                '2.1',
            ],
            '> is escaped' => [
                '>',
                '&gt;',
            ],
            'Markup EM tag is unchanged' => [
                Markup::create('<em>hi</em>'),
                '<em>hi</em>',
            ],
            'Markup SCRIPT tag is unchanged' => [
                Markup::create('<script>alert("hi");</script>'),
                '<script>alert("hi");</script>',
            ],
            'EM tag in string is escaped' => [
                '<em>hi</em>',
                Html::escape('<em>hi</em>'),
            ],
            'type link render array is rendered' => [
                [
                    '#type' => 'link',
                    '#title' => 'Text',
                    '#url' => '<none>',
                ],
                '<a href="">Text</a>',
            ],
            'type markup with EM tags is rendered' => [
                [
                    '#markup' => '<em>hi</em>',
                ],
                '<em>hi</em>',
            ],
            'SCRIPT tag in string is escaped' => [
                '<script>alert(123)</script>',
                Html::escape('<script>alert(123)</script>'),
            ],
            'type plain_text render array EM tag is escaped' => [
                [
                    '#plain_text' => '<em>hi</em>',
                ],
                Html::escape('<em>hi</em>'),
            ],
            'type hidden render array is rendered' => [
                [
                    '#type' => 'hidden',
                    '#name' => 'foo',
                    '#value' => 'bar',
                ],
                "<input type=\"hidden\" name=\"foo\" value=\"bar\" />\n",
            ],
        ];
    }
    
    /**
     * Ensures invalid content is handled correctly.
     */
    public function testThemeEscapeAndRenderNotPrintable() : void {
        $this->expectException(\Exception::class);
        theme_render_and_autoescape(new NonPrintable());
    }
    
    /**
     * Ensure cache metadata is bubbled when using theme_render_and_autoescape().
     */
    public function testBubblingMetadata() : void {
        $link = new GeneratedLink();
        $link->setGeneratedLink('<a href="http://example.com"></a>');
        $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('<a href="http://example.com"></a>', $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() : void {
        $link = new Link('', Url::fromRoute('<current>'));
        $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('<a href="/' . urlencode('<none>') . '"></a>', $output);
        
        /** @var \Drupal\Core\Render\BubbleableMetadata $metadata */
        $metadata = $context->pop();
        $this->assertEquals([
            'route',
        ], $metadata->getCacheContexts());
    }

}
class NonPrintable {

}

Classes

Title Deprecated Summary
NonPrintable
ThemeRenderAndAutoescapeTest Tests the theme_render_and_autoescape() function.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.