HtmlTest.php
Same filename in other branches
Namespace
Drupal\Tests\Component\UtilityFile
-
core/
tests/ Drupal/ Tests/ Component/ Utility/ HtmlTest.php
View source
<?php
declare (strict_types=1);
namespace Drupal\Tests\Component\Utility;
use Drupal\Component\Render\MarkupInterface;
use Drupal\Component\Render\MarkupTrait;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Random;
use PHPUnit\Framework\TestCase;
// cspell:ignore répét répété
/**
* Tests \Drupal\Component\Utility\Html.
*
* @group Common
*
* @coversDefaultClass \Drupal\Component\Utility\Html
*/
class HtmlTest extends TestCase {
/**
* {@inheritdoc}
*/
protected function setUp() : void {
parent::setUp();
$property = new \ReflectionProperty('Drupal\\Component\\Utility\\Html', 'seenIdsInit');
$property->setValue(NULL, NULL);
}
/**
* Tests the Html::cleanCssIdentifier() method.
*
* @param string $expected
* The expected result.
* @param string $source
* The string being transformed to an ID.
* @param array|null $filter
* (optional) An array of string replacements to use on the identifier. If
* NULL, no filter will be passed and a default will be used.
*
* @dataProvider providerTestCleanCssIdentifier
*
* @covers ::cleanCssIdentifier
*/
public function testCleanCssIdentifier($expected, $source, $filter = NULL) : void {
if ($filter !== NULL) {
$this->assertSame($expected, Html::cleanCssIdentifier($source, $filter));
}
else {
$this->assertSame($expected, Html::cleanCssIdentifier($source));
}
}
/**
* Provides test data for testCleanCssIdentifier().
*
* @return array
* Test data.
*/
public static function providerTestCleanCssIdentifier() {
$id1 = 'abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789';
$id2 = '¡¢£¤¥';
$id3 = 'css__identifier__with__double__underscores';
return [
// Verify that no valid ASCII characters are stripped from the identifier.
[
$id1,
$id1,
[],
],
// Verify that valid UTF-8 characters are not stripped from the identifier.
[
$id2,
$id2,
[],
],
// Verify that double underscores are not stripped from the identifier.
[
$id3,
$id3,
],
// Verify that invalid characters (including non-breaking space) are
// stripped from the identifier.
[
'invalid_identifier',
'invalid_ !"#$%&\'()*+,./:;<=>?@[\\]^`{|}~ identifier',
[],
],
// Verify that an identifier starting with a digit is replaced.
[
'_css_identifier',
'1css_identifier',
[],
],
// Verify that an identifier starting with a hyphen followed by a digit is
// replaced.
[
'__css_identifier',
'-1css_identifier',
[],
],
// Verify that an identifier starting with two hyphens is replaced.
[
'__css_identifier',
'--css_identifier',
[],
],
// Verify that passing double underscores as a filter is processed.
[
'_css_identifier',
'__css_identifier',
[
'__' => '_',
],
],
];
}
/**
* Tests that Html::getClass() cleans the class name properly.
*
* @covers ::getClass
*/
public function testHtmlClass() : void {
// Verify Drupal coding standards are enforced.
$this->assertSame('class-name--ü', Html::getClass('CLASS NAME_[Ü]'), 'Enforce Drupal coding standards.');
// Test Html::getClass() handles Drupal\Component\Render\MarkupInterface
// input.
$markup = HtmlTestMarkup::create('CLASS_FROM_OBJECT');
$this->assertSame('class-from-object', Html::getClass($markup), 'Markup object is converted to CSS class.');
}
/**
* Tests the Html::getUniqueId() method.
*
* @param string $expected
* The expected result.
* @param string $source
* The string being transformed to an ID.
* @param bool $reset
* (optional) If TRUE, reset the list of seen IDs. Defaults to FALSE.
*
* @dataProvider providerTestHtmlGetUniqueId
*
* @covers ::getUniqueId
*/
public function testHtmlGetUniqueId($expected, $source, $reset = FALSE) : void {
if ($reset) {
Html::resetSeenIds();
}
$this->assertSame($expected, Html::getUniqueId($source));
}
/**
* Provides test data for testHtmlGetId().
*
* @return array
* Test data.
*/
public static function providerTestHtmlGetUniqueId() {
// cSpell:disable
$id = 'abcdefghijklmnopqrstuvwxyz-0123456789';
return [
// Verify that letters, digits, and hyphens are not stripped from the ID.
[
$id,
$id,
],
// Verify that invalid characters are stripped from the ID.
[
'invalididentifier',
'invalid,./:@\\^`{Üidentifier',
],
// Verify Drupal coding standards are enforced.
[
'id-name-1',
'ID NAME_[1]',
],
// Verify that a repeated ID is made unique.
[
'test-unique-id',
'test-unique-id',
TRUE,
],
[
'test-unique-id--2',
'test-unique-id',
],
[
'test-unique-id--3',
'test-unique-id',
],
];
// cSpell:enable
}
/**
* Tests the Html::getUniqueId() method.
*
* @param string $expected
* The expected result.
* @param string $source
* The string being transformed to an ID.
*
* @dataProvider providerTestHtmlGetUniqueIdWithAjaxIds
*
* @covers ::getUniqueId
*/
public function testHtmlGetUniqueIdWithAjaxIds($expected, $source) : void {
Html::setIsAjax(TRUE);
$id = Html::getUniqueId($source);
// Note, we truncate two hyphens at the end.
// @see \Drupal\Component\Utility\Html::getId()
if (str_contains($source, '--')) {
$random_suffix = substr($id, strlen($source) + 1);
}
else {
$random_suffix = substr($id, strlen($source) + 2);
}
$expected = $expected . $random_suffix;
$this->assertSame($expected, $id);
}
/**
* Provides test data for testHtmlGetId().
*
* @return array
* Test data.
*/
public static function providerTestHtmlGetUniqueIdWithAjaxIds() {
return [
[
'test-unique-id1--',
'test-unique-id1',
],
// Note, we truncate two hyphens at the end.
// @see \Drupal\Component\Utility\Html::getId()
[
'test-unique-id1---',
'test-unique-id1--',
],
[
'test-unique-id2--',
'test-unique-id2',
],
];
}
/**
* Tests the Html::getUniqueId() method.
*
* @param string $expected
* The expected result.
* @param string $source
* The string being transformed to an ID.
*
* @dataProvider providerTestHtmlGetId
*
* @covers ::getId
*/
public function testHtmlGetId($expected, $source) : void {
Html::setIsAjax(FALSE);
$this->assertSame($expected, Html::getId($source));
}
/**
* Provides test data for testHtmlGetId().
*
* @return array
* Test data.
*/
public static function providerTestHtmlGetId() {
// cSpell:disable
$id = 'abcdefghijklmnopqrstuvwxyz-0123456789';
return [
// Verify that letters, digits, and hyphens are not stripped from the ID.
[
$id,
$id,
],
// Verify that invalid characters are stripped from the ID.
[
'invalididentifier',
'invalid,./:@\\^`{Üidentifier',
],
// Verify Drupal coding standards are enforced.
[
'id-name-1',
'ID NAME_[1]',
],
// Verify that a repeated ID is made unique.
[
'test-unique-id',
'test-unique-id',
],
[
'test-unique-id',
'test-unique-id',
],
];
// cSpell:enable
}
/**
* Tests Html::decodeEntities().
*
* @dataProvider providerDecodeEntities
* @covers ::decodeEntities
*/
public function testDecodeEntities($text, $expected) : void {
$this->assertEquals($expected, Html::decodeEntities($text));
}
/**
* Data provider for testDecodeEntities().
*
* @see testDecodeEntities()
*/
public static function providerDecodeEntities() {
return [
[
'Drupal',
'Drupal',
],
[
'<script>',
'<script>',
],
[
'<script>',
'<script>',
],
[
'<script>',
'<script>',
],
[
'&lt;script&gt;',
'<script>',
],
[
'"',
'"',
],
[
'"',
'"',
],
[
'&#34;',
'"',
],
[
'"',
'"',
],
[
'&quot;',
'"',
],
[
"'",
"'",
],
[
''',
"'",
],
[
'&#39;',
''',
],
[
'©',
'©',
],
[
'©',
'©',
],
[
'©',
'©',
],
[
'→',
'→',
],
[
'→',
'→',
],
[
'➼',
'➼',
],
[
'➼',
'➼',
],
[
'€',
'€',
],
];
}
/**
* Tests Html::escape().
*
* @dataProvider providerEscape
* @covers ::escape
*/
public function testEscape($expected, $text) : void {
$this->assertEquals($expected, Html::escape($text));
}
/**
* Data provider for testEscape().
*
* @see testEscape()
*/
public static function providerEscape() {
return [
[
'Drupal',
'Drupal',
],
[
'<script>',
'<script>',
],
[
'&lt;script&gt;',
'<script>',
],
[
'&#34;',
'"',
],
[
'"',
'"',
],
[
'&quot;',
'"',
],
[
''',
"'",
],
[
'&#039;',
''',
],
[
'©',
'©',
],
[
'→',
'→',
],
[
'➼',
'➼',
],
[
'€',
'€',
],
// cspell:disable-next-line
[
'Drup�al',
"Drup\x80al",
],
];
}
/**
* Tests relationship between escaping and decoding HTML entities.
*
* @covers ::decodeEntities
* @covers ::escape
*/
public function testDecodeEntitiesAndEscape() : void {
$string = "<em>répété</em>";
$escaped = Html::escape($string);
$this->assertSame('<em>répét&eacute;</em>', $escaped);
$decoded = Html::decodeEntities($escaped);
$this->assertSame('<em>répété</em>', $decoded);
$decoded = Html::decodeEntities($decoded);
$this->assertSame('<em>répété</em>', $decoded);
$escaped = Html::escape($decoded);
$this->assertSame('<em>répété</em>', $escaped);
}
/**
* Tests Html::serialize().
*
* Resolves an issue by where an empty DOMDocument object sent to serialization would
* cause errors in getElementsByTagName() in the serialization function.
*
* @covers ::serialize
*/
public function testSerialize() : void {
$document = new \DOMDocument();
$result = Html::serialize($document);
$this->assertSame('', $result);
}
/**
* @covers ::transformRootRelativeUrlsToAbsolute
* @dataProvider providerTestTransformRootRelativeUrlsToAbsolute
*/
public function testTransformRootRelativeUrlsToAbsolute($html, $scheme_and_host, $expected_html) : void {
$this->assertSame($expected_html ?: $html, Html::transformRootRelativeUrlsToAbsolute($html, $scheme_and_host));
}
/**
* @covers ::transformRootRelativeUrlsToAbsolute
* @dataProvider providerTestTransformRootRelativeUrlsToAbsoluteAssertion
*/
public function testTransformRootRelativeUrlsToAbsoluteAssertion($scheme_and_host) : void {
$this->expectException(\AssertionError::class);
Html::transformRootRelativeUrlsToAbsolute('', $scheme_and_host);
}
/**
* Provides test data for testTransformRootRelativeUrlsToAbsolute().
*
* @return array
* Test data.
*/
public static function providerTestTransformRootRelativeUrlsToAbsolute() {
$data = [];
// Random generator.
$random = new Random();
// One random tag name.
$tag_name = strtolower($random->name(8, TRUE));
// A site installed either in the root of a domain or a subdirectory.
$base_paths = [
'/',
'/subdir/' . $random->name(8, TRUE) . '/',
];
foreach ($base_paths as $base_path) {
// The only attribute that has more than just a URL as its value, is
// 'srcset', so special-case it.
$data += [
"{$tag_name}, srcset, {$base_path}: root-relative" => [
"<{$tag_name} srcset=\"http://example.com{$base_path}already-absolute 200w, {$base_path}root-relative 300w\">root-relative test</{$tag_name}>",
'http://example.com',
"<{$tag_name} srcset=\"http://example.com{$base_path}already-absolute 200w, http://example.com{$base_path}root-relative 300w\">root-relative test</{$tag_name}>",
],
"{$tag_name}, srcset, {$base_path}: protocol-relative" => [
"<{$tag_name} srcset=\"http://example.com{$base_path}already-absolute 200w, //example.com{$base_path}protocol-relative 300w\">protocol-relative test</{$tag_name}>",
'http://example.com',
FALSE,
],
"{$tag_name}, srcset, {$base_path}: absolute" => [
"<{$tag_name} srcset=\"http://example.com{$base_path}already-absolute 200w, http://example.com{$base_path}absolute 300w\">absolute test</{$tag_name}>",
'http://example.com',
FALSE,
],
"{$tag_name}, empty srcset" => [
"<{$tag_name} srcset>empty test</{$tag_name}>",
'http://example.com',
FALSE,
],
];
foreach ([
'href',
'poster',
'src',
'cite',
'data',
'action',
'formaction',
'about',
] as $attribute) {
$data += [
"{$tag_name}, {$attribute}, {$base_path}: root-relative" => [
"<{$tag_name} {$attribute}=\"{$base_path}root-relative\">root-relative test</{$tag_name}>",
'http://example.com',
"<{$tag_name} {$attribute}=\"http://example.com{$base_path}root-relative\">root-relative test</{$tag_name}>",
],
"{$tag_name}, {$attribute}, {$base_path}: protocol-relative" => [
"<{$tag_name} {$attribute}=\"//example.com{$base_path}protocol-relative\">protocol-relative test</{$tag_name}>",
'http://example.com',
FALSE,
],
"{$tag_name}, {$attribute}, {$base_path}: absolute" => [
"<{$tag_name} {$attribute}=\"http://example.com{$base_path}absolute\">absolute test</{$tag_name}>",
'http://example.com',
FALSE,
],
];
}
}
// Double-character carriage return should be normalized.
$data['line break with double special character'] = [
"Test without links but with\r\nsome special characters",
'http://example.com',
"Test without links but with\nsome special characters",
];
$data['line break with single special character'] = [
"Test without links but with \nsome special characters",
'http://example.com',
"Test without links but with\nsome special characters",
];
$data['carriage return within html'] = [
"<a\rhref='/node'>My link</a>",
'http://example.com',
'<a href="http://example.com/node">My link</a>',
];
return $data;
}
/**
* Provides test data for testTransformRootRelativeUrlsToAbsoluteAssertion().
*
* @return array
* Test data.
*/
public static function providerTestTransformRootRelativeUrlsToAbsoluteAssertion() {
return [
'only relative path' => [
'llama',
],
'only root-relative path' => [
'/llama',
],
'host and path' => [
'example.com/llama',
],
'scheme, host and path' => [
'http://example.com/llama',
],
];
}
}
/**
* Marks an object's __toString() method as returning markup.
*/
class HtmlTestMarkup implements MarkupInterface {
use MarkupTrait;
}
Classes
Title | Deprecated | Summary |
---|---|---|
HtmlTest | Tests \Drupal\Component\Utility\Html. | |
HtmlTestMarkup | Marks an object's __toString() method as returning markup. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.