Dustin Wilson
2 years ago
28 changed files with 161 additions and 3559 deletions
@ -1,239 +0,0 @@ |
|||
<?php |
|||
/** |
|||
* @license MIT |
|||
* Copyright 2017 Dustin Wilson, J. King, et al. |
|||
* See LICENSE and AUTHORS files for details |
|||
*/ |
|||
|
|||
declare(strict_types=1); |
|||
namespace MensBeam\HTML\DOM\TestCase; |
|||
|
|||
use MensBeam\HTML\DOM\{ |
|||
Document, |
|||
Element, |
|||
Exception |
|||
}; |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\ChildNode */ |
|||
class TestChildNode extends \PHPUnit\Framework\TestCase { |
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\ChildNode::after |
|||
* @covers \MensBeam\HTML\DOM\ChildNode::before |
|||
* @covers \MensBeam\HTML\DOM\ChildNode::replaceWith |
|||
* @covers \MensBeam\HTML\DOM\NodeTrait::convertNodesToNode |
|||
*/ |
|||
public function testAfterBeforeReplaceWith(): void { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$div = $d->body->appendChild($d->createElement('div')); |
|||
$o = $d->body->appendChild($d->createTextNode('ook')); |
|||
$div2 = $d->body->appendChild($d->createElement('div')); |
|||
|
|||
// On node with parent |
|||
$div->after($d->createElement('span'), $o, 'eek'); |
|||
$this->assertSame('<body><div></div><span></span>ookeek<div></div></body>', (string)$d->body); |
|||
$div->after($o); |
|||
$this->assertSame('<body><div></div>ook<span></span>eek<div></div></body>', (string)$d->body); |
|||
|
|||
// On node with no parent |
|||
$c = $d->createComment('ook'); |
|||
$this->assertNull($c->after($d->createTextNode('ook'))); |
|||
|
|||
// On node with parent |
|||
$br = $d->body->insertBefore($d->createElement('br'), $div); |
|||
$e = $d->createTextNode('eek'); |
|||
$div->before($d->createElement('span'), $o, 'eek', $e, $br); |
|||
$this->assertSame('<body><span></span>ookeekeek<br><div></div><span></span>eek<div></div></body>', (string)$d->body); |
|||
$div->before($o); |
|||
$this->assertSame('<body><span></span>eekeek<br>ook<div></div><span></span>eek<div></div></body>', (string)$d->body); |
|||
|
|||
// On node with no parent |
|||
$c = $d->createComment('ook'); |
|||
$this->assertNull($c->before($d->createTextNode('ook'))); |
|||
|
|||
// On node with parent |
|||
$s = $d->createElement('span'); |
|||
$br->replaceWith('ack', $o, $e, $s); |
|||
$this->assertSame('<body><span></span>eekackookeek<span></span><div></div><span></span>eek<div></div></body>', (string)$d->body); |
|||
$s->replaceWith($o); |
|||
$this->assertSame('<body><span></span>eekackeekook<div></div><span></span>eek<div></div></body>', (string)$d->body); |
|||
|
|||
// On node with no parent |
|||
$c = $d->createComment('ook'); |
|||
$this->assertNull($c->replaceWith($d->createTextNode('ook'))); |
|||
|
|||
// Parent within node |
|||
$o->replaceWith('poo', $o, $e); |
|||
$this->assertSame('<body><span></span>eekackpooookeek<div></div><span></span>eek<div></div></body>', (string)$d->body); |
|||
} |
|||
|
|||
|
|||
public function provideAfterBeforeReplaceWithFailures(): array { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$div = $d->body->appendChild($d->createElement('div')); |
|||
|
|||
return [ |
|||
[ function() use($div) { |
|||
$div->after(false); |
|||
} ], |
|||
[ function() use($div) { |
|||
$div->before(false); |
|||
} ], |
|||
[ function() use($div) { |
|||
$div->replaceWith(false); |
|||
} ], |
|||
[ function() use($div) { |
|||
$div->after(new \DateTime); |
|||
} ], |
|||
[ function() use($div) { |
|||
$div->before(new \DateTime); |
|||
} ], |
|||
[ function() use($div) { |
|||
$div->replaceWith(new \DateTime); |
|||
} ] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideAfterBeforeReplaceWithFailures |
|||
* @covers \MensBeam\HTML\DOM\ChildNode::after |
|||
* @covers \MensBeam\HTML\DOM\ChildNode::before |
|||
* @covers \MensBeam\HTML\DOM\ChildNode::replaceWith |
|||
*/ |
|||
public function testAfterBeforeReplaceWithFailures(\Closure $closure): void { |
|||
$this->expectException(Exception::class); |
|||
$this->expectExceptionCode(Exception::ARGUMENT_TYPE_ERROR); |
|||
$closure(); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\ChildNode::moonwalk */ |
|||
public function testMoonwalk(): void { |
|||
// Test removal of elements when moonwalking |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$div = $d->body->appendChild($d->createElement('div')); |
|||
$div = $div->appendChild($d->createElement('div')); |
|||
$div = $div->appendChild($d->createElement('div')); |
|||
$div->setAttribute('class', 'delete-me'); |
|||
$div = $div->appendChild($d->createElement('div')); |
|||
$t = $div->appendChild($d->createTextNode('ook')); |
|||
|
|||
$divs = $t->moonwalk(function($n) { |
|||
return ($n instanceof Element && $n->nodeName === 'div'); |
|||
}); |
|||
|
|||
foreach ($divs as $div) { |
|||
if ($div->getAttribute('class') === 'delete-me') { |
|||
$div->parentNode->removeChild($div); |
|||
} |
|||
} |
|||
|
|||
$this->assertSame('<body><div><div></div></div></body>', (string)$d->body); |
|||
|
|||
// Test moonwalking through template barriers |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$t = $d->body->appendChild($d->createElement('template')); |
|||
|
|||
$w = $t->content->appendChild($d->createTextNode('ook'))->moonwalk(); |
|||
$this->assertTrue($t->content->isSameNode($w->current())); |
|||
$w->next(); |
|||
$this->assertTrue($t->isSameNode($w->current())); |
|||
} |
|||
|
|||
public function provideMoonwalkFailures(): iterable { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$d->body->innerHTML = '<header><h1>Ook</h1></header><main><h2>Eek</h2><p>Ook <a href="ook">eek</a>, ook?</p></main><footer></footer>'; |
|||
$main = $d->body->getElementsByTagName('main')->item(0); |
|||
|
|||
return [ |
|||
[ function() use ($main) { |
|||
$main->moonwalk(function($n) { |
|||
return 'ook'; |
|||
})->current(); |
|||
} ], |
|||
[ function() use ($main) { |
|||
$main->moonwalk(function($n) { |
|||
return new \DateTime(); |
|||
})->current(); |
|||
} ] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideMoonwalkFailures |
|||
* @covers \MensBeam\HTML\DOM\DOMException::__construct |
|||
* @covers \MensBeam\HTML\DOM\ChildNode::moonwalk |
|||
*/ |
|||
public function testMoonwalkFailures(\Closure $closure): void { |
|||
$this->expectException(Exception::class); |
|||
$this->expectExceptionCode(Exception::CLOSURE_RETURN_TYPE_ERROR); |
|||
$closure(); |
|||
} |
|||
|
|||
|
|||
public function provideWalkFailures(): iterable { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$d->body->innerHTML = '<header><h1>Ook</h1></header><main><h2>Eek</h2><p>Ook <a href="ook">eek</a>, ook?</p></main><footer></footer>'; |
|||
|
|||
return [ |
|||
[ function() use ($d) { |
|||
$d->body->firstChild->walkFollowing(function($n) { |
|||
return 'ook'; |
|||
})->current(); |
|||
} ], |
|||
[ function() use ($d) { |
|||
$d->body->firstChild->walkFollowing(function($n) { |
|||
return new \DateTime(); |
|||
})->current(); |
|||
} ], |
|||
[ function() use ($d) { |
|||
$d->body->lastChild->walkPreceding(function($n) { |
|||
return 'ook'; |
|||
})->current(); |
|||
} ], |
|||
[ function() use ($d) { |
|||
$d->body->lastChild->walkPreceding(function($n) { |
|||
return new \DateTime(); |
|||
})->current(); |
|||
} ] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideWalkFailures |
|||
* @covers \MensBeam\HTML\DOM\DOMException::__construct |
|||
* @covers \MensBeam\HTML\DOM\ChildNode::walkFollowing |
|||
* @covers \MensBeam\HTML\DOM\ChildNode::walkPreceding |
|||
*/ |
|||
public function testWalkFailures(\Closure $closure): void { |
|||
$this->expectException(Exception::class); |
|||
$this->expectExceptionCode(Exception::CLOSURE_RETURN_TYPE_ERROR); |
|||
$closure(); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\ParentNode::walk */ |
|||
public function testWalkPreceding(): void { |
|||
// Test removal of elements when walking |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$d->body->innerHTML = '<header><h1>Ook</h1></header><main><h2>Eek</h2><p>Ook <a href="ook">eek</a>, ook?</p></main><footer></footer>'; |
|||
|
|||
$this->assertNotNull($d->body->lastChild->walkPreceding(function($n) { |
|||
return ($n instanceof Element && $n->nodeName === 'main'); |
|||
}, true)->current()); |
|||
} |
|||
} |
@ -1,532 +0,0 @@ |
|||
<?php |
|||
/** |
|||
* @license MIT |
|||
* Copyright 2017 Dustin Wilson, J. King, et al. |
|||
* See LICENSE and AUTHORS files for details |
|||
*/ |
|||
|
|||
declare(strict_types=1); |
|||
namespace MensBeam\HTML\DOM\TestCase; |
|||
|
|||
use MensBeam\HTML\DOM\{ |
|||
Document, |
|||
DOMException, |
|||
Element, |
|||
ElementMap, |
|||
Exception, |
|||
HTMLTemplateElement |
|||
}; |
|||
use MensBeam\HTML\Parser, |
|||
org\bovigo\vfs\vfsStream; |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\Document */ |
|||
class TestDocument extends \PHPUnit\Framework\TestCase { |
|||
/** @covers \MensBeam\HTML\DOM\Document::adoptNode */ |
|||
public function testAdoptNode() { |
|||
$d = new Document(); |
|||
$t = $d->createElement('template'); |
|||
|
|||
$d2 = new Document(); |
|||
$t2 = $d2->adoptNode($t, true); |
|||
$this->assertSame($d2, $t2->ownerDocument); |
|||
$this->assertNull($t->parentNode); |
|||
|
|||
/*$d = new \DOMDocument(); |
|||
$t = $d->createElement('template'); |
|||
// Add a child template to cover recursive template conversions. |
|||
$t->appendChild($d->createElement('template')); |
|||
$this->assertSame(\DOMElement::class, $t::class); |
|||
|
|||
$d2 = new Document(); |
|||
$t2 = $d2->importNode($t, true); |
|||
$this->assertSame(HTMLTemplateElement::class, $t2::class);*/ |
|||
} |
|||
|
|||
public function provideAttributeNodeCreation(): iterable { |
|||
return [ |
|||
[ 'test', 'test' ], |
|||
[ 'TEST', 'test' ], |
|||
[ 'test:test', 'testU00003Atest' ], |
|||
[ 'TEST:TEST', 'testU00003Atest' ] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideAttributeNodeCreation |
|||
* @covers \MensBeam\HTML\DOM\Document::createAttribute |
|||
*/ |
|||
public function testAttributeNodeCreation(string $nameIn, string $local): void { |
|||
// Test without a document element and with |
|||
$d = new Document(); |
|||
$a = $d->createAttribute($nameIn); |
|||
$this->assertSame($local, $a->localName); |
|||
|
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$a = $d->createAttribute($nameIn); |
|||
$this->assertSame($local, $a->localName); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Document::createAttribute |
|||
* @covers \MensBeam\HTML\DOM\DOMException::__construct |
|||
*/ |
|||
public function testAttributeNodeCreationFailure(): void { |
|||
$this->expectException(DOMException::class); |
|||
$this->expectExceptionCode(DOMException::INVALID_CHARACTER); |
|||
$d = new Document(); |
|||
$d->createAttribute('<ook>'); |
|||
} |
|||
|
|||
|
|||
public function provideAttributeNodeNSCreation(): iterable { |
|||
return [ |
|||
[ 'fake_ns', 'test', 'fake_ns', '', 'test' ], |
|||
[ 'fake_ns', 'test:test', 'fake_ns', 'test', 'test' ], |
|||
[ 'fake_ns', 'TEST:TEST', 'fake_ns', 'TEST', 'TEST' ], |
|||
[ 'another_fake_ns', 'steaming💩:poop💩', 'another_fake_ns', 'steamingU01F4A9', 'poopU01F4A9' ], |
|||
// An empty string for a prefix is technically incorrect, but we cannot fix that. |
|||
[ '', 'poop💩', null, '', 'poopU01F4A9' ], |
|||
// An empty string for a prefix is technically incorrect, but we cannot fix that. |
|||
[ null, 'poop💩', null, '', 'poopU01F4A9' ] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideAttributeNodeNSCreation |
|||
* @covers \MensBeam\HTML\DOM\Document::createAttributeNS |
|||
* @covers \MensBeam\HTML\DOM\Document::validateAndExtract |
|||
*/ |
|||
public function testAttributeNodeNSCreation(?string $nsIn, string $nameIn, ?string $nsExpected, ?string $prefixExpected, string $localNameExpected): void { |
|||
// Test without a document element and with |
|||
$d = new Document(); |
|||
$a = $d->createAttributeNS($nsIn, $nameIn); |
|||
$this->assertSame($nsExpected, $a->namespaceURI); |
|||
$this->assertSame($prefixExpected, $a->prefix); |
|||
$this->assertSame($localNameExpected, $a->localName); |
|||
|
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$a = $d->createAttributeNS($nsIn, $nameIn); |
|||
$this->assertSame($nsExpected, $a->namespaceURI); |
|||
$this->assertSame($prefixExpected, $a->prefix); |
|||
$this->assertSame($localNameExpected, $a->localName); |
|||
} |
|||
|
|||
|
|||
public function provideDisabledMethods(): iterable { |
|||
return [ |
|||
[ 'createCDATASection', 'ook' ], |
|||
[ 'createEntityReference', 'ook' ], |
|||
[ 'loadXML', 'ook' ], |
|||
[ 'registerNodeClass', 'ook', null ], |
|||
[ 'relaxNGValidate', 'ook' ], |
|||
[ 'relaxNGValidateSource', 'ook' ], |
|||
[ 'saveXML', null ], |
|||
[ 'schemaValidate', 'ook', 0 ], |
|||
[ 'schemaValidateSource', 'ook', 0 ], |
|||
[ 'validate', null ], |
|||
[ 'xinclude', null ], |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideDisabledMethods |
|||
* @covers \MensBeam\HTML\DOM\Document::createEntityReference |
|||
* @covers \MensBeam\HTML\DOM\Document::loadXML |
|||
* @covers \MensBeam\HTML\DOM\Document::saveXML |
|||
* @covers \MensBeam\HTML\DOM\Document::validate |
|||
* @covers \MensBeam\HTML\DOM\Document::xinclude |
|||
* @covers \MensBeam\HTML\DOM\DOMException::__construct |
|||
*/ |
|||
public function testDisabledMethods(string $methodName, ...$arguments): void { |
|||
$this->expectException(Exception::class); |
|||
$this->expectExceptionCode(Exception::DISABLED_METHOD); |
|||
$d = new Document(); |
|||
$d->$methodName(...$arguments); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Document::__construct |
|||
* @covers \MensBeam\HTML\DOM\Document::convertTemplate |
|||
* @covers \MensBeam\HTML\DOM\Document::load |
|||
* @covers \MensBeam\HTML\DOM\Document::loadDOM |
|||
* @covers \MensBeam\HTML\DOM\Document::loadHTML |
|||
* @covers \MensBeam\HTML\DOM\Document::loadHTMLFile |
|||
* @covers \MensBeam\HTML\DOM\Document::preInsertionValidity |
|||
* @covers \MensBeam\HTML\DOM\Document::replaceTemplates |
|||
* @covers \MensBeam\HTML\DOM\Document::__get_compatMode |
|||
* @covers \MensBeam\HTML\DOM\Document::__get_URL |
|||
* @covers \MensBeam\HTML\DOM\NodeTrait::getRootNode |
|||
*/ |
|||
public function testDocumentCreation(): void { |
|||
// Test null source |
|||
$d = new Document(); |
|||
$this->assertSame('MensBeam\HTML\DOM\Document', get_class($d)); |
|||
$this->assertSame(null, $d->firstChild); |
|||
|
|||
// Test compatibility mode |
|||
$d = new Document('<html><body>Ook!</body></html>'); |
|||
$this->assertSame('BackCompat', $d->compatMode); |
|||
|
|||
// Test DOM source |
|||
$d = new \DOMDocument(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d2 = new Document(); |
|||
$d2->appendChild($d2->createElement('html')); |
|||
$d2->loadDOM($d); |
|||
$d3 = new Document($d); |
|||
$this->assertSame('MensBeam\HTML\DOM\Element', get_class($d3->firstChild)); |
|||
$this->assertSame('html', $d3->firstChild->nodeName); |
|||
|
|||
// Test file source |
|||
$vfs = vfsStream::setup('DOM', 0777, [ 'test.html' => <<<HTML |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="ISO-2022-JP"> |
|||
<title>Ook</title> |
|||
</head> |
|||
</html> |
|||
HTML ]); |
|||
$f = $vfs->url() . '/test.html'; |
|||
|
|||
// Test nonexistent file source |
|||
$d = new Document(); |
|||
$this->assertFalse(@$d->load('fileDoesNotExist.html')); |
|||
$d->load($f); |
|||
$this->assertNotNull($d->documentElement); |
|||
$this->assertSame('ISO-2022-JP', $d->charset); |
|||
|
|||
// Test http source |
|||
$d = new Document(); |
|||
$d->load('https://google.com'); |
|||
$this->assertNotNull($d->documentElement); |
|||
$this->assertSame('UTF-8', $d->charset); |
|||
$this->assertSame('https://google.com', $d->URL); |
|||
$this->assertNull($d->documentURI); |
|||
|
|||
// Test document encoding |
|||
$d = new Document(); |
|||
$d->loadHTMLFile($f, null, 'UTF-8'); |
|||
$this->assertSame('UTF-8', $d->charset); |
|||
|
|||
// Test real document loading |
|||
$d = new Document(); |
|||
$d->loadHTMLFile(dirname(__FILE__) . '/../test.html', null, 'UTF-8'); |
|||
$this->assertStringStartsWith('file://', $d->URL); |
|||
|
|||
// Test templates in source |
|||
$d = new Document('<!DOCTYPE html><html><body><template class="test"><template></template></template></body></html>'); |
|||
$t = $d->getElementsByTagName('template')->item(0); |
|||
$this->assertSame(HTMLTemplateElement::class, get_class($t)); |
|||
$this->assertSame(HTMLTemplateElement::class, get_class($t->content->firstChild)); |
|||
} |
|||
|
|||
|
|||
public function provideElementCreation(): iterable { |
|||
return [ |
|||
// HTML element |
|||
[ 'div', 'div', Element::class ], |
|||
// HTML element and uppercase qualified name |
|||
[ 'DIV', 'div', Element::class ], |
|||
// Template element |
|||
[ 'template', 'template', HTMLTemplateElement::class ], |
|||
// Template element and uppercase qualified name |
|||
[ 'TEMPLATE', 'template', HTMLTemplateElement::class ], |
|||
// Name coercion |
|||
[ 'poop💩', 'poopU01F4A9', Element::class ] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideElementCreation |
|||
* @covers \MensBeam\HTML\DOM\Document::createElement |
|||
*/ |
|||
public function testElementCreation(string $nameIn, string $nameExpected, string $classExpected): void { |
|||
$d = new Document; |
|||
$n = $d->createElement($nameIn); |
|||
$this->assertInstanceOf($classExpected, $n); |
|||
$this->assertNotNull($n->ownerDocument); |
|||
$this->assertSame($nameExpected, $n->nodeName); |
|||
} |
|||
|
|||
|
|||
public function provideElementCreationFailures(): iterable { |
|||
return [ |
|||
[ function() { |
|||
$d = new Document(); |
|||
$d->createElement('ook', 'FAIL'); |
|||
}, DOMException::NOT_SUPPORTED ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$d->createElement('<ook>'); |
|||
}, DOMException::INVALID_CHARACTER ] |
|||
]; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @dataProvider provideElementCreationFailures |
|||
* @covers \MensBeam\HTML\DOM\Document::__construct |
|||
* @covers \MensBeam\HTML\DOM\DOMException::__construct |
|||
*/ |
|||
public function testElementCreationFailures(\Closure $closure, int $errorCode): void { |
|||
$this->expectException(DOMException::class); |
|||
$this->expectExceptionCode($errorCode); |
|||
$closure(); |
|||
} |
|||
|
|||
|
|||
public function provideElementCreationNS(): iterable { |
|||
return [ |
|||
// HTML element with a null namespace |
|||
[ null, null, 'div', 'div', Element::class ], |
|||
// Template element with a null namespace |
|||
[ null, null, 'template', 'template', HTMLTemplateElement::class ], |
|||
// Template element with a null namespace and uppercase name |
|||
[ null, null, 'TEMPLATE', 'TEMPLATE', HTMLTemplateElement::class ], |
|||
// Template element |
|||
[ Parser::HTML_NAMESPACE, Parser::HTML_NAMESPACE, 'template', 'template', HTMLTemplateElement::class ], |
|||
// SVG element with SVG namespace |
|||
[ Parser::SVG_NAMESPACE, Parser::SVG_NAMESPACE, 'svg', 'svg', Element::class ], |
|||
// SVG element with SVG namespace and uppercase local name |
|||
[ Parser::SVG_NAMESPACE, Parser::SVG_NAMESPACE, 'SVG', 'SVG', Element::class ], |
|||
// Name coercion |
|||
[ 'steaming💩', 'steaming💩', 'poop💩', 'poopU01F4A9', Element::class ] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideElementCreationNS |
|||
* @covers \MensBeam\HTML\DOM\Document::createElementNS |
|||
* @covers \MensBeam\HTML\DOM\Document::validateAndExtract |
|||
*/ |
|||
public function testElementCreationNS(?string $nsIn, ?string $nsExpected, string $localNameIn, string $localNameExpected, string $classExpected): void { |
|||
$d = new Document(); |
|||
$n = $d->createElementNS($nsIn, $localNameIn); |
|||
$this->assertInstanceOf($classExpected, $n); |
|||
$this->assertNotNull($n->ownerDocument); |
|||
$this->assertSame($nsExpected, $n->namespaceURI); |
|||
$this->assertSame($localNameExpected, $n->localName); |
|||
} |
|||
|
|||
|
|||
public function provideElementCreationNSFailures(): iterable { |
|||
return [ |
|||
[ function() { |
|||
$d = new Document(); |
|||
$d->createElementNS('ook', 'ook', 'FAIL'); |
|||
}, DOMException::NOT_SUPPORTED ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$d->createElementNS(null, '<ook>'); |
|||
}, DOMException::INVALID_CHARACTER ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$d->createElementNS(null, 'xmlns'); |
|||
}, DOMException::NAMESPACE_ERROR ] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideElementCreationNSFailures |
|||
* @covers \MensBeam\HTML\DOM\Document::createElementNS |
|||
* @covers \MensBeam\HTML\DOM\Document::validateAndExtract |
|||
* @covers \MensBeam\HTML\DOM\DOMException::__construct |
|||
*/ |
|||
public function testElementCreationNSFailures(\Closure $closure, int $errorCode): void { |
|||
$this->expectException(DOMException::class); |
|||
$this->expectExceptionCode($errorCode); |
|||
$closure(); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Document::save |
|||
* @covers \MensBeam\HTML\DOM\Document::saveHTMLFile |
|||
*/ |
|||
public function testFileSaving(): void { |
|||
$vfs = vfsStream::setup('DOM', 0777); |
|||
$path = $vfs->url() . '/test.html'; |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->save($path); |
|||
$this->assertSame('<html></html>', file_get_contents($path)); |
|||
$d->saveHTMLFile($path); |
|||
$this->assertSame('<html></html>', file_get_contents($path)); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\Document::importNode */ |
|||
public function testImportNode() { |
|||
$d = new Document(); |
|||
$t = $d->createElement('template'); |
|||
|
|||
$d2 = new Document(); |
|||
$t2 = $d2->importNode($t, true); |
|||
$this->assertFalse($t2->ownerDocument->isSameNode($t->ownerDocument)); |
|||
$this->assertSame($t2::class, $t::class); |
|||
|
|||
$d = new \DOMDocument(); |
|||
$t = $d->createElement('template'); |
|||
// Add a child template to cover recursive template conversions. |
|||
$t->appendChild($d->createElement('template')); |
|||
$this->assertSame(\DOMElement::class, $t::class); |
|||
|
|||
$d2 = new Document(); |
|||
$t2 = $d2->importNode($t, true); |
|||
$this->assertSame(HTMLTemplateElement::class, $t2::class); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\Document::importNode */ |
|||
public function testImportingNodesFailure() { |
|||
$this->expectException(DOMException::class); |
|||
$this->expectExceptionCode(DOMException::NOT_SUPPORTED); |
|||
$d = new \DOMDocument(); |
|||
$c = $d->createCDATASection('fail'); |
|||
$d2 = new Document(); |
|||
$d2->importNode($c); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\Document::__get_body */ |
|||
public function testPropertyGetBody(): void { |
|||
$d = new Document(); |
|||
$this->assertNull($d->body); |
|||
$d->appendChild($d->createElement('html')); |
|||
$this->assertNull($d->body); |
|||
$d->documentElement->appendChild($d->createTextNode(' ')); |
|||
$this->assertNull($d->body); |
|||
$f = $d->createElement('frameset'); |
|||
$d->documentElement->appendChild($f); |
|||
$this->assertNotNull($d->body); |
|||
$d->documentElement->removeChild($f); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\Document::__set_body */ |
|||
public function testPropertySetBody(): void { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$b = $d->createElement('body'); |
|||
$d->body = $b; |
|||
$this->assertSame('body', $d->body->nodeName); |
|||
$d->body = $b; |
|||
$this->assertSame('body', $d->body->nodeName); |
|||
|
|||
$b = $d->createElement('body'); |
|||
$b->appendChild($d->createTextNode('Ook')); |
|||
$d->body = $b; |
|||
$this->assertSame('Ook', $d->body->firstChild->data); |
|||
} |
|||
|
|||
public function providePropertySetBodyFailures(): iterable { |
|||
$result = []; |
|||
$d = new Document(); |
|||
$result[] = [ $d, $d->createElement('body') ]; |
|||
$d = new Document(); |
|||
$result[] = [ $d, $d->createElement('div') ]; |
|||
$d = new Document(); |
|||
$result[] = [ $d, $d->createTextNode('FAIL') ]; |
|||
return $result; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider providePropertySetBodyFailures |
|||
* @covers \MensBeam\HTML\DOM\Document::__set_body |
|||
* @covers \MensBeam\HTML\DOM\DOMException::__construct |
|||
*/ |
|||
public function testPropertySetBodyFailures(Document $document, \DOMNode $node): void { |
|||
$this->expectException(DOMException::class); |
|||
$this->expectExceptionCode(DOMException::HIERARCHY_REQUEST_ERROR); |
|||
$document->body = $node; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Document::__get_charset |
|||
* @covers \MensBeam\HTML\DOM\Document::__get_characterSet |
|||
* @covers \MensBeam\HTML\DOM\Document::__get_inputEncoding |
|||
*/ |
|||
public function testPropertyGetCharset(): void { |
|||
$d = new Document(null, 'UTF-8'); |
|||
$this->assertSame('UTF-8', $d->charset); |
|||
$this->assertSame('UTF-8', $d->characterSet); |
|||
$this->assertSame('UTF-8', $d->inputEncoding); |
|||
|
|||
$d = new Document('<!DOCTYPE html><html><head><meta charset="GB18030"></head></html>'); |
|||
$this->assertSame('gb18030', $d->charset); |
|||
$this->assertSame('gb18030', $d->characterSet); |
|||
$this->assertSame('gb18030', $d->inputEncoding); |
|||
} |
|||
|
|||
|
|||
public function providePropertyGetCompatMode(): iterable { |
|||
return [ |
|||
// Empty document |
|||
[ null, 'CSS1Compat' ], |
|||
// Document without doctype |
|||
[ '<html></html>', 'BackCompat' ], |
|||
// Document with doctype |
|||
[ '<!DOCTYPE html><html></html>', 'CSS1Compat' ] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider providePropertyGetCompatMode |
|||
* @covers \MensBeam\HTML\DOM\Document::__get_compatMode |
|||
*/ |
|||
public function testPropertyGetCompatMode(?string $html, string $compatMode): void { |
|||
$d = new Document($html); |
|||
$this->assertSame($compatMode, $d->compatMode); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\Document::__get_contentType */ |
|||
public function testPropertyGetContentType(): void { |
|||
$d = new Document(); |
|||
$this->assertSame('text/html', $d->contentType); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\Document::__get_xpath */ |
|||
public function testPropertyGetXPath(): void { |
|||
$d = new Document(); |
|||
$this->assertSame('DOMXPath', get_class($d->xpath)); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Document::__destruct |
|||
* @covers \MensBeam\HTML\DOM\ElementMap::add |
|||
* @covers \MensBeam\HTML\DOM\ElementMap::delete |
|||
* @covers \MensBeam\HTML\DOM\ElementMap::destroy |
|||
* @covers \MensBeam\HTML\DOM\ElementMap::has |
|||
* @covers \MensBeam\HTML\DOM\ElementMap::index |
|||
*/ |
|||
public function testTemplateElementReferences(): void { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$t = $d->createElement('template'); |
|||
$this->assertFalse(ElementMap::has($t)); |
|||
$d->documentElement->appendChild($t); |
|||
$this->assertTrue(ElementMap::has($t)); |
|||
$d->__destruct(); |
|||
$this->assertFalse(ElementMap::has($t)); |
|||
|
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
|
|||
$t = $d->importNode($t); |
|||
$this->assertFalse(ElementMap::has($t)); |
|||
$d->documentElement->appendChild($t); |
|||
$this->assertTrue(ElementMap::has($t)); |
|||
$d->documentElement->removeChild($t); |
|||
$this->assertFalse(ElementMap::has($t)); |
|||
} |
|||
} |
@ -1,68 +0,0 @@ |
|||
<?php |
|||
/** |
|||
* @license MIT |
|||
* Copyright 2017 Dustin Wilson, J. King, et al. |
|||
* See LICENSE and AUTHORS files for details |
|||
*/ |
|||
|
|||
declare(strict_types=1); |
|||
namespace MensBeam\HTML\DOM\TestCase; |
|||
|
|||
use MensBeam\HTML\DOM\{ |
|||
Document, |
|||
DocumentFragment, |
|||
Element, |
|||
Exception, |
|||
HTMLTemplateElement |
|||
}; |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\DocumentFragment */ |
|||
class TestDocumentFragment extends \PHPUnit\Framework\TestCase { |
|||
/** @covers \MensBeam\HTML\DOM\DocumentFragment::getElementById */ |
|||
public function testGetElementById(): void { |
|||
$d = new Document(); |
|||
$df = $d->createDocumentFragment(); |
|||
$o = $df->appendChild($d->createElement('span')); |
|||
$o->setAttribute('id', 'eek'); |
|||
$this->assertSame(Element::class, $df->getElementById('eek')::class); |
|||
$this->assertNull($df->getElementById('ook')); |
|||
} |
|||
|
|||
/** @covers \MensBeam\HTML\DOM\DocumentFragment::__get_host */ |
|||
public function testGetHost(): void { |
|||
$d = new Document(); |
|||
// From a template |
|||
$t = $d->createElement('template'); |
|||
$this->assertSame(HTMLTemplateElement::class, get_class($t->content->host)); |
|||
// From a created document fragment |
|||
$df = $d->createDocumentFragment(); |
|||
$this->assertNull($df->host); |
|||
} |
|||
|
|||
public function provideSetHostFailures(): iterable { |
|||
return [ |
|||
[ function() { |
|||
$d = new Document(); |
|||
$t = $d->createElement('template'); |
|||
$t->content->host = $d->createElement('template'); |
|||
} ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$df = $d->createDocumentFragment(); |
|||
$df->host = $d->createElement('template'); |
|||
} ] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideSetHostFailures |
|||
* @covers \MensBeam\HTML\DOM\DocumentFragment::__set_host |
|||
* @covers \MensBeam\HTML\DOM\Exception::__construct |
|||
*/ |
|||
public function testSetHostFailures(\Closure $closure): void { |
|||
$this->expectException(Exception::class); |
|||
$this->expectExceptionCode(Exception::READONLY_PROPERTY); |
|||
$closure(); |
|||
} |
|||
} |
@ -1,25 +0,0 @@ |
|||
<?php |
|||
/** |
|||
* @license MIT |
|||
* Copyright 2017 Dustin Wilson, J. King, et al. |
|||
* See LICENSE and AUTHORS files for details |
|||
*/ |
|||
|
|||
declare(strict_types=1); |
|||
namespace MensBeam\HTML\DOM\TestCase; |
|||
|
|||
use MensBeam\HTML\DOM\Document; |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\DocumentOrElement */ |
|||
class TestDocumentOrElement extends \PHPUnit\Framework\TestCase { |
|||
/** @covers \MensBeam\HTML\DOM\DocumentOrElement::getElementsByClassName */ |
|||
public function testGetElementsByClassName(): void { |
|||
$d = new Document(); |
|||
$this->assertSame(0, $d->getElementsByClassName('fail')->length); |
|||
$this->assertSame(0, $d->getElementsByClassName('')->length); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->setAttribute('class', 'ook'); |
|||
$this->assertSame($d->documentElement->nodeName, $d->getElementsByClassName('ook')->item(0)->nodeName); |
|||
} |
|||
} |
@ -1,303 +0,0 @@ |
|||
<?php |
|||
/** |
|||
* @license MIT |
|||
* Copyright 2017 Dustin Wilson, J. King, et al. |
|||
* See LICENSE and AUTHORS files for details |
|||
*/ |
|||
|
|||
declare(strict_types=1); |
|||
namespace MensBeam\HTML\DOM\TestCase; |
|||
|
|||
use MensBeam\HTML\DOM\{ |
|||
Document, |
|||
DOMException |
|||
}; |
|||
use MensBeam\HTML\Parser; |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\Element */ |
|||
class TestElement extends \PHPUnit\Framework\TestCase { |
|||
/** @covers \MensBeam\HTML\DOM\Element::getAttributeNames */ |
|||
public function testGetAttributeNames(): void { |
|||
$d = new Document(); |
|||
$e = $d->createElement('html'); |
|||
$d->appendChild($e); |
|||
|
|||
$this->assertSame([], $e->getAttributeNames()); |
|||
|
|||
$e->setAttribute('ook:eek', 'ook'); |
|||
$e->setAttributeNS(Parser::XMLNS_NAMESPACE, 'xmlns:xlink', Parser::XLINK_NAMESPACE); |
|||
$e->setAttribute('ook', 'eek'); |
|||
|
|||
$this->assertSame([ |
|||
'ook:eek', |
|||
'xmlns:xlink', |
|||
'ook' |
|||
], $e->getAttributeNames()); |
|||
} |
|||
|
|||
|
|||
public function provideGetHasSetAttribute(): iterable { |
|||
return [ |
|||
[ 'ook', 'eek', 'ook', 'eek' ], |
|||
[ 'ook:eek', 'ook', 'ook:eek', 'ook' ], |
|||
[ 'poop💩', 'soccer', 'poop💩', 'soccer' ] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideGetHasSetAttribute |
|||
* @covers \MensBeam\HTML\DOM\Element::getAttribute |
|||
* @covers \MensBeam\HTML\DOM\Element::hasAttribute |
|||
* @covers \MensBeam\HTML\DOM\Element::setAttribute |
|||
*/ |
|||
public function testGetHasSetAttribute(string $nameIn, string $valueIn, string $nameExpected, string $valueExpected): void { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$e = $d->documentElement; |
|||
$e->setAttribute($nameIn, $valueIn); |
|||
$this->assertTrue($e->hasAttribute($nameExpected)); |
|||
$this->assertSame($valueExpected, $e->getAttribute($nameExpected)); |
|||
} |
|||
|
|||
|
|||
public function provideGetHasSetAttributeNS(): iterable { |
|||
return [ |
|||
[ 'fake_ns', 'ook', 'eek', 'ookeek', 'ook', 'eek', 'ookeek' ], |
|||
[ 'another_fake_ns', 'steaming💩', 'poop💩', 'soccer', 'steaming💩', 'poop💩', 'soccer' ], |
|||
[ Parser::XMLNS_NAMESPACE, 'xmlns', 'xlink', Parser::XLINK_NAMESPACE, 'xmlns', 'xlink', Parser::XLINK_NAMESPACE ] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideGetHasSetAttributeNS |
|||
* @covers \MensBeam\HTML\DOM\Element::getAttributeNS |
|||
* @covers \MensBeam\HTML\DOM\Element::hasAttributeNS |
|||
* @covers \MensBeam\HTML\DOM\Element::setAttributeNS |
|||
*/ |
|||
public function testGetHasSetAttributeNS(?string $namespaceIn, ?string $prefixIn, string $localNameIn, string $valueIn, ?string $prefixExpected, string $localNameExpected, string $valueExpected): void { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$e = $d->documentElement; |
|||
$qualifiedNameIn = ($prefixIn === null || $prefixIn === '') ? $localNameIn : "{$prefixIn}:{$localNameIn}"; |
|||
$e->setAttributeNS($namespaceIn, $qualifiedNameIn, $valueIn); |
|||
$this->assertTrue($e->hasAttributeNS($namespaceIn, $localNameExpected)); |
|||
$this->assertSame($valueExpected, $e->getAttributeNS($namespaceIn, $localNameExpected)); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Element::__get_classList |
|||
* @covers \MensBeam\HTML\DOM\TokenList::__construct |
|||
*/ |
|||
public function testPropertyGetClassList(): void { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->setAttribute('class', 'ook eek ack ookeek'); |
|||
$this->assertSame(4, $d->documentElement->classList->length); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Element::__get_innerHTML |
|||
* @covers \MensBeam\HTML\DOM\Element::__set_innerHTML |
|||
* @covers \MensBeam\HTML\DOM\Document::importNode |
|||
*/ |
|||
public function testPropertyGetSetInnerHTML(): void { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$s = $d->body->appendChild($d->createElement('span')); |
|||
$s->appendChild($d->createTextNode('ook')); |
|||
$this->assertSame('<span>ook</span>', $d->body->innerHTML); |
|||
|
|||
$d->body->innerHTML = '<div id ="ook">eek</div>'; |
|||
$this->assertSame('<div id="ook">eek</div>', $d->body->innerHTML); |
|||
|
|||
$t = $d->body->appendChild($d->createElement('template')); |
|||
$t->innerHTML = 'ook'; |
|||
$this->assertSame('ook', $t->innerHTML); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Element::__get_outerHTML |
|||
* @covers \MensBeam\HTML\DOM\Element::__set_outerHTML |
|||
*/ |
|||
public function testPropertyGetSetOuterHTML(): void { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$d->body->setAttribute('class', 'ook'); |
|||
$s = $d->body->appendChild($d->createElement('span')); |
|||
$s->appendChild($d->createTextNode('ook')); |
|||
$this->assertSame('<body class="ook"><span>ook</span></body>', $d->body->outerHTML); |
|||
|
|||
$d->body->outerHTML = '<body>eek</body>'; |
|||
$this->assertSame('<body>eek</body>', $d->body->outerHTML); |
|||
|
|||
$f = $d->createDocumentFragment(); |
|||
$div = $f->appendChild($d->createElement('div')); |
|||
$div->outerHTML = 'ook'; |
|||
$this->assertSame('ook', (string)$f); |
|||
|
|||
$div = $d->createElement('div'); |
|||
$div->appendChild($d->createTextNode('ook')); |
|||
$div->outerHTML = '<div>eek</div>'; |
|||
$this->assertSame('<div>ook</div>', (string)$div); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Element::__set_outerHTML |
|||
*/ |
|||
public function testPropertySetOuterHTMLFailure(): void { |
|||
$this->expectException(DOMException::class); |
|||
$this->expectExceptionCode(DOMException::NO_MODIFICATION_ALLOWED); |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->outerHTML = '<html>FAIL</html>'; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Element::getAttribute |
|||
*/ |
|||
public function testGetAttribute(): void { |
|||
// Just need to test nonexistent attributes |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$this->assertNull($d->documentElement->getAttribute('ook')); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Element::getAttributeNodeNS |
|||
*/ |
|||
public function testGetAttributeNodeNS(): void { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->setAttribute('ook', 'eek'); |
|||
// Empty string namespace |
|||
$ook = $d->documentElement->getAttributeNodeNS('', 'ook'); |
|||
$this->assertSame('eek', $ook->value); |
|||
// Bogus attribute |
|||
$this->assertNull($d->documentElement->getAttributeNodeNS(null, 'what')); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Element::getAttributeNS |
|||
*/ |
|||
public function testGetAttributeNS(): void { |
|||
// Just need to test nonexistent attributes |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$this->assertNull($d->documentElement->getAttributeNS(Parser::HTML_NAMESPACE, 'ook')); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Element::hasAttributeNS |
|||
*/ |
|||
public function testHasAttributeNS(): void { |
|||
// Just need to test empty string namespace |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->setAttribute('ook', 'eek'); |
|||
$this->assertTrue($d->documentElement->hasAttributeNS('', 'ook')); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Element::removeAttribute |
|||
*/ |
|||
public function testRemoveAttribute(): void { |
|||
// Just need to test classList updates |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->classList->add('ook', 'eek'); |
|||
$d->documentElement->removeAttribute('class'); |
|||
$this->assertNull($d->documentElement->getAttribute('class')); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Element::removeAttributeNS |
|||
*/ |
|||
public function testRemoveAttributeNS(): void { |
|||
// Just need to test classList updates |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->classList->add('ook', 'eek'); |
|||
$d->documentElement->removeAttributeNS(null, 'class'); |
|||
$this->assertNull($d->documentElement->getAttribute('class')); |
|||
|
|||
$d->documentElement->setAttributeNS(Parser::XMLNS_NAMESPACE, 'xmlns', Parser::HTML_NAMESPACE); |
|||
$d->documentElement->removeAttributeNS(Parser::XMLNS_NAMESPACE, 'xmlns'); |
|||
$this->assertNull($d->documentElement->getAttributeNS(Parser::XMLNS_NAMESPACE, 'xmlns')); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Element::setAttribute |
|||
* @covers \MensBeam\HTML\DOM\TokenList::add |
|||
*/ |
|||
public function testSetAttribute(): void { |
|||
// Need to test classList updates |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->classList->add('ook', 'eek'); |
|||
$d->documentElement->setAttribute('class', 'ack'); |
|||
$this->assertSame('ack', $d->documentElement->classList[0]); |
|||
// Test setting class to empty string |
|||
$d->documentElement->setAttribute('class', ''); |
|||
$this->assertSame('', $d->documentElement->getAttribute('class')); |
|||
// Test setting id attribute |
|||
$d->documentElement->setAttribute('id', 'ook'); |
|||
$this->assertSame('ook', $d->documentElement->getAttribute('id')); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Element::setAttribute |
|||
* @covers \MensBeam\HTML\DOM\TokenList::add |
|||
*/ |
|||
public function testSetAttributeFailure(): void { |
|||
$this->expectException(DOMException::class); |
|||
$this->expectExceptionCode(DOMException::INVALID_CHARACTER); |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->setAttribute('ook eek', 'fail'); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Element::setAttributeNS |
|||
* @covers \MensBeam\HTML\DOM\TokenList::add |
|||
*/ |
|||
public function testSetAttributeNS(): void { |
|||
$d = new Document(); |
|||
// Don't append html element and set attribute |
|||
$de = $d->createElement('html'); |
|||
$de->setAttributeNS(null, 'id', 'ook'); |
|||
$this->assertSame('ook', $de->getAttribute('id')); |
|||
$de->setAttributeNS(null, 'class', 'ook'); |
|||
$this->assertSame('ook', $de->getAttribute('class')); |
|||
|
|||
$de->setAttributeNS(Parser::XMLNS_NAMESPACE, 'xmlns', Parser::HTML_NAMESPACE); |
|||
$this->assertSame(Parser::HTML_NAMESPACE, $de->getAttributeNS(Parser::XMLNS_NAMESPACE, 'xmlns')); |
|||
|
|||
$b = $d->createElement('body'); |
|||
$b->setAttributeNS(Parser::XMLNS_NAMESPACE, 'xmlns', Parser::HTML_NAMESPACE); |
|||
$this->assertSame(Parser::HTML_NAMESPACE, $b->getAttributeNS(Parser::XMLNS_NAMESPACE, 'xmlns')); |
|||
|
|||
$t = $d->createElement('template'); |
|||
$t->setAttributeNS(Parser::XMLNS_NAMESPACE, 'xmlns', Parser::HTML_NAMESPACE); |
|||
$this->assertSame(Parser::HTML_NAMESPACE, $t->getAttributeNS(Parser::XMLNS_NAMESPACE, 'xmlns')); |
|||
|
|||
// Test name coercion when namespace is null |
|||
$de->setAttributeNS(null, 'poop💩', 'ook'); |
|||
$this->assertSame('ook', $de->getAttribute('poop💩')); |
|||
} |
|||
} |
@ -1,38 +0,0 @@ |
|||
<?php |
|||
/** |
|||
* @license MIT |
|||
* Copyright 2017 Dustin Wilson, J. King, et al. |
|||
* See LICENSE and AUTHORS files for details |
|||
*/ |
|||
|
|||
declare(strict_types=1); |
|||
namespace MensBeam\HTML\DOM\TestCase; |
|||
|
|||
use MensBeam\HTML\DOM\{ |
|||
Document, |
|||
ElementMap |
|||
}; |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\ElementMap |
|||
*/ |
|||
class TestElementMap extends \PHPUnit\Framework\TestCase { |
|||
/** @covers \MensBeam\HTML\DOM\ElementMap::add */ |
|||
public function testAdd(): void { |
|||
$d = new Document(); |
|||
$t = $d->createElement('template'); |
|||
$this->assertTrue(ElementMap::add($t)); |
|||
$this->assertFalse(ElementMap::add($t)); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\ElementMap::delete */ |
|||
public function testDelete(): void { |
|||
$d = new Document(); |
|||
$t = $d->createElement('template'); |
|||
$this->assertTrue(ElementMap::add($t)); |
|||
$this->assertTrue(ElementMap::delete($t)); |
|||
$this->assertFalse(ElementMap::delete($t)); |
|||
} |
|||
} |
@ -1,49 +0,0 @@ |
|||
<?php |
|||
/** |
|||
* @license MIT |
|||
* Copyright 2017 Dustin Wilson, J. King, et al. |
|||
* See LICENSE and AUTHORS files for details |
|||
*/ |
|||
|
|||
declare(strict_types=1); |
|||
namespace MensBeam\HTML\DOM\TestCase; |
|||
|
|||
use MensBeam\HTML\DOM\{ |
|||
Document, |
|||
DOMException |
|||
}; |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\LeafNode */ |
|||
class TestLeafNode extends \PHPUnit\Framework\TestCase { |
|||
public function provideDisabledMethods(): iterable { |
|||
return [ |
|||
[ function($d, $n) { |
|||
$n->appendChild($d->createElement('fail')); |
|||
} ], |
|||
[ function($d, $n) { |
|||
$n->insertBefore($d->createElement('fail')); |
|||
} ], |
|||
[ function($d, $n) { |
|||
$n->removeChild($d->createElement('fail')); |
|||
} ], |
|||
[ function($d, $n) { |
|||
$n->replaceChild($d->createElement('fail2'), $d->createElement('fail')); |
|||
} ], |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideDisabledMethods |
|||
* @covers \MensBeam\HTML\DOM\LeafNode::appendChild |
|||
* @covers \MensBeam\HTML\DOM\LeafNode::insertBefore |
|||
* @covers \MensBeam\HTML\DOM\LeafNode::removeChild |
|||
* @covers \MensBeam\HTML\DOM\LeafNode::replaceChild |
|||
*/ |
|||
public function testDisabledMethods(\Closure $closure): void { |
|||
$this->expectException(DOMException::class); |
|||
$this->expectExceptionCode(DOMException::HIERARCHY_REQUEST_ERROR); |
|||
$d = new Document(); |
|||
$closure($d, $d->createTextNode('ook')); |
|||
} |
|||
} |
@ -0,0 +1,40 @@ |
|||
<?php |
|||
/** |
|||
* @license MIT |
|||
* Copyright 2017 Dustin Wilson, J. King, et al. |
|||
* See LICENSE and AUTHORS files for details |
|||
*/ |
|||
|
|||
declare(strict_types=1); |
|||
namespace MensBeam\HTML\DOM\TestCase; |
|||
|
|||
use MensBeam\HTML\DOM\{ |
|||
Document, |
|||
Node |
|||
}; |
|||
use MensBeam\HTML\Parser; |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\Document */ |
|||
class TestNode extends \PHPUnit\Framework\TestCase { |
|||
/** @covers \MensBeam\HTML\DOM\Node::__get_childNodes */ |
|||
public function testProperty_childNodes() { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$b = $d->body; |
|||
$b->appendChild($d->createElement('span')); |
|||
$b->appendChild($d->createTextNode('ook')); |
|||
|
|||
// Node::childNodes on Element |
|||
$childNodes = $d->body->childNodes; |
|||
$this->assertEquals(2, $childNodes->length); |
|||
$this->assertSame('SPAN', $childNodes[0]->nodeName); |
|||
|
|||
// Node::childNodes on Text |
|||
$childNodes = $d->body->lastChild->childNodes; |
|||
$this->assertEquals(0, $childNodes->length); |
|||
// Try it again to test caching |
|||
$childNodes = $d->body->lastChild->childNodes; |
|||
} |
|||
} |
@ -1,103 +0,0 @@ |
|||
<?php |
|||
/** |
|||
* @license MIT |
|||
* Copyright 2017 Dustin Wilson, J. King, et al. |
|||
* See LICENSE and AUTHORS files for details |
|||
*/ |
|||
|
|||
declare(strict_types=1); |
|||
namespace MensBeam\HTML\DOM\TestCase; |
|||
|
|||
use MensBeam\HTML\DOM\{ |
|||
Document, |
|||
DOMException, |
|||
Exception, |
|||
NodeList |
|||
}; |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\NodeList */ |
|||
class TestNodeList extends \PHPUnit\Framework\TestCase { |
|||
public function provideConstructorFailures(): iterable { |
|||
return [ |
|||
[ function() { |
|||
new NodeList([ 'fail' ]); |
|||
} ], |
|||
[ function() { |
|||
new NodeList([ new \DateTime() ]); |
|||
} ] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideConstructorFailures |
|||
* @covers \MensBeam\HTML\DOM\NodeList::__construct |
|||
*/ |
|||
public function testConstructorFailures(\Closure $closure): void { |
|||
$this->expectException(Exception::class); |
|||
$this->expectExceptionCode(Exception::ARGUMENT_TYPE_ERROR); |
|||
$closure(); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\NodeList::count */ |
|||
public function testCount(): void { |
|||
$d = new Document(); |
|||
$list = new NodeList([ |
|||
$d->createElement('ook'), |
|||
$d->createTextNode('eek'), |
|||
$d->createComment('ack') |
|||
]); |
|||
$this->assertEquals(3, count($list)); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\NodeList::item */ |
|||
public function testItem(): void { |
|||
$d = new Document(); |
|||
$list = new NodeList([ |
|||
$d->createElement('ook'), |
|||
$d->createTextNode('eek'), |
|||
$d->createComment('ack') |
|||
]); |
|||
$this->assertNull($list->item(42)); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\NodeList::current |
|||
* @covers \MensBeam\HTML\DOM\NodeList::item |
|||
* @covers \MensBeam\HTML\DOM\NodeList::key |
|||
* @covers \MensBeam\HTML\DOM\NodeList::next |
|||
* @covers \MensBeam\HTML\DOM\NodeList::rewind |
|||
* @covers \MensBeam\HTML\DOM\NodeList::offsetExists |
|||
* @covers \MensBeam\HTML\DOM\NodeList::offsetGet |
|||
* @covers \MensBeam\HTML\DOM\NodeList::valid |
|||
*/ |
|||
public function testIteration(): void { |
|||
$d = new Document(); |
|||
$list = new NodeList([ |
|||
$d->createElement('ook'), |
|||
$d->createTextNode('eek'), |
|||
$d->createComment('ack') |
|||
]); |
|||
|
|||
foreach ($list as $key => $node) { |
|||
$this->assertSame($node, $list[$key]); |
|||
// test offsetExists |
|||
$this->assertTrue(isset($list[$key])); |
|||
} |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\NodeList::__get_length */ |
|||
public function testPropertyGetLength(): void { |
|||
$d = new Document(); |
|||
$list = new NodeList([ |
|||
$d->createElement('ook'), |
|||
$d->createTextNode('eek'), |
|||
$d->createComment('ack') |
|||
]); |
|||
$this->assertEquals(3, $list->length); |
|||
} |
|||
} |
@ -1,167 +0,0 @@ |
|||
<?php |
|||
/** |
|||
* @license MIT |
|||
* Copyright 2017 Dustin Wilson, J. King, et al. |
|||
* See LICENSE and AUTHORS files for details |
|||
*/ |
|||
|
|||
declare(strict_types=1); |
|||
namespace MensBeam\HTML\DOM\TestCase; |
|||
|
|||
use MensBeam\HTML\DOM\{ |
|||
Document, |
|||
DOMException, |
|||
Exception |
|||
}; |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\NodeTrait */ |
|||
class TestNodeTrait extends \PHPUnit\Framework\TestCase { |
|||
/** @covers \MensBeam\HTML\DOM\NodeTrait::compareDocumentPosition */ |
|||
public function testCompareDocumentPosition(): void { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$d->body->innerHTML = '<header><h1>Ook</h1></header><main><h2 id="eek" class="ack">Eek</h2><p>Ook <a href="ook">eek</a>, ook?</p></main><footer></footer>'; |
|||
$m = $d->getElementsByTagName('main')->item(0); |
|||
$f = $d->getElementsByTagName('footer')->item(0); |
|||
$e = $d->getElementById('eek'); |
|||
$h2Id = $e->getAttributeNode('id'); |
|||
$h2Class = $e->getAttributeNode('class'); |
|||
$aHref = $d->getElementsByTagName('a')->item(0)->getAttributeNode('href'); |
|||
|
|||
$compareMainToBody = $m->compareDocumentPosition($d->body); |
|||
$this->assertEquals(10, $compareMainToBody); |
|||
$compareBodyToMain = $d->body->compareDocumentPosition($m); |
|||
$this->assertEquals(20, $compareBodyToMain); |
|||
$compareFooterToMain = $f->compareDocumentPosition($m); |
|||
$this->assertEquals(2, $compareFooterToMain); |
|||
$compareMainToFooter = $m->compareDocumentPosition($f); |
|||
$this->assertEquals(4, $compareMainToFooter); |
|||
$compareH2IdToAHref = $h2Id->compareDocumentPosition($aHref); |
|||
$this->assertEquals(4, $compareH2IdToAHref); |
|||
$compareH2IdToH2Class = $h2Id->compareDocumentPosition($h2Class); |
|||
$this->assertEquals(36, $compareH2IdToH2Class); |
|||
$compareH2ClassToH2Id = $h2Class->compareDocumentPosition($h2Id); |
|||
$this->assertEquals(34, $compareH2ClassToH2Id); |
|||
$this->assertEquals(0, $m->compareDocumentPosition($m)); |
|||
|
|||
$this->assertGreaterThan(0, $compareMainToBody & Document::DOCUMENT_POSITION_CONTAINS); |
|||
$this->assertGreaterThan(0, $compareMainToBody & Document::DOCUMENT_POSITION_PRECEDING); |
|||
$this->assertEquals(0, $compareMainToBody & Document::DOCUMENT_POSITION_FOLLOWING); |
|||
|
|||
$this->assertGreaterThan(0, $compareBodyToMain & Document::DOCUMENT_POSITION_CONTAINED_BY); |
|||
$this->assertGreaterThan(0, $compareBodyToMain & Document::DOCUMENT_POSITION_FOLLOWING); |
|||
$this->assertEquals(0, $compareBodyToMain & Document::DOCUMENT_POSITION_PRECEDING); |
|||
|
|||
$this->assertGreaterThan(0, $compareFooterToMain & Document::DOCUMENT_POSITION_PRECEDING); |
|||
$this->assertGreaterThan(0, $compareMainToFooter & Document::DOCUMENT_POSITION_FOLLOWING); |
|||
|
|||
$this->assertGreaterThan(0, $compareH2IdToAHref & Document::DOCUMENT_POSITION_FOLLOWING); |
|||
$this->assertGreaterThan(0, $compareH2IdToH2Class & Document::DOCUMENT_POSITION_FOLLOWING); |
|||
$this->assertGreaterThan(0, $compareH2ClassToH2Id & Document::DOCUMENT_POSITION_PRECEDING); |
|||
|
|||
$m->parentNode->removeChild($m); |
|||
$compareDetachedMainToFooter = $m->compareDocumentPosition($f); |
|||
$this->assertEquals($compareDetachedMainToFooter, $m->compareDocumentPosition($f)); |
|||
$this->assertGreaterThanOrEqual(35, $compareDetachedMainToFooter); |
|||
$this->assertLessThanOrEqual(37, $compareDetachedMainToFooter); |
|||
$this->assertNotEquals(36, $compareDetachedMainToFooter); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\NodeTrait::contains */ |
|||
public function testContains(): void { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$o = $d->body->appendChild($d->createTextNode('Ook!')); |
|||
$d2 = new Document(); |
|||
$d2->appendChild($d2->createElement('html')); |
|||
|
|||
$this->assertTrue($d->documentElement->contains($d->body)); |
|||
$this->assertTrue($d->contains($o)); |
|||
$this->assertFalse($o->contains($d)); |
|||
$this->assertFalse($d->contains($d2->documentElement)); |
|||
} |
|||
|
|||
|
|||
public function provideDisabledMethods(): iterable { |
|||
return [ |
|||
[ 'C14N' ], |
|||
[ 'C14NFile', 'ook' ], |
|||
[ 'getLineNo' ] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideDisabledMethods |
|||
* @covers \MensBeam\HTML\DOM\NodeTrait::C14N |
|||
* @covers \MensBeam\HTML\DOM\NodeTrait::C14NFile |
|||
* @covers \MensBeam\HTML\DOM\NodeTrait::getLineNo |
|||
*/ |
|||
public function testDisabledMethods(string $methodName, ...$arguments): void { |
|||
$this->expectException(Exception::class); |
|||
$this->expectExceptionCode(Exception::DISABLED_METHOD); |
|||
$d = new Document(); |
|||
$d->$methodName(...$arguments); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\NodeTrait::getRootNode */ |
|||
public function testGetRootNode(): void { |
|||
$d = new Document(); |
|||
$t = $d->createElement('template'); |
|||
$div = $t->content->appendChild($d->createElement('div')); |
|||
$this->assertTrue($t->content->isSameNode($div->getRootNode())); |
|||
} |
|||
|
|||
/** @covers \MensBeam\HTML\DOM\NodeTrait::isEqualNode */ |
|||
public function testIsEqualNode(): void { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$d->body->innerHTML = '<main><h1>Ook</h1><p>Eek</p></main><footer></footer>'; |
|||
|
|||
$d2 = new Document(); |
|||
$d2->appendChild($d2->createElement('html')); |
|||
$d2->documentElement->appendChild($d2->createElement('body')); |
|||
$d2->body->innerHTML = '<main><h1>Ook</h1><p>Eek</p></main><footer></footer>'; |
|||
|
|||
$this->assertTrue($d->isEqualNode($d2)); |
|||
|
|||
$d = new Document(); |
|||
$de = $d->createElement('html'); |
|||
$this->assertFalse($d->isEqualNode($de)); |
|||
|
|||
$d = new Document(); |
|||
$d->appendChild($d->implementation->createDocumentType('html', '', '')); |
|||
|
|||
$d2 = new Document(); |
|||
$d2->appendChild($d2->implementation->createDocumentType('ook', 'eek', 'ack')); |
|||
$this->assertFalse($d->isEqualNode($d2)); |
|||
|
|||
$d = new Document('<!DOCTYPE html><html lang="en"><head><title>Ook!</title></head><body><head><h1>Eek</h1></head><footer></footer></body></html>'); |
|||
$d2 = new Document('<!DOCTYPE html><html lang="en"><head><title>Eek!</title></head><body><head><h1>Eek</h1></head><footer></footer></body></html>'); |
|||
$this->assertFalse($d->isEqualNode($d2)); |
|||
|
|||
$d = new Document(); |
|||
$f = $d->createDocumentFragment(); |
|||
$f->appendChild($d->createElement('span')); |
|||
$f->appendChild($d->createTextNode('Ook')); |
|||
|
|||
$f2 = $d->createDocumentFragment(); |
|||
$f2->appendChild($d->createElement('span')); |
|||
$this->assertFalse($f->isEqualNode($f2)); |
|||
|
|||
$s = $d->createElement('span'); |
|||
$s->setAttribute('id', 'ook'); |
|||
$s2 = $d->createElement('span'); |
|||
$s2->setAttribute('class', 'ook'); |
|||
$this->assertFalse($s->isEqualNode($s2)); |
|||
|
|||
$s = $d->createElement('span'); |
|||
$br = $d->createElement('br'); |
|||
$this->assertFalse($s->isEqualNode($br)); |
|||
} |
|||
} |
@ -1,289 +0,0 @@ |
|||
<?php |
|||
/** |
|||
* @license MIT |
|||
* Copyright 2017 Dustin Wilson, J. King, et al. |
|||
* See LICENSE and AUTHORS files for details |
|||
*/ |
|||
|
|||
declare(strict_types=1); |
|||
namespace MensBeam\HTML\DOM\TestCase; |
|||
|
|||
use MensBeam\HTML\DOM\{ |
|||
Document, |
|||
DOMException, |
|||
Element, |
|||
ElementMap, |
|||
Exception, |
|||
NodeList |
|||
}; |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\ParentNode */ |
|||
class TestParentNode extends \PHPUnit\Framework\TestCase { |
|||
/** @covers \MensBeam\HTML\DOM\ParentNode::insertBefore */ |
|||
public function testInsertBefore(): void { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$div = $d->body->appendChild($d->createElement('div')); |
|||
$ook = $d->body->insertBefore($d->createTextNode('ook'), $div); |
|||
|
|||
$this->assertSame('<body>ook<div></div></body>', (string)$d->body); |
|||
|
|||
$t = $d->body->insertBefore($d->createElement('template'), $ook); |
|||
|
|||
$this->assertSame('<body><template></template>ook<div></div></body>', (string)$d->body); |
|||
$this->assertTrue(ElementMap::has($t)); |
|||
} |
|||
|
|||
|
|||
public function providePreInsertionValidationFailures(): iterable { |
|||
return [ |
|||
[ function() { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$b = $d->documentElement->appendChild($d->createElement('body')); |
|||
$b->appendChild($d->documentElement); |
|||
} ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$b = $d->documentElement->appendChild($d->createElement('body')); |
|||
$t = $b->appendChild($d->createElement('template')); |
|||
$t->content->appendChild($b); |
|||
} ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$b = $d->documentElement->appendChild($d->createElement('body')); |
|||
$d->insertBefore($d->createElement('fail'), $b); |
|||
}, DOMException::NOT_FOUND ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$df = $d->createDocumentFragment(); |
|||
$df->appendChild($d->createElement('html')); |
|||
$df->appendChild($d->createTextNode(' ')); |
|||
$d->appendChild($df); |
|||
} ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$d->appendChild($d); |
|||
} ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$d->appendChild($d->implementation->createDocumentType('html')); |
|||
$d->appendChild($d->implementation->createDocumentType('html')); |
|||
} ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->appendChild($d->implementation->createDocumentType('html')); |
|||
} ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$c = $d->appendChild($d->createComment('ook')); |
|||
$d->insertBefore($d->implementation->createDocumentType('html'), $c); |
|||
} ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->insertBefore($d->implementation->createDocumentType('html')); |
|||
} ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->insertBefore($d->implementation->createDocumentType('html')); |
|||
} ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$dt = $d->appendChild($d->implementation->createDocumentType('html')); |
|||
$df = $d->createDocumentFragment(); |
|||
$df->appendChild($d->createElement('html')); |
|||
$d->insertBefore($df, $dt); |
|||
} ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$c = $d->appendChild($d->createComment('OOK')); |
|||
$d->appendChild($d->implementation->createDocumentType('html')); |
|||
$df = $d->createDocumentFragment(); |
|||
$df->appendChild($d->createElement('html')); |
|||
$d->insertBefore($df, $c); |
|||
} ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$dt = $d->appendChild($d->implementation->createDocumentType('html')); |
|||
$d->insertBefore($d->createElement('html'), $dt); |
|||
} ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$c = $d->appendChild($d->createComment('OOK')); |
|||
$d->appendChild($d->implementation->createDocumentType('html')); |
|||
$d->insertBefore($d->createElement('html'), $c); |
|||
} ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->appendChild($d->createElement('body')); |
|||
} ] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider providePreInsertionValidationFailures |
|||
* @covers \MensBeam\HTML\DOM\DOMException::__construct |
|||
* @covers \MensBeam\HTML\DOM\NodeTrait::getRootNode |
|||
* @covers \MensBeam\HTML\DOM\ParentNode::preInsertionValidity |
|||
*/ |
|||
public function testPreInsertionValidationFailures(\Closure $closure, int $errorCode = DOMException::HIERARCHY_REQUEST_ERROR): void { |
|||
$this->expectException(DOMException::class); |
|||
$this->expectExceptionCode($errorCode); |
|||
$closure(); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\ParentNode::__get_children */ |
|||
public function testPropertyGetChildren(): void { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
|
|||
$this->assertSame(1, $d->documentElement->children->length); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\ParentNode::querySelector |
|||
* @covers \MensBeam\HTML\DOM\ParentNode::querySelectorAll |
|||
* @covers \MensBeam\HTML\DOM\ParentNode::scopeMatchSelector |
|||
* @covers \MensBeam\HTML\DOM\NodeList::__construct |
|||
* @covers \MensBeam\HTML\DOM\NodeList::item |
|||
*/ |
|||
public function testQuerySelector(): void { |
|||
$d = new Document('<!DOCTYPE html><html><body><div>ook</div><div id="eek">eek</div></body></html>'); |
|||
$div = $d->body->querySelector('div'); |
|||
$this->assertSame('div', $div->nodeName); |
|||
$this->assertNull($d->querySelector('body::before')); |
|||
|
|||
$divs = $d->body->querySelectorAll('div'); |
|||
$this->assertEquals(2, $divs->length); |
|||
$this->assertSame('eek', $divs->item(1)->getAttribute('id')); |
|||
$this->assertNull($d->querySelector('.ook')); |
|||
$this->assertEquals(0, $d->querySelectorAll('body::before')->length); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\ParentNode::querySelector |
|||
* @covers \MensBeam\HTML\DOM\ParentNode::querySelectorAll |
|||
* @covers \MensBeam\HTML\DOM\ParentNode::scopeMatchSelector |
|||
*/ |
|||
public function testQuerySelectorFailure(): void { |
|||
$this->expectException(DOMException::class); |
|||
$this->expectExceptionCode(DOMException::SYNTAX_ERROR); |
|||
$d = new Document(); |
|||
$d->querySelector('ook?'); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\ParentNode::replaceChild */ |
|||
public function testReplaceChild(): void { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$div = $d->body->appendChild($d->createElement('div')); |
|||
$ook = $d->body->replaceChild($d->createTextNode('ook'), $div); |
|||
|
|||
$this->assertSame('<body>ook</body>', (string)$d->body); |
|||
|
|||
$t = $d->body->replaceChild($d->createElement('template'), $ook); |
|||
|
|||
$this->assertSame('<body><template></template></body>', (string)$d->body); |
|||
$this->assertTrue(ElementMap::has($t)); |
|||
|
|||
$d->body->replaceChild($d->createElement('br'), $t); |
|||
|
|||
$this->assertSame('<body><br></body>', (string)$d->body); |
|||
$this->assertFalse(ElementMap::has($t)); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\ParentNode::replaceChildren */ |
|||
public function testReplaceChildren(): void { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$div = $d->body->appendChild($d->createElement('div')); |
|||
$ook = $d->body->appendChild($d->createTextNode('ook'), $d->body->appendChild($d->createElement('div'))); |
|||
|
|||
$d->body->replaceChildren($d->createElement('br'), 'ook', $d->createElement('span'), 'eek'); |
|||
$this->assertSame('<body><br>ook<span></span>eek</body>', (string)$d->body); |
|||
|
|||
$d->body->replaceChildren('ook'); |
|||
$this->assertSame('<body>ook</body>', (string)$d->body); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\ParentNode::walk */ |
|||
public function testWalk(): void { |
|||
// Test removal of elements when walking |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$d->body->innerHTML = '<span class="one">O</span><span class="two">O</span><span class="three">O</span><span class="four">K</span>'; |
|||
$spans = $d->body->walk(function($n) { |
|||
return ($n instanceof Element && $n->nodeName === 'span'); |
|||
}); |
|||
|
|||
foreach ($spans as $s) { |
|||
if ($s->getAttribute('class') === 'three') { |
|||
$s->parentNode->removeChild($s); |
|||
} |
|||
} |
|||
|
|||
$this->assertSame('<body><span class="one">O</span><span class="two">O</span><span class="four">K</span></body>', (string)$d->body); |
|||
|
|||
// Test walking through templates' content |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$t = $d->body->appendChild($d->createElement('template')); |
|||
$t->content->appendChild($d->createElement('ook')); |
|||
|
|||
$this->assertSame('ook', $d->body->walk(function($n) { |
|||
return ($n instanceof Element && $n->nodeName === 'ook'); |
|||
})->current()->nodeName); |
|||
} |
|||
|
|||
|
|||
public function provideWalkFailures(): iterable { |
|||
$d = new Document(); |
|||
$d->appendChild($d->createElement('html')); |
|||
$d->documentElement->appendChild($d->createElement('body')); |
|||
$d->body->innerHTML = '<header><h1>Ook</h1></header><main><h2>Eek</h2><p>Ook <a href="ook">eek</a>, ook?</p></main><footer></footer>'; |
|||
|
|||
return [ |
|||
[ function() use ($d) { |
|||
$d->body->walk(function($n) { |
|||
return 'ook'; |
|||
})->current(); |
|||
} ], |
|||
[ function() use ($d) { |
|||
$d->body->walk(function($n) { |
|||
return new \DateTime(); |
|||
})->current(); |
|||
} ] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideWalkFailures |
|||
* @covers \MensBeam\HTML\DOM\DOMException::__construct |
|||
* @covers \MensBeam\HTML\DOM\ParentNode::walk |
|||
*/ |
|||
public function testWalkFailures(\Closure $closure): void { |
|||
$this->expectException(Exception::class); |
|||
$this->expectExceptionCode(Exception::CLOSURE_RETURN_TYPE_ERROR); |
|||
$closure(); |
|||
} |
|||
} |
@ -1,230 +0,0 @@ |
|||
<?php |
|||
/** |
|||
* @license MIT |
|||
* Copyright 2017 Dustin Wilson, J. King, et al. |
|||
* See LICENSE and AUTHORS files for details |
|||
*/ |
|||
|
|||
declare(strict_types=1); |
|||
namespace MensBeam\HTML\DOM\TestCase; |
|||
|
|||
use MensBeam\HTML\DOM\{ |
|||
Document, |
|||
DOMException |
|||
}; |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\TokenList */ |
|||
class TestTokenList extends \PHPUnit\Framework\TestCase { |
|||
public function provideAddRemoveReplaceToggleFailures(): iterable { |
|||
return [ |
|||
[ function() { |
|||
$d = new Document(); |
|||
$e = $d->createElement('html'); |
|||
$e->classList->add(''); |
|||
}, DOMException::SYNTAX_ERROR ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$e = $d->createElement('html'); |
|||
$e->classList->remove(''); |
|||
}, DOMException::SYNTAX_ERROR ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$e = $d->createElement('html'); |
|||
$e->classList->replace('ack', ''); |
|||
}, DOMException::SYNTAX_ERROR ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$e = $d->createElement('html'); |
|||
$e->classList->toggle(''); |
|||
}, DOMException::SYNTAX_ERROR ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$e = $d->createElement('html'); |
|||
$e->classList->add('fail fail'); |
|||
}, DOMException::INVALID_CHARACTER ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$e = $d->createElement('html'); |
|||
$e->classList->remove('fail fail'); |
|||
}, DOMException::INVALID_CHARACTER ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$e = $d->createElement('html'); |
|||
$e->classList->replace('ack', 'fail fail'); |
|||
}, DOMException::INVALID_CHARACTER ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$e = $d->createElement('html'); |
|||
$e->classList->toggle('fail fail'); |
|||
}, DOMException::INVALID_CHARACTER ] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideAddRemoveReplaceToggleFailures |
|||
* @covers \MensBeam\HTML\DOM\TokenList::add |
|||
* @covers \MensBeam\HTML\DOM\TokenList::remove |
|||
* @covers \MensBeam\HTML\DOM\TokenList::replace |
|||
* @covers \MensBeam\HTML\DOM\TokenList::toggle |
|||
*/ |
|||
public function testAddRemoveReplaceFailures(\Closure $closure, int $errorCode): void { |
|||
$this->expectException(DOMException::class); |
|||
$this->expectExceptionCode($errorCode); |
|||
$closure(); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\TokenList::contains */ |
|||
public function testContains(): void { |
|||
$d = new Document(); |
|||
$e = $d->appendChild($d->createElement('html')); |
|||
$e->classList->add('ook', 'eek', 'ack', 'ookeek'); |
|||
$this->assertTrue($e->classList->contains('ack')); |
|||
$this->assertFalse($e->classList->contains('fail')); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\TokenList::count */ |
|||
public function testCount(): void { |
|||
$d = new Document(); |
|||
$e = $d->appendChild($d->createElement('html')); |
|||
$e->classList->add('ook', 'eek', 'ack', 'ookeek'); |
|||
$this->assertSame(4, count($e->classList)); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\TokenList::item */ |
|||
public function testItem(): void { |
|||
$d = new Document(); |
|||
$e = $d->appendChild($d->createElement('html')); |
|||
$e->classList->add('ook', 'eek', 'ack', 'ookeek'); |
|||
$this->assertNull($e->classList->item(42)); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\TokenList::current |
|||
* @covers \MensBeam\HTML\DOM\TokenList::item |
|||
* @covers \MensBeam\HTML\DOM\TokenList::key |
|||
* @covers \MensBeam\HTML\DOM\TokenList::next |
|||
* @covers \MensBeam\HTML\DOM\TokenList::rewind |
|||
* @covers \MensBeam\HTML\DOM\TokenList::offsetExists |
|||
* @covers \MensBeam\HTML\DOM\TokenList::offsetGet |
|||
* @covers \MensBeam\HTML\DOM\TokenList::valid |
|||
*/ |
|||
public function testIteration(): void { |
|||
$d = new Document(); |
|||
$e = $d->appendChild($d->createElement('html')); |
|||
$e->classList->add('ook', 'eek', 'ack', 'ookeek'); |
|||
|
|||
foreach ($e->classList as $key => $className) { |
|||
$this->assertSame($className, $e->classList[$key]); |
|||
// test offsetExists |
|||
$this->assertTrue(isset($e->classList[$key])); |
|||
} |
|||
} |
|||
|
|||
/** @covers \MensBeam\HTML\DOM\TokenList::__get_length */ |
|||
public function testPropertyGetLength(): void { |
|||
// Test it with and without an attached document element |
|||
$d = new Document(); |
|||
$e = $d->appendChild($d->createElement('html')); |
|||
$e->classList->add('ook', 'eek', 'ack', 'ookeek'); |
|||
$this->assertSame(4, $e->classList->length); |
|||
|
|||
$d = new Document(); |
|||
$e = $d->createElement('html'); |
|||
$e->classList->add('ook', 'eek', 'ack', 'ookeek'); |
|||
$this->assertSame(4, $e->classList->length); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\TokenList::__get_value |
|||
* @covers \MensBeam\HTML\DOM\TokenList::__set_value |
|||
*/ |
|||
public function testPropertyGetSetValue(): void { |
|||
// Test it with and without an attached document element |
|||
$d = new Document(); |
|||
$e = $d->createElement('html'); |
|||
$e->classList->add('ook', 'eek', 'ack', 'ookeek'); |
|||
$this->assertSame('ook eek ack ookeek', $e->classList->value); |
|||
$this->assertSame('ook eek ack ookeek', $e->getAttribute('class')); |
|||
$e->classList->value = 'omg wtf bbq lol zor bor xxx'; |
|||
$this->assertSame('lol', $e->classList[3]); |
|||
$this->assertSame('omg wtf bbq lol zor bor xxx', $e->classList->value); |
|||
$this->assertSame('omg wtf bbq lol zor bor xxx', $e->getAttribute('class')); |
|||
$e->classList->value = ''; |
|||
$this->assertSame('', $e->classList->value); |
|||
$this->assertSame('', $e->getAttribute('class')); |
|||
|
|||
$d = new Document(); |
|||
$e = $d->appendChild($d->createElement('html')); |
|||
$e->classList->add('ook', 'eek', 'ack', 'ookeek'); |
|||
$this->assertSame('ook eek ack ookeek', $e->classList->value); |
|||
$this->assertSame('ook eek ack ookeek', $e->getAttribute('class')); |
|||
$e->classList->value = 'omg wtf bbq lol zor bor xxx'; |
|||
$this->assertSame('lol', $e->classList[3]); |
|||
$this->assertSame('omg wtf bbq lol zor bor xxx', $e->classList->value); |
|||
$this->assertSame('omg wtf bbq lol zor bor xxx', $e->getAttribute('class')); |
|||
$e->classList->value = ''; |
|||
$this->assertSame('', $e->classList->value); |
|||
$this->assertSame('', $e->getAttribute('class')); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\TokenList::replace */ |
|||
public function testReplace(): void { |
|||
$d = new Document(); |
|||
$e = $d->appendChild($d->createElement('html')); |
|||
$e->setAttribute('class', 'ook eek ack ookeek'); |
|||
$this->assertTrue($e->classList->replace('ack', 'what')); |
|||
$this->assertSame('ook eek what ookeek', $e->classList->value); |
|||
$this->assertSame('ook eek what ookeek', $e->getAttribute('class')); |
|||
$this->assertFalse($e->classList->replace('fail', 'eekook')); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\TokenList::remove */ |
|||
public function testRemove(): void { |
|||
$d = new Document(); |
|||
$e = $d->appendChild($d->createElement('html')); |
|||
$e->setAttribute('class', 'ook eek ack ookeek'); |
|||
$e->classList->remove('ack'); |
|||
$this->assertSame('ook eek ookeek', $e->classList->value); |
|||
$this->assertSame('ook eek ookeek', $e->getAttribute('class')); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\TokenList::supports */ |
|||
public function testSupports(): void { |
|||
$d = new Document(); |
|||
$e = $d->appendChild($d->createElement('html')); |
|||
$e->classList->add('ook', 'eek', 'ack', 'ookeek'); |
|||
$this->assertTrue($e->classList->supports('ack')); |
|||
} |
|||
|
|||
|
|||
/** @covers \MensBeam\HTML\DOM\TokenList::toggle */ |
|||
public function testToggle(): void { |
|||
$d = new Document(); |
|||
$e = $d->appendChild($d->createElement('html')); |
|||
$e->setAttribute('class', 'ook eek ack ookeek'); |
|||
$this->assertFalse($e->classList->toggle('ack')); |
|||
$this->assertSame('ook eek ookeek', $e->classList->value); |
|||
$this->assertSame('ook eek ookeek', $e->getAttribute('class')); |
|||
$this->assertTrue($e->classList->toggle('ack')); |
|||
$this->assertSame('ook eek ookeek ack', $e->classList->value); |
|||
$this->assertSame('ook eek ookeek ack', $e->getAttribute('class')); |
|||
$this->assertTrue($e->classList->toggle('ack', true)); |
|||
$this->assertSame('ook eek ookeek ack', $e->classList->value); |
|||
$this->assertSame('ook eek ookeek ack', $e->getAttribute('class')); |
|||
$this->assertFalse($e->classList->toggle('eekook', false)); |
|||
$this->assertSame('ook eek ookeek ack', $e->classList->value); |
|||
$this->assertSame('ook eek ookeek ack', $e->getAttribute('class')); |
|||
$this->assertTrue($e->classList->toggle('eekook', true)); |
|||
$this->assertSame('ook eek ookeek ack eekook', $e->classList->value); |
|||
$this->assertSame('ook eek ookeek ack eekook', $e->getAttribute('class')); |
|||
} |
|||
} |
@ -1,279 +0,0 @@ |
|||
<?php |
|||
/** |
|||
* @license MIT |
|||
* Copyright 2017 Dustin Wilson, J. King, et al. |
|||
* See LICENSE and AUTHORS files for details |
|||
*/ |
|||
|
|||
declare(strict_types=1); |
|||
namespace MensBeam\HTML\DOM\TestCase; |
|||
|
|||
use MensBeam\HTML\DOM\{ |
|||
Document, |
|||
DOMException, |
|||
Exception |
|||
}; |
|||
use MensBeam\HTML\Parser; |
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Comment |
|||
* @covers \MensBeam\HTML\DOM\Document |
|||
* @covers \MensBeam\HTML\DOM\DocumentFragment |
|||
* @covers \MensBeam\HTML\DOM\Element |
|||
* @covers \MensBeam\HTML\DOM\HTMLTemplateElement |
|||
* @covers \MensBeam\HTML\DOM\ProcessingInstruction |
|||
* @covers \MensBeam\HTML\DOM\Text |
|||
* @covers \MensBeam\HTML\DOM\ToString |
|||
*/ |
|||
class TestSerializer extends \PHPUnit\Framework\TestCase { |
|||
public function provideStandardTreeTests(): iterable { |
|||
$blacklist = []; |
|||
$files = new \AppendIterator(); |
|||
$files->append(new \GlobIterator(\MensBeam\HTML\DOM\BASE."tests/cases/Serializer/standard/*.dat", \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::CURRENT_AS_PATHNAME)); |
|||
foreach ($files as $file) { |
|||
if (!in_array(basename($file), $blacklist)) { |
|||
yield from $this->parseTreeTestFile($file); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideStandardTreeTests |
|||
* @covers \MensBeam\HTML\DOM\Document::saveHTML |
|||
* @covers \MensBeam\HTML\DOM\Document::blockElementFilterFactory |
|||
* @covers \MensBeam\HTML\DOM\Document::serializeNode |
|||
* @covers \MensBeam\HTML\DOM\Document::__toString |
|||
* @covers \MensBeam\HTML\DOM\ToString::__toString |
|||
*/ |
|||
public function testStandardTreeTests(array $data, bool $fragment, string $exp): void { |
|||
$node = $this->buildTree($data, $fragment); |
|||
$this->assertSame($exp, (string)$node); |
|||
} |
|||
|
|||
|
|||
public function provideFormattedTreeTests(): iterable { |
|||
$files = new \AppendIterator(); |
|||
$files->append(new \GlobIterator(\MensBeam\HTML\DOM\BASE."tests/cases/Serializer/formatted/*.dat", \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::CURRENT_AS_PATHNAME)); |
|||
foreach ($files as $file) { |
|||
yield from $this->parseTreeTestFile($file); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideFormattedTreeTests |
|||
* @covers \MensBeam\HTML\DOM\Document::saveHTML |
|||
* @covers \MensBeam\HTML\DOM\Document::blockElementFilterFactory |
|||
* @covers \MensBeam\HTML\DOM\Document::serializeNode |
|||
* @covers \MensBeam\HTML\DOM\Document::__toString |
|||
* @covers \MensBeam\HTML\DOM\ToString::__toString |
|||
*/ |
|||
public function testFormattedTreeTests(array $data, bool $fragment, string $exp): void { |
|||
$node = $this->buildTree($data, $fragment, true); |
|||
$this->assertSame($exp, (string)$node); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Document::saveHTML |
|||
* @covers \MensBeam\HTML\DOM\Document::serializeNode |
|||
*/ |
|||
public function testSerializingDocumentType(): void { |
|||
$d = new Document(); |
|||
$dt = $d->implementation->createDocumentType('ook', 'eek', 'ack'); |
|||
$d->appendChild($dt); |
|||
$this->assertSame('<!DOCTYPE ook>', $d->saveHTML($dt)); |
|||
} |
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Document::saveHTML |
|||
* @covers \MensBeam\HTML\DOM\Document::serializeNode |
|||
*/ |
|||
public function testSerializingDocumentFragments(): void { |
|||
$d = new Document(); |
|||
$d->formatOutput = true; |
|||
$df = $d->createDocumentFragment(); |
|||
$df->appendChild($d->createTextNode('ook')); |
|||
$this->assertSame('ook', (string)$df); |
|||
$this->assertSame('ook', $d->saveHTML($df)); |
|||
} |
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Document::saveHTML |
|||
* @covers \MensBeam\HTML\DOM\Document::serializeNode |
|||
* @covers \MensBeam\HTML\DOM\ToString::__toString |
|||
*/ |
|||
public function testSerializingElements(): void { |
|||
$d = new Document(); |
|||
$i = $d->createElement('input'); |
|||
$i->appendChild($d->createTextNode('You should not see this text')); |
|||
$this->assertSame('<input>', (string)$i); |
|||
$this->assertSame('', $d->saveHTML($i)); |
|||
|
|||
$t = $d->createElement('template'); |
|||
$t->setAttribute('ook', 'eek'); |
|||
$t->content->appendChild($d->createTextNode('Ook!')); |
|||
$this->assertSame('<template ook="eek">Ook!</template>', (string)$t); |
|||
$this->assertSame('Ook!', $d->saveHTML($t)); |
|||
} |
|||
|
|||
/** |
|||
* @covers \MensBeam\HTML\DOM\Document::saveHTML |
|||
* @covers \MensBeam\HTML\DOM\Document::serializeNode |
|||
* @covers \MensBeam\HTML\DOM\ToString::__toString |
|||
*/ |
|||
public function testSerializingTextNodes(): void { |
|||
$d = new Document(); |
|||
$d->formatOutput = true; |
|||
$i = $d->createTextNode('test'); |
|||
$this->assertSame('test', (string)$i); |
|||
$this->assertSame('test', $d->saveHTML($i)); |
|||
} |
|||
|
|||
|
|||
public function provideSerializerFailures(): iterable { |
|||
return [ |
|||
[ function() { |
|||
$d = new Document(); |
|||
$h = $d->createElement('html'); |
|||
$d2 = new Document(); |
|||
$d2->saveHTML($h); |
|||
}, DOMException::class, DOMException::WRONG_DOCUMENT ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$d->saveHTML($d->createAttribute('fail')); |
|||
}, Exception::class, Exception::ARGUMENT_TYPE_ERROR ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$d->saveHTML(new \DOMDocument()); |
|||
}, Exception::class, Exception::ARGUMENT_TYPE_ERROR ], |
|||
[ function() { |
|||
$d = new Document(); |
|||
$d2 = new \DOMDocument(); |
|||
$d->saveHTML($d2->createComment('fail')); |
|||
}, Exception::class, Exception::ARGUMENT_TYPE_ERROR ] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @dataProvider provideSerializerFailures |
|||
* @covers \MensBeam\HTML\DOM\Document::saveHTML |
|||
*/ |
|||
public function testSerializerFailures(\Closure $closure, string $exceptionClassName, int $errorCode): void { |
|||
$this->expectException($exceptionClassName); |
|||
$this->expectExceptionCode($errorCode); |
|||
$closure(); |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
protected function buildTree(array $data, bool $fragment, bool $formatOutput = false): \DOMNode { |
|||
$document = new Document; |
|||
$document->formatOutput = $formatOutput; |
|||
if ($fragment) { |
|||
$document->appendChild($document->createElement("html")); |
|||
$out = $document->createDocumentFragment(); |
|||
} else { |
|||
$out = $document; |
|||
} |
|||
$cur = $out; |
|||
$pad = 2; |
|||
// process each line in turn |
|||
for ($l = 0; $l < sizeof($data); $l++) { |
|||
preg_match('/^(\|\s+)(.+)/', $data[$l], $m); |
|||
// pop any parents as long as the padding of the line is less than the expected padding |
|||
$p = strlen((string) $m[1]); |
|||
assert($p >= 2 && $p <= $pad && !($p % 2), new \Exception("Input data is invalid on line ".($l + 1))); |
|||
while ($p < $pad) { |
|||
$pad -= 2; |
|||
$cur = $cur->parentNode; |
|||
} |
|||
// act based upon what the rest of the line looks like |
|||
$d = $m[2]; |
|||
if (preg_match('/^<!-- (.*?) -->$/', $d, $m)) { |
|||
// comment |
|||
$cur->appendChild($document->createComment($m[1])); |
|||
} elseif (preg_match('/^<!DOCTYPE(?: ([^ >]*)(?: "([^"]*)" "([^"]*)")?)?>$/', $d, $m)) { |
|||
// doctype |
|||
$name = strlen((string) ($m[1] ?? "")) ? $m[1] : " "; |
|||
$public = strlen((string) ($m[2] ?? "")) ? $m[2] : ""; |
|||
$system = strlen((string) ($m[3] ?? "")) ? $m[3] : ""; |
|||
$cur->appendChild($document->implementation->createDocumentType($name, $public, $system)); |
|||
} elseif (preg_match('/^<\?([^ ]+) ([^>]*)>$/', $d, $m)) { |
|||
$cur->appendChild($document->createProcessingInstruction($m[1], $m[2])); |
|||
} elseif (preg_match('/^<(?:([^ ]+) )?([^>]+)>$/', $d, $m)) { |
|||
// element |
|||
$ns = strlen((string) $m[1]) ? (array_flip(Parser::NAMESPACE_MAP)[$m[1]] ?? $m[1]) : null; |
|||
$cur = $cur->appendChild($document->createElementNS($ns, $m[2])); |
|||
$pad += 2; |
|||
} elseif (preg_match('/^(?:([^" ]+) )?([^"=]+)="((?:[^"]|"(?!$))*)"$/', $d, $m)) { |
|||
// attribute |
|||
$ns = strlen((string) $m[1]) ? (array_flip(Parser::NAMESPACE_MAP)[$m[1]] ?? $m[1]) : ""; |
|||
|
|||
if ($ns === '') { |
|||
$cur->setAttribute($m[2], $m[3]); |
|||
} else { |
|||
$cur->setAttributeNS($ns, $m[2], $m[3]); |
|||
} |
|||
} elseif (preg_match('/^"((?:[^"]|"(?!$))*)("?)$/', $d, $m)) { |
|||
// text |
|||
$t = $m[1]; |
|||
while (!strlen((string) $m[2])) { |
|||
preg_match('/^((?:[^"]|"(?!$))*)("?)$/', $data[++$l], $m); |
|||
$t .= "\n".$m[1]; |
|||
} |
|||
$cur->appendChild($document->createTextNode($t)); |
|||
} else { |
|||
throw new \Exception("Input data is invalid on line ".($l + 1)); |
|||
} |
|||
} |
|||
return $out; |
|||
} |
|||
|
|||
protected function parseTreeTestFile(string $file): \Generator { |
|||
$index = 0; |
|||
$l = 0; |
|||
$lines = array_map(function($v) { |
|||
return rtrim($v, "\n"); |
|||
}, file($file)); |
|||
while ($l < sizeof($lines)) { |
|||
$pos = $l + 1; |
|||
assert(in_array($lines[$l], ["#document", "#fragment"]), new \Exception("Test $file #$index does not start with #document or #fragment tag at line ".($l + 1))); |
|||
$fragment = $lines[$l] === "#fragment"; |
|||
// collect the test input |
|||
$data = []; |
|||
for (++$l; $l < sizeof($lines); $l++) { |
|||
if (preg_match('/^#(script-(on|off)|output)$/', $lines[$l])) { |
|||
break; |
|||
} |
|||
$data[] = $lines[$l]; |
|||
} |
|||
// set the script mode, if present |
|||
assert(preg_match('/^#(script-(on|off)|output)$/', $lines[$l]) === 1, new \Exception("Test $file #$index follows data with something other than script flag or output at line ".($l + 1))); |
|||
$script = null; |
|||
if ($lines[$l] === "#script-off") { |
|||
$script = false; |
|||
$l++; |
|||
} elseif ($lines[$l] === "#script-on") { |
|||
$script = true; |
|||
$l++; |
|||
} |
|||
// collect the output string |
|||
$exp = []; |
|||
assert($lines[$l] === "#output", new \Exception("Test $file #$index follows input with something other than output at line ".($l + 1))); |
|||
for (++$l; $l < sizeof($lines); $l++) { |
|||
if ($lines[$l] === "" && in_array(($lines[$l + 1] ?? ""), ["#document", "#fragment"])) { |
|||
break; |
|||
} |
|||
assert(preg_match('/^([^#]|$)/', $lines[$l]) === 1, new \Exception("Test $file #$index contains unrecognized data after output at line ".($l + 1))); |
|||
$exp[] = $lines[$l]; |
|||
} |
|||
$exp = implode("\n", $exp); |
|||
if (!$script) { |
|||
yield basename($file)." #$index (line $pos)" => [$data, $fragment, $exp]; |
|||
} |
|||
$l++; |
|||
$index++; |
|||
} |
|||
} |
|||
} |
@ -1,153 +0,0 @@ |
|||
#fragment |
|||
| <html> |
|||
#output |
|||
<html></html> |
|||
|
|||
#document |
|||
| <!-- data --> |
|||
| <!DOCTYPE html> |
|||
| <html> |
|||
#output |
|||
<!--data--> |
|||
<!DOCTYPE html> |
|||
<html></html> |
|||
|
|||
#document |
|||
| <!DOCTYPE html> |
|||
| <html> |
|||
| <head> |
|||
| <body> |
|||
#output |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head></head> |
|||
|
|||
<body></body> |
|||
</html> |
|||
|
|||
#document |
|||
| <html> |
|||
| <body> |
|||
| <pre> |
|||
| <code> |
|||
#output |
|||
<html> |
|||
<body> |
|||
<pre><code></code></pre> |
|||
</body> |
|||
</html> |
|||
|
|||
#document |
|||
| <html> |
|||
| <body> |
|||
| <svg> |
|||
#output |
|||
<html> |
|||
<body><svg></svg></body> |
|||
</html> |
|||
|
|||
#fragment |
|||
| <body> |
|||
| <div> |
|||
| <svg svg> |
|||
#output |
|||
<body> |
|||
<div></div> |
|||
|
|||
<svg></svg> |
|||
</body> |
|||
|
|||
#fragment |
|||
| <body> |
|||
| <div> |
|||
| <svg svg> |
|||
| <svg tspan> |
|||
#output |
|||
<body> |
|||
<div></div> |
|||
|
|||
<svg> |
|||
<tspan/> |
|||
</svg> |
|||
</body> |
|||
|
|||
#document |
|||
| <!DOCTYPE html> |
|||
| <html> |
|||
| " |
|||
" |
|||
| <head> |
|||
| <body> |
|||
| "ook |
|||
" |
|||
#output |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head></head> |
|||
|
|||
<body>ook |
|||
</body> |
|||
</html> |
|||
|
|||
#fragment |
|||
| <div> |
|||
| <div> |
|||
| " |
|||
" |
|||
#output |
|||
<div> |
|||
<div></div> |
|||
</div> |
|||
|
|||
#fragment |
|||
| <div> |
|||
| <a> |
|||
| <div> |
|||
| <svg> |
|||
#output |
|||
<div> |
|||
<a> |
|||
<div></div> |
|||
</a> |
|||
|
|||
<svg></svg> |
|||
</div> |
|||
|
|||
#fragment |
|||
| <div> |
|||
| <!-- data --> |
|||
| <div> |
|||
#output |
|||
<div> |
|||
<!--data--> |
|||
|
|||
<div></div> |
|||
</div> |
|||
|
|||
#fragment |
|||
| <div> |
|||
| <div> |
|||
| <!-- data --> |
|||
| <div> |
|||
#output |
|||
<div> |
|||
<div></div> |
|||
|
|||
<!--data--> |
|||
|
|||
<div></div> |
|||
</div> |
|||
|
|||
#fragment |
|||
| <div> |
|||
| <div> |
|||
| <?php echo "Hello world!"; ?> |
|||
| <div> |
|||
#output |
|||
<div> |
|||
<div></div> |
|||
|
|||
<?php echo "Hello world!"; ?> |
|||
|
|||
<div></div> |
|||
</div> |
@ -1,33 +0,0 @@ |
|||
#fragment |
|||
| <fake_ns test:test> |
|||
#output |
|||
<test:test></test:test> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| test💩test="test" |
|||
#output |
|||
<span test💩test="test"></span> |
|||
|
|||
#fragment |
|||
| <wbr> |
|||
| "You should not see this text." |
|||
#output |
|||
<wbr> |
|||
|
|||
#fragment |
|||
| <wbr> |
|||
| class="test" |
|||
#output |
|||
<wbr class="test"> |
|||
|
|||
#fragment |
|||
| <poop💩> |
|||
#output |
|||
<poop💩></poop💩> |
|||
|
|||
#fragment |
|||
| <test> |
|||
| poop💩="soccer" |
|||
#output |
|||
<test poop💩="soccer"></test> |
@ -1,34 +0,0 @@ |
|||
#document |
|||
| <html> |
|||
#output |
|||
<html></html> |
|||
|
|||
#document |
|||
| <!DOCTYPE html> |
|||
| <html> |
|||
#output |
|||
<!DOCTYPE html><html></html> |
|||
|
|||
#document |
|||
| <!DOCTYPE html "public" "system"> |
|||
| <html> |
|||
#output |
|||
<!DOCTYPE html><html></html> |
|||
|
|||
#document |
|||
| <!DOCTYPE test> |
|||
| <html> |
|||
#output |
|||
<!DOCTYPE test><html></html> |
|||
|
|||
#document |
|||
| <!DOCTYPE> |
|||
| <html> |
|||
#output |
|||
<!DOCTYPE ><html></html> |
|||
|
|||
#document |
|||
| <html> |
|||
| <?php echo "Hello world!"; ?> |
|||
#output |
|||
<html><?php echo "Hello world!"; ?></html> |
@ -1,913 +0,0 @@ |
|||
#fragment |
|||
| <span> |
|||
#output |
|||
<span></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
#output |
|||
<span><a></a></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| b="c" |
|||
#output |
|||
<span><a b="c"></a></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| b="&" |
|||
#output |
|||
<span><a b="&"></a></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| b=" " |
|||
#output |
|||
<span><a b=" "></a></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| b=""" |
|||
#output |
|||
<span><a b="""></a></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| b="<" |
|||
#output |
|||
<span><a b="<"></a></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| b=">" |
|||
#output |
|||
<span><a b=">"></a></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| href="javascript:"<>"" |
|||
#output |
|||
<span><a href="javascript:"<>""></a></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <svg svg> |
|||
| xlink xlink:href="a" |
|||
#output |
|||
<span><svg xlink:href="a"></svg></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <svg svg> |
|||
| xmlns xmlns:svg="test" |
|||
#output |
|||
<span><svg xmlns:svg="test"></svg></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| "a" |
|||
#output |
|||
<span>a</span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| "&" |
|||
#output |
|||
<span>&</span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| " " |
|||
#output |
|||
<span> </span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| "<" |
|||
#output |
|||
<span><</span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| ">" |
|||
#output |
|||
<span>></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| """ |
|||
#output |
|||
<span>"</span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <style> |
|||
| "<&>" |
|||
#output |
|||
<span><style><&></style></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <script> |
|||
| type="test" |
|||
| "<&>" |
|||
#output |
|||
<span><script type="test"><&></script></span> |
|||
|
|||
#fragment |
|||
| <script> |
|||
| type="test" |
|||
| "<&>" |
|||
#output |
|||
<script type="test"><&></script> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <xmp> |
|||
| "<&>" |
|||
#output |
|||
<span><xmp><&></xmp></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <iframe> |
|||
| "<&>" |
|||
#output |
|||
<span><iframe><&></iframe></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <noembed> |
|||
| "<&>" |
|||
#output |
|||
<span><noembed><&></noembed></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <noframes> |
|||
| "<&>" |
|||
#output |
|||
<span><noframes><&></noframes></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <noscript> |
|||
| "<&>" |
|||
#script-off |
|||
#output |
|||
<span><noscript><&></noscript></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <noscript> |
|||
| "<&>" |
|||
#script-on |
|||
#output |
|||
<span><noscript><&></noscript></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <!-- data --> |
|||
#output |
|||
<span><!--data--></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| <b> |
|||
| <c> |
|||
| <d> |
|||
| "e" |
|||
| <f> |
|||
| <g> |
|||
| "h" |
|||
#output |
|||
<span><a><b><c></c></b><d>e</d><f><g>h</g></f></a></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| b="c" |
|||
#output |
|||
<span b="c"></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <svg svg> |
|||
| xml xml:foo="test" |
|||
#output |
|||
<span><svg xml:foo="test"></svg></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <svg svg> |
|||
| xml abc:foo="test" |
|||
#output |
|||
<span><svg xml:foo="test"></svg></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <svg svg> |
|||
| xmlns xmlns:foo="test" |
|||
#output |
|||
<span><svg xmlns:foo="test"></svg></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <svg svg> |
|||
| xmlns xmlns="test" |
|||
#output |
|||
<span><svg xmlns="test"></svg></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <svg svg> |
|||
| fake_ns abc:def="test" |
|||
#output |
|||
<span><svg abc:def="test"></svg></span> |
|||
|
|||
#fragment |
|||
| <pre> |
|||
| " |
|||
" |
|||
#output |
|||
<pre> |
|||
</pre> |
|||
|
|||
#fragment |
|||
| <pre> |
|||
| "a |
|||
" |
|||
#output |
|||
<pre>a |
|||
</pre> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <pre> |
|||
| " |
|||
" |
|||
#output |
|||
<span><pre> |
|||
</pre></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <pre> |
|||
| "a |
|||
" |
|||
#output |
|||
<span><pre>a |
|||
</pre></span> |
|||
|
|||
#fragment |
|||
| <textarea> |
|||
| " |
|||
" |
|||
#output |
|||
<textarea> |
|||
</textarea> |
|||
|
|||
#fragment |
|||
| <textarea> |
|||
| "a |
|||
" |
|||
#output |
|||
<textarea>a |
|||
</textarea> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <textarea> |
|||
| " |
|||
" |
|||
#output |
|||
<span><textarea> |
|||
</textarea></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <textarea> |
|||
| "a |
|||
" |
|||
#output |
|||
<span><textarea>a |
|||
</textarea></span> |
|||
|
|||
#fragment |
|||
| <listing> |
|||
| " |
|||
" |
|||
#output |
|||
<listing> |
|||
</listing> |
|||
|
|||
#fragment |
|||
| <listing> |
|||
| "a |
|||
" |
|||
#output |
|||
<listing>a |
|||
</listing> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <listing> |
|||
| " |
|||
" |
|||
#output |
|||
<span><listing> |
|||
</listing></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <listing> |
|||
| "a |
|||
" |
|||
#output |
|||
<span><listing>a |
|||
</listing></span> |
|||
|
|||
#fragment |
|||
| <area> |
|||
#output |
|||
<area> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <area> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
#output |
|||
<span><area><a>test</a><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <area> |
|||
| <b> |
|||
#output |
|||
<span><a>test</a><area><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
| <area> |
|||
#output |
|||
<span><a>test</a><b></b><area></span> |
|||
|
|||
#fragment |
|||
| <base> |
|||
#output |
|||
<base> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <base> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
#output |
|||
<span><base><a>test</a><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <base> |
|||
| <b> |
|||
#output |
|||
<span><a>test</a><base><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
| <base> |
|||
#output |
|||
<span><a>test</a><b></b><base></span> |
|||
|
|||
#fragment |
|||
| <basefont> |
|||
#output |
|||
<basefont> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <basefont> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
#output |
|||
<span><basefont><a>test</a><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <basefont> |
|||
| <b> |
|||
#output |
|||
<span><a>test</a><basefont><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
| <basefont> |
|||
#output |
|||
<span><a>test</a><b></b><basefont></span> |
|||
|
|||
#fragment |
|||
| <bgsound> |
|||
#output |
|||
<bgsound> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <bgsound> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
#output |
|||
<span><bgsound><a>test</a><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <bgsound> |
|||
| <b> |
|||
#output |
|||
<span><a>test</a><bgsound><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
| <bgsound> |
|||
#output |
|||
<span><a>test</a><b></b><bgsound></span> |
|||
|
|||
#fragment |
|||
| <br> |
|||
#output |
|||
<br> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <br> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
#output |
|||
<span><br><a>test</a><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <br> |
|||
| <b> |
|||
#output |
|||
<span><a>test</a><br><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
| <br> |
|||
#output |
|||
<span><a>test</a><b></b><br></span> |
|||
|
|||
#fragment |
|||
| <col> |
|||
#output |
|||
<col> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <col> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
#output |
|||
<span><col><a>test</a><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <col> |
|||
| <b> |
|||
#output |
|||
<span><a>test</a><col><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
| <col> |
|||
#output |
|||
<span><a>test</a><b></b><col></span> |
|||
|
|||
#fragment |
|||
| <embed> |
|||
#output |
|||
<embed> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <embed> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
#output |
|||
<span><embed><a>test</a><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <embed> |
|||
| <b> |
|||
#output |
|||
<span><a>test</a><embed><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
| <embed> |
|||
#output |
|||
<span><a>test</a><b></b><embed></span> |
|||
|
|||
#fragment |
|||
| <frame> |
|||
#output |
|||
<frame> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <frame> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
#output |
|||
<span><frame><a>test</a><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <frame> |
|||
| <b> |
|||
#output |
|||
<span><a>test</a><frame><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
| <frame> |
|||
#output |
|||
<span><a>test</a><b></b><frame></span> |
|||
|
|||
#fragment |
|||
| <hr> |
|||
#output |
|||
<hr> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <hr> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
#output |
|||
<span><hr><a>test</a><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <hr> |
|||
| <b> |
|||
#output |
|||
<span><a>test</a><hr><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
| <hr> |
|||
#output |
|||
<span><a>test</a><b></b><hr></span> |
|||
|
|||
#fragment |
|||
| <img> |
|||
#output |
|||
<img> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <img> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
#output |
|||
<span><img><a>test</a><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <img> |
|||
| <b> |
|||
#output |
|||
<span><a>test</a><img><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
| <img> |
|||
#output |
|||
<span><a>test</a><b></b><img></span> |
|||
|
|||
#fragment |
|||
| <input> |
|||
#output |
|||
<input> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <input> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
#output |
|||
<span><input><a>test</a><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <input> |
|||
| <b> |
|||
#output |
|||
<span><a>test</a><input><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
| <input> |
|||
#output |
|||
<span><a>test</a><b></b><input></span> |
|||
|
|||
#fragment |
|||
| <keygen> |
|||
#output |
|||
<keygen> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <keygen> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
#output |
|||
<span><keygen><a>test</a><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <keygen> |
|||
| <b> |
|||
#output |
|||
<span><a>test</a><keygen><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
| <keygen> |
|||
#output |
|||
<span><a>test</a><b></b><keygen></span> |
|||
|
|||
#fragment |
|||
| <link> |
|||
#output |
|||
<link> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <link> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
#output |
|||
<span><link><a>test</a><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <link> |
|||
| <b> |
|||
#output |
|||
<span><a>test</a><link><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
| <link> |
|||
#output |
|||
<span><a>test</a><b></b><link></span> |
|||
|
|||
#fragment |
|||
| <meta> |
|||
#output |
|||
<meta> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <meta> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
#output |
|||
<span><meta><a>test</a><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <meta> |
|||
| <b> |
|||
#output |
|||
<span><a>test</a><meta><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
| <meta> |
|||
#output |
|||
<span><a>test</a><b></b><meta></span> |
|||
|
|||
#fragment |
|||
| <param> |
|||
#output |
|||
<param> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <param> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
#output |
|||
<span><param><a>test</a><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <param> |
|||
| <b> |
|||
#output |
|||
<span><a>test</a><param><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
| <param> |
|||
#output |
|||
<span><a>test</a><b></b><param></span> |
|||
|
|||
#fragment |
|||
| <source> |
|||
#output |
|||
<source> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <source> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
#output |
|||
<span><source><a>test</a><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <source> |
|||
| <b> |
|||
#output |
|||
<span><a>test</a><source><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
| <source> |
|||
#output |
|||
<span><a>test</a><b></b><source></span> |
|||
|
|||
#fragment |
|||
| <track> |
|||
#output |
|||
<track> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <track> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
#output |
|||
<span><track><a>test</a><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <track> |
|||
| <b> |
|||
#output |
|||
<span><a>test</a><track><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
| <track> |
|||
#output |
|||
<span><a>test</a><b></b><track></span> |
|||
|
|||
#fragment |
|||
| <wbr> |
|||
#output |
|||
<wbr> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <wbr> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
#output |
|||
<span><wbr><a>test</a><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <wbr> |
|||
| <b> |
|||
#output |
|||
<span><a>test</a><wbr><b></b></span> |
|||
|
|||
#fragment |
|||
| <span> |
|||
| <a> |
|||
| "test" |
|||
| <b> |
|||
| <wbr> |
|||
#output |
|||
<span><a>test</a><b></b><wbr></span> |
Loading…
Reference in new issue