Files

84 lines
3.4 KiB
PHP

<?php
declare(strict_types=1);
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Compose;
use LIT\MCP\Integrations\Divi\Compose\HtmlContext;
use PHPUnit\Framework\TestCase;
final class HtmlContextTest extends TestCase
{
/**
* HTML with the probe marked as [[…]]: whether the browser reads it as text.
*
* @return array<string, array{string, bool}>
*/
public static function probes(): array
{
return [
'plain text' => ['a [[B]] c', true],
'between tags' => ['<p>[[B]]</p>', true],
'double-quoted ">" keeps the tag' => ['<a title="A > [[B]]" href="/x">T</a>', false],
'single-quoted ">" keeps the tag' => ["<img alt='A > [[B]]' src=x>", false],
'quoted value after spaces around =' => ['<a title = "A > [[B]]">', false],
'after a quoted ">"' => ['<a title="A > B">[[T]]</a>', true],
'quote in an attribute name is no value' => ['<a b"c>[[T]]', true],
'unquoted value' => ['<a href=[[x]]>', false],
'end tag' => ['</a [[x]]>', false],
'comment' => ['<!-- a > [[B]] -->', false],
'after a comment' => ['<!-- a -->[[B]]', true],
'comment closed by --!>' => ['<!-- a --!>[[B]]', true],
'abrupt comment' => ['<!-->[[B]]', true],
'unterminated comment' => ['<!-- a [[B]]', false],
'bogus comment' => ['<!DOCTYPE [[x]]>', false],
'processing instruction' => ['<?x [[B]] >', false],
'unterminated tag' => ['<a title="x [[B]]', false],
'unterminated quote' => ['<a title="x>[[B]]</a>', false],
'lone "<"' => ['a < [[B]]', true],
'"<" + digit' => ['a <3 [[B]]', true],
'script body' => ['<script>var x = "[[B]]";</script>', false],
'after the script' => ['<script>x</script>[[B]]', true],
'script end needs a delimiter' => ['<script>x</script-x>[[B]]</script>', false],
'script end in upper case' => ['<SCRIPT>x</Script >[[B]]', true],
'double-escaped script' => ['<script><!--<script></script>[[B]]</script>', false],
'style body' => ['<style>.a{} [[B]]</style>', false],
'iframe body' => ['<iframe>[[B]]</iframe>', false],
'plaintext' => ['<plaintext></plaintext>[[B]]', false],
'textarea is text' => ['<textarea>[[B]]</textarea>', true],
];
}
/** @dataProvider probes */
public function testKnowsWhatIsText(string $marked, bool $text): void
{
$start = (int) strpos($marked, '[[');
$html = str_replace(['[[', ']]'], '', $marked);
$end = (int) strpos($marked, ']]') - 2;
$spans = HtmlContext::markupSpans($html);
self::assertSame($text, HtmlContext::isText($spans, $start, $end), $marked);
}
public function testBoundaries(): void
{
$spans = HtmlContext::markupSpans('<p>ab</p>');
self::assertSame([[0, 3], [5, 9]], $spans);
self::assertTrue(HtmlContext::isBoundary($spans, 3));
self::assertTrue(HtmlContext::isBoundary($spans, 5));
self::assertFalse(HtmlContext::isBoundary($spans, 1));
}
public function testLongInputsStayLinear(): void
{
$start = microtime(true);
foreach (['<', '<a ', '<a title="', '<!--', '<script>', '</'] as $unit) {
HtmlContext::markupSpans(str_repeat($unit, 100000));
}
self::assertLessThan(2.0, microtime(true) - $start);
}
}