diff --git a/lib/Document.php b/lib/Document.php index 4eba3c1..f70cc27 100644 --- a/lib/Document.php +++ b/lib/Document.php @@ -19,7 +19,7 @@ use MensBeam\HTML\Parser\{ }; -class Document extends Node { +class Document extends Node implements \ArrayAccess { use DocumentOrElement, NonElementParentNode, ParentNode; protected string $_characterSet = 'UTF-8'; @@ -623,6 +623,105 @@ class Document extends Node { $this->load($data, $charset); } + public function offsetExists(mixed $offset): bool { + // There is no equivalent to this in the way it is typically implemented in + // JavaScript, so to keep things the way PHP developers expect (that ArrayAccess + // implementations work with isset) this will check to see if a valid named + // element exists. + + // Because PHP is dumb and won't let us implement ArrayAccess with a more + // specific type than its interface... + if (!is_string($offset)) { + trigger_error('Type error; ' . __CLASS__ . ' keys may only be strings', \E_USER_ERROR); + } + + $namespace = (!$this instanceof XMLDocument) ? '' : Node::HTML_NAMESPACE; + return ($this->innerNode->xpath->query(".//*[(name()='form' or name()='iframe' or name()='img') and namespace-uri()='$namespace' and @name='$offset'] | .//img[namespace-uri()='$namespace' and @id='$offset' and @name and not(@name='')] | .//embed[namespace-uri()='$namespace' and @name='$offset' and not(ancestor::object[namespace-uri()='$namespace']) and not(descendant::*[(name()='embed' or name()='object') and namespace-uri()='$namespace'])] | .//object[namespace-uri()='$namespace' and @id='$offset' and not(ancestor::object[namespace-uri()='$namespace']) and not(descendant::*[(name()='embed' or name()='object') and namespace-uri()='$namespace'])]")->length > 0); + } + + public function offsetGet(mixed $offset): Element|HTMLCollection|null { + // Because PHP is dumb and won't let us implement ArrayAccess with a more + // specific type than its interface... + if (!is_string($offset)) { + trigger_error('Type error; ' . __CLASS__ . ' keys may only be strings', \E_USER_ERROR); + } + + // In JavaScript this part of the Document interface is implemented as + // properties. This is impractical in PHP because the said properties can + // contain characters which aren't valid PHP properties. So, this will be + // implemented as an ArrayAccess implementation instead. + + # The Document interface supports named properties. The supported property names + # of a Document object document at any moment consist of the following, in tree + # order according to the element that contributed them, ignoring later + # duplicates, and with values from id attributes coming before values from name + # attributes when the same element contributes both: + + # • the value of the name content attribute for all exposed embed, form, iframe, + # img, and exposed object elements that have a non-empty name content attribute + # and are in a document tree with document as their root; + # • the value of the id content attribute for all img elements that have both a + # non-empty id content attribute and a non-empty name content attribute, and are + # in a document tree with document as their root. + + # To determine the value of a named property name for a Document, the user agent + # must return the value obtained using the following steps: + # + # 1. Let elements be the list of named elements with the name name that are in a + # document tree with the Document as their root. + + # Named elements with the name name, for the purposes of the above algorithm, + # are those that are either: + # • Exposed embed, form, iframe, img, or exposed object elements that have a name + # content attribute whose value is name, or + # • Exposed object elements that have an id content attribute whose value is name, + # or + # • img elements that have an id content attribute whose value is name, and that + # have a non-empty name content attribute present also. + + # An embed or object element is said to be exposed if it has no exposed object + # ancestor, and, for object elements, is additionally either not showing its + # fallback content or has no object or embed descendants. + $namespace = (!$this instanceof XMLDocument) ? '' : Node::HTML_NAMESPACE; + $elements = $this->innerNode->xpath->query(".//*[(name()='form' or name()='iframe' or name()='img') and namespace-uri()='$namespace' and @name='$offset'] | .//img[namespace-uri()='$namespace' and @id='$offset' and @name and not(@name='')] | .//embed[namespace-uri()='$namespace' and @name='$offset' and not(ancestor::object[namespace-uri()='$namespace']) and not(descendant::*[(name()='embed' or name()='object') and namespace-uri()='$namespace'])] | .//object[namespace-uri()='$namespace' and @id='$offset' and not(ancestor::object[namespace-uri()='$namespace']) and not(descendant::*[(name()='embed' or name()='object') and namespace-uri()='$namespace'])]"); + + # NOTE: There will be at least one such element, by definition. + // This algorithm seems to expect user agents to keep up with a list of named + // elements as elements are manipulated... I think? It is very vague on this + // subject. There will of course be an instance where there's no such element -- + // if there's no valid named element in the document. Browsers return undefined + // if there's no matching name, so let's return null here as PHP does not have + // undefined. + if ($elements->length === 0) { + return null; + } + + # 2. If elements has only one element, and that element is an iframe element, and + # that iframe element's nested browsing context is not null, then return the + # WindowProxy object of the element's nested browsing context. + // No. This is stupid. + + # 3. Otherwise, if elements has only one element, return that element. + if ($elements->length === 1) { + return $this->innerNode->getWrapperNode($elements->item(0)); + } + + # 4. Otherwise return an HTMLCollection rooted at the Document node, whose + # filter matches only named elements with the name name. + // HTMLCollections cannot be created from their constructors normally. + return Reflection::createFromProtectedConstructor(__NAMESPACE__ . '\\HTMLCollection', $this->innerNode, $elements); + } + + public function offsetSet(mixed $offset, mixed $value): void { + // The specification is vague as to what to do here. Browsers silently fail, so + // that's what we're going to do. + } + + public function offsetUnset(mixed $offset): void { + // The specification is vague as to what to do here. Browsers silently fail, so + // that's what we're going to do. + } + public function serialize(?Node $node = null, array $config = []): string { $node = $node ?? $this; if ($node !== $this) { diff --git a/tests/cases/TestDocument.php b/tests/cases/TestDocument.php index 470297e..fae4133 100644 --- a/tests/cases/TestDocument.php +++ b/tests/cases/TestDocument.php @@ -13,6 +13,7 @@ use MensBeam\HTML\DOM\{ DOMException, DOMImplementation, Element, + HTMLElement, Node, Text, XMLDocument @@ -22,6 +23,162 @@ use org\bovigo\vfs\vfsStream; /** @covers \MensBeam\HTML\DOM\Document */ class TestDocument extends \PHPUnit\Framework\TestCase { + /** + * @covers \MensBeam\HTML\DOM\Document::offsetExists + * + * @covers \MensBeam\HTML\DOM\Document::__construct + * @covers \MensBeam\HTML\DOM\Document::load + * @covers \MensBeam\HTML\DOM\DOMImplementation::__construct + * @covers \MensBeam\HTML\DOM\Node::__construct + * @covers \MensBeam\HTML\DOM\Node::getInnerDocument + * @covers \MensBeam\HTML\DOM\Node::hasChildNodes + * @covers \MensBeam\HTML\DOM\Node::postParsingTemplatesFix + * @covers \MensBeam\HTML\DOM\Inner\Document::__construct + * @covers \MensBeam\HTML\DOM\Inner\Document::__get_xpath + */ + public function testMethod_offsetExists(): void { + $d = new Document(''); + $this->assertTrue(isset($d['ook'])); + } + + + /** + * @covers \MensBeam\HTML\DOM\Document::offsetExists + * + * @covers \MensBeam\HTML\DOM\Document::__construct + * @covers \MensBeam\HTML\DOM\DOMImplementation::__construct + * @covers \MensBeam\HTML\DOM\Node::__construct + * @covers \MensBeam\HTML\DOM\Inner\Document::__construct + * @covers \MensBeam\HTML\DOM\Inner\Document::__get_xpath + */ + public function testMethod_offsetExists__errors(): void { + // PHPUnit is supposed to support expecting of errors, but it doesn't. So let's + // write a bunch of bullshit so we can catch and assert errors instead. + set_error_handler(function($errno) { + if ($errno === \E_USER_ERROR) { + $this->assertEquals(\E_USER_ERROR, $errno); + } + }); + + $d = new Document(); + isset($d[0]); + + restore_error_handler(); + } + + + /** + * @covers \MensBeam\HTML\DOM\Document::offsetGet + * + * @covers \MensBeam\HTML\DOM\Collection::__construct + * @covers \MensBeam\HTML\DOM\Document::__construct + * @covers \MensBeam\HTML\DOM\Document::load + * @covers \MensBeam\HTML\DOM\DOMImplementation::__construct + * @covers \MensBeam\HTML\DOM\Element::__construct + * @covers \MensBeam\HTML\DOM\Node::__construct + * @covers \MensBeam\HTML\DOM\Node::getInnerDocument + * @covers \MensBeam\HTML\DOM\Node::hasChildNodes + * @covers \MensBeam\HTML\DOM\Node::postParsingTemplatesFix + * @covers \MensBeam\HTML\DOM\Inner\Document::__construct + * @covers \MensBeam\HTML\DOM\Inner\Document::__get_xpath + * @covers \MensBeam\HTML\DOM\Inner\Document::getWrapperNode + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::get + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::has + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::key + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::set + * @covers \MensBeam\HTML\DOM\Inner\Reflection::createFromProtectedConstructor + */ + public function testMethod_offsetGet(): void { + $d = new Document(''); + $this->assertSame(HTMLElement::class, $d['ook']::class); + $this->assertEquals(5, $d['eek']->length); + $this->assertNull($d['ookeek']); + + $d['ook'] = 'fail'; + $this->assertSame(HTMLElement::class, $d['ook']::class); + } + + + /** + * @covers \MensBeam\HTML\DOM\Document::offsetGet + * + * @covers \MensBeam\HTML\DOM\Document::__construct + * @covers \MensBeam\HTML\DOM\DOMImplementation::__construct + * @covers \MensBeam\HTML\DOM\Node::__construct + * @covers \MensBeam\HTML\DOM\Inner\Document::__construct + * @covers \MensBeam\HTML\DOM\Inner\Document::__get_xpath + */ + public function testMethod_offsetGet__errors(): void { + // PHPUnit is supposed to support expecting of errors, but it doesn't. So let's + // write a bunch of bullshit so we can catch and assert errors instead. + set_error_handler(function($errno) { + if ($errno === \E_USER_ERROR) { + $this->assertEquals(\E_USER_ERROR, $errno); + } + }); + + $d = new Document(); + $fail = $d[0]; + + restore_error_handler(); + } + + + /** + * @covers \MensBeam\HTML\DOM\Document::offsetSet + * + * @covers \MensBeam\HTML\DOM\Document::__construct + * @covers \MensBeam\HTML\DOM\Document::load + * @covers \MensBeam\HTML\DOM\Document::offsetGet + * @covers \MensBeam\HTML\DOM\DOMImplementation::__construct + * @covers \MensBeam\HTML\DOM\Element::__construct + * @covers \MensBeam\HTML\DOM\Node::__construct + * @covers \MensBeam\HTML\DOM\Node::getInnerDocument + * @covers \MensBeam\HTML\DOM\Node::hasChildNodes + * @covers \MensBeam\HTML\DOM\Node::postParsingTemplatesFix + * @covers \MensBeam\HTML\DOM\Inner\Document::__construct + * @covers \MensBeam\HTML\DOM\Inner\Document::__get_xpath + * @covers \MensBeam\HTML\DOM\Inner\Document::getWrapperNode + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::get + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::has + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::key + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::set + * @covers \MensBeam\HTML\DOM\Inner\Reflection::createFromProtectedConstructor + */ + public function testMethod_offsetSet(): void { + $d = new Document(''); + $d['ook'] = 'fail'; + $this->assertSame(HTMLElement::class, $d['ook']::class); + } + + + /** + * @covers \MensBeam\HTML\DOM\Document::offsetUnset + * + * @covers \MensBeam\HTML\DOM\Document::__construct + * @covers \MensBeam\HTML\DOM\Document::load + * @covers \MensBeam\HTML\DOM\Document::offsetGet + * @covers \MensBeam\HTML\DOM\DOMImplementation::__construct + * @covers \MensBeam\HTML\DOM\Element::__construct + * @covers \MensBeam\HTML\DOM\Node::__construct + * @covers \MensBeam\HTML\DOM\Node::getInnerDocument + * @covers \MensBeam\HTML\DOM\Node::hasChildNodes + * @covers \MensBeam\HTML\DOM\Node::postParsingTemplatesFix + * @covers \MensBeam\HTML\DOM\Inner\Document::__construct + * @covers \MensBeam\HTML\DOM\Inner\Document::__get_xpath + * @covers \MensBeam\HTML\DOM\Inner\Document::getWrapperNode + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::get + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::has + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::key + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::set + * @covers \MensBeam\HTML\DOM\Inner\Reflection::createFromProtectedConstructor + */ + public function testMethod_offsetUnset(): void { + $d = new Document(''); + unset($d['ook']); + $this->assertSame(HTMLElement::class, $d['ook']::class); + } + /** * @covers \MensBeam\HTML\DOM\Document::adoptNode * @@ -158,6 +315,23 @@ class TestDocument extends \PHPUnit\Framework\TestCase { } + /** + * @covers \MensBeam\HTML\DOM\Document::getElementsByName + * + * @covers \MensBeam\HTML\DOM\Collection::__construct + * @covers \MensBeam\HTML\DOM\Collection::__get_length + * @covers \MensBeam\HTML\DOM\Collection::count + * @covers \MensBeam\HTML\DOM\Document::__construct + * @covers \MensBeam\HTML\DOM\Document::load + * @covers \MensBeam\HTML\DOM\DOMImplementation::__construct + * @covers \MensBeam\HTML\DOM\Node::__construct + * @covers \MensBeam\HTML\DOM\Node::getInnerDocument + * @covers \MensBeam\HTML\DOM\Node::hasChildNodes + * @covers \MensBeam\HTML\DOM\Node::postParsingTemplatesFix + * @covers \MensBeam\HTML\DOM\Inner\Document::__construct + * @covers \MensBeam\HTML\DOM\Inner\Document::__get_xpath + * @covers \MensBeam\HTML\DOM\Inner\Reflection::createFromProtectedConstructor + */ public function testMethod_getElementsByName() { $d = new Document('
'); $this->assertEquals(2, $d->getElementsByName('ook')->length); @@ -493,6 +667,24 @@ class TestDocument extends \PHPUnit\Framework\TestCase { } + /** + * @covers \MensBeam\HTML\DOM\Document::__get_embeds + * + * @covers \MensBeam\HTML\DOM\Collection::__construct + * @covers \MensBeam\HTML\DOM\Collection::__get_length + * @covers \MensBeam\HTML\DOM\Collection::count + * @covers \MensBeam\HTML\DOM\Document::__construct + * @covers \MensBeam\HTML\DOM\Document::__get_plugins + * @covers \MensBeam\HTML\DOM\Document::load + * @covers \MensBeam\HTML\DOM\DOMImplementation::__construct + * @covers \MensBeam\HTML\DOM\Node::__construct + * @covers \MensBeam\HTML\DOM\Node::getInnerDocument + * @covers \MensBeam\HTML\DOM\Node::hasChildNodes + * @covers \MensBeam\HTML\DOM\Node::postParsingTemplatesFix + * @covers \MensBeam\HTML\DOM\Inner\Document::__construct + * @covers \MensBeam\HTML\DOM\Inner\Document::__get_xpath + * @covers \MensBeam\HTML\DOM\Inner\Reflection::createFromProtectedConstructor + */ public function testProperty_embeds() { $d = new Document('
'); $this->assertEquals(4, $d->embeds->length); @@ -500,12 +692,74 @@ class TestDocument extends \PHPUnit\Framework\TestCase { } + /** + * @covers \MensBeam\HTML\DOM\Document::__get_forms + * + * @covers \MensBeam\HTML\DOM\Collection::__construct + * @covers \MensBeam\HTML\DOM\Collection::__get_length + * @covers \MensBeam\HTML\DOM\Collection::count + * @covers \MensBeam\HTML\DOM\Document::__construct + * @covers \MensBeam\HTML\DOM\Document::createDocumentFragment + * @covers \MensBeam\HTML\DOM\Document::load + * @covers \MensBeam\HTML\DOM\DocumentFragment::__construct + * @covers \MensBeam\HTML\DOM\DOMImplementation::__construct + * @covers \MensBeam\HTML\DOM\Element::__construct + * @covers \MensBeam\HTML\DOM\HTMLTemplateElement::__construct + * @covers \MensBeam\HTML\DOM\HTMLTemplateElement::__get_content + * @covers \MensBeam\HTML\DOM\Node::__construct + * @covers \MensBeam\HTML\DOM\Node::__get_ownerDocument + * @covers \MensBeam\HTML\DOM\Node::appendChildInner + * @covers \MensBeam\HTML\DOM\Node::cloneInnerNode + * @covers \MensBeam\HTML\DOM\Node::getInnerDocument + * @covers \MensBeam\HTML\DOM\Node::getInnerNode + * @covers \MensBeam\HTML\DOM\Node::getRootNode + * @covers \MensBeam\HTML\DOM\Node::hasChildNodes + * @covers \MensBeam\HTML\DOM\Node::postInsertionBugFixes + * @covers \MensBeam\HTML\DOM\Node::postParsingTemplatesFix + * @covers \MensBeam\HTML\DOM\Node::preInsertionBugFixes + * @covers \MensBeam\HTML\DOM\Inner\Document::__construct + * @covers \MensBeam\HTML\DOM\Inner\Document::__get_wrapperNode + * @covers \MensBeam\HTML\DOM\Inner\Document::__get_xpath + * @covers \MensBeam\HTML\DOM\Inner\Document::getWrapperNode + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::get + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::has + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::key + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::set + * @covers \MensBeam\HTML\DOM\Inner\Reflection::createFromProtectedConstructor + * @covers \MensBeam\HTML\DOM\Inner\Reflection::getProtectedProperty + * @covers \MensBeam\HTML\DOM\Inner\Reflection::setProtectedProperties + */ public function testProperty_forms() { $d = new Document('
'); $this->assertEquals(4, $d->forms->length); } + /** + * @covers \MensBeam\HTML\DOM\Document::__get_head + * + * @covers \MensBeam\HTML\DOM\Document::__construct + * @covers \MensBeam\HTML\DOM\Document::createElement + * @covers \MensBeam\HTML\DOM\DOMImplementation::__construct + * @covers \MensBeam\HTML\DOM\Element::__construct + * @covers \MensBeam\HTML\DOM\Node::__construct + * @covers \MensBeam\HTML\DOM\Node::appendChild + * @covers \MensBeam\HTML\DOM\Node::getInnerDocument + * @covers \MensBeam\HTML\DOM\Node::getInnerNode + * @covers \MensBeam\HTML\DOM\Node::getRootNode + * @covers \MensBeam\HTML\DOM\Node::postInsertionBugFixes + * @covers \MensBeam\HTML\DOM\Node::preInsertionBugFixes + * @covers \MensBeam\HTML\DOM\Node::preInsertionValidity + * @covers \MensBeam\HTML\DOM\Inner\Document::__construct + * @covers \MensBeam\HTML\DOM\Inner\Document::__get_wrapperNode + * @covers \MensBeam\HTML\DOM\Inner\Document::getWrapperNode + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::get + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::has + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::key + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::set + * @covers \MensBeam\HTML\DOM\Inner\Reflection::createFromProtectedConstructor + * @covers \MensBeam\HTML\DOM\Inner\Reflection::getProtectedProperty + */ public function testProperty_head() { $d = new Document(); $this->assertNull($d->head); @@ -517,24 +771,168 @@ class TestDocument extends \PHPUnit\Framework\TestCase { } + /** + * @covers \MensBeam\HTML\DOM\Document::__get_images + * + * @covers \MensBeam\HTML\DOM\Collection::__construct + * @covers \MensBeam\HTML\DOM\Collection::__get_length + * @covers \MensBeam\HTML\DOM\Collection::count + * @covers \MensBeam\HTML\DOM\Document::__construct + * @covers \MensBeam\HTML\DOM\Document::createDocumentFragment + * @covers \MensBeam\HTML\DOM\Document::load + * @covers \MensBeam\HTML\DOM\DocumentFragment::__construct + * @covers \MensBeam\HTML\DOM\DOMImplementation::__construct + * @covers \MensBeam\HTML\DOM\Element::__construct + * @covers \MensBeam\HTML\DOM\HTMLTemplateElement::__construct + * @covers \MensBeam\HTML\DOM\HTMLTemplateElement::__get_content + * @covers \MensBeam\HTML\DOM\Node::__construct + * @covers \MensBeam\HTML\DOM\Node::__get_ownerDocument + * @covers \MensBeam\HTML\DOM\Node::appendChildInner + * @covers \MensBeam\HTML\DOM\Node::cloneInnerNode + * @covers \MensBeam\HTML\DOM\Node::getInnerDocument + * @covers \MensBeam\HTML\DOM\Node::getInnerNode + * @covers \MensBeam\HTML\DOM\Node::getRootNode + * @covers \MensBeam\HTML\DOM\Node::hasChildNodes + * @covers \MensBeam\HTML\DOM\Node::postInsertionBugFixes + * @covers \MensBeam\HTML\DOM\Node::postParsingTemplatesFix + * @covers \MensBeam\HTML\DOM\Node::preInsertionBugFixes + * @covers \MensBeam\HTML\DOM\Inner\Document::__construct + * @covers \MensBeam\HTML\DOM\Inner\Document::__get_wrapperNode + * @covers \MensBeam\HTML\DOM\Inner\Document::__get_xpath + * @covers \MensBeam\HTML\DOM\Inner\Document::getWrapperNode + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::get + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::has + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::key + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::set + * @covers \MensBeam\HTML\DOM\Inner\Reflection::createFromProtectedConstructor + * @covers \MensBeam\HTML\DOM\Inner\Reflection::getProtectedProperty + * @covers \MensBeam\HTML\DOM\Inner\Reflection::setProtectedProperties + */ public function testProperty_images() { $d = new Document('
'); $this->assertEquals(4, $d->images->length); } + /** + * @covers \MensBeam\HTML\DOM\Document::__get_links + * + * @covers \MensBeam\HTML\DOM\Collection::__construct + * @covers \MensBeam\HTML\DOM\Collection::__get_length + * @covers \MensBeam\HTML\DOM\Collection::count + * @covers \MensBeam\HTML\DOM\Document::__construct + * @covers \MensBeam\HTML\DOM\Document::createDocumentFragment + * @covers \MensBeam\HTML\DOM\Document::load + * @covers \MensBeam\HTML\DOM\DocumentFragment::__construct + * @covers \MensBeam\HTML\DOM\DOMImplementation::__construct + * @covers \MensBeam\HTML\DOM\Element::__construct + * @covers \MensBeam\HTML\DOM\HTMLTemplateElement::__construct + * @covers \MensBeam\HTML\DOM\HTMLTemplateElement::__get_content + * @covers \MensBeam\HTML\DOM\Node::__construct + * @covers \MensBeam\HTML\DOM\Node::__get_ownerDocument + * @covers \MensBeam\HTML\DOM\Node::appendChildInner + * @covers \MensBeam\HTML\DOM\Node::cloneInnerNode + * @covers \MensBeam\HTML\DOM\Node::getInnerDocument + * @covers \MensBeam\HTML\DOM\Node::getInnerNode + * @covers \MensBeam\HTML\DOM\Node::getRootNode + * @covers \MensBeam\HTML\DOM\Node::hasChildNodes + * @covers \MensBeam\HTML\DOM\Node::postInsertionBugFixes + * @covers \MensBeam\HTML\DOM\Node::postParsingTemplatesFix + * @covers \MensBeam\HTML\DOM\Node::preInsertionBugFixes + * @covers \MensBeam\HTML\DOM\Inner\Document::__construct + * @covers \MensBeam\HTML\DOM\Inner\Document::__get_wrapperNode + * @covers \MensBeam\HTML\DOM\Inner\Document::__get_xpath + * @covers \MensBeam\HTML\DOM\Inner\Document::getWrapperNode + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::get + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::has + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::key + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::set + * @covers \MensBeam\HTML\DOM\Inner\Reflection::createFromProtectedConstructor + * @covers \MensBeam\HTML\DOM\Inner\Reflection::getProtectedProperty + * @covers \MensBeam\HTML\DOM\Inner\Reflection::setProtectedProperties + */ public function testProperty_links() { $d = new Document('
'); $this->assertEquals(4, $d->links->length); } + /** + * @covers \MensBeam\HTML\DOM\Document::__get_scripts + * + * @covers \MensBeam\HTML\DOM\Collection::__construct + * @covers \MensBeam\HTML\DOM\Collection::__get_length + * @covers \MensBeam\HTML\DOM\Collection::count + * @covers \MensBeam\HTML\DOM\Document::__construct + * @covers \MensBeam\HTML\DOM\Document::createDocumentFragment + * @covers \MensBeam\HTML\DOM\Document::load + * @covers \MensBeam\HTML\DOM\DocumentFragment::__construct + * @covers \MensBeam\HTML\DOM\DOMImplementation::__construct + * @covers \MensBeam\HTML\DOM\Element::__construct + * @covers \MensBeam\HTML\DOM\HTMLTemplateElement::__construct + * @covers \MensBeam\HTML\DOM\HTMLTemplateElement::__get_content + * @covers \MensBeam\HTML\DOM\Node::__construct + * @covers \MensBeam\HTML\DOM\Node::__get_ownerDocument + * @covers \MensBeam\HTML\DOM\Node::appendChildInner + * @covers \MensBeam\HTML\DOM\Node::cloneInnerNode + * @covers \MensBeam\HTML\DOM\Node::getInnerDocument + * @covers \MensBeam\HTML\DOM\Node::getInnerNode + * @covers \MensBeam\HTML\DOM\Node::getRootNode + * @covers \MensBeam\HTML\DOM\Node::hasChildNodes + * @covers \MensBeam\HTML\DOM\Node::postInsertionBugFixes + * @covers \MensBeam\HTML\DOM\Node::postParsingTemplatesFix + * @covers \MensBeam\HTML\DOM\Node::preInsertionBugFixes + * @covers \MensBeam\HTML\DOM\Inner\Document::__construct + * @covers \MensBeam\HTML\DOM\Inner\Document::__get_wrapperNode + * @covers \MensBeam\HTML\DOM\Inner\Document::__get_xpath + * @covers \MensBeam\HTML\DOM\Inner\Document::getWrapperNode + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::get + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::has + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::key + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::set + * @covers \MensBeam\HTML\DOM\Inner\Reflection::createFromProtectedConstructor + * @covers \MensBeam\HTML\DOM\Inner\Reflection::getProtectedProperty + * @covers \MensBeam\HTML\DOM\Inner\Reflection::setProtectedProperties + */ public function testProperty_scripts() { $d = new Document('
'); $this->assertEquals(4, $d->scripts->length); } + /** + * @covers \MensBeam\HTML\DOM\Document::__get_title + * @covers \MensBeam\HTML\DOM\Document::__set_title + * + * @covers \MensBeam\HTML\DOM\Document::__construct + * @covers \MensBeam\HTML\DOM\Document::__get_documentElement + * @covers \MensBeam\HTML\DOM\Document::createElement + * @covers \MensBeam\HTML\DOM\Document::createElementNS + * @covers \MensBeam\HTML\DOM\DocumentOrElement::validateAndExtract + * @covers \MensBeam\HTML\DOM\DOMImplementation::__construct + * @covers \MensBeam\HTML\DOM\DOMImplementation::createDocument + * @covers \MensBeam\HTML\DOM\Element::__construct + * @covers \MensBeam\HTML\DOM\Element::__get_namespaceURI + * @covers \MensBeam\HTML\DOM\Node::__construct + * @covers \MensBeam\HTML\DOM\Node::__get_ownerDocument + * @covers \MensBeam\HTML\DOM\Node::appendChild + * @covers \MensBeam\HTML\DOM\Node::getInnerDocument + * @covers \MensBeam\HTML\DOM\Node::getInnerNode + * @covers \MensBeam\HTML\DOM\Node::getRootNode + * @covers \MensBeam\HTML\DOM\Node::postInsertionBugFixes + * @covers \MensBeam\HTML\DOM\Node::preInsertionBugFixes + * @covers \MensBeam\HTML\DOM\Node::preInsertionValidity + * @covers \MensBeam\HTML\DOM\Inner\Document::__construct + * @covers \MensBeam\HTML\DOM\Inner\Document::__get_wrapperNode + * @covers \MensBeam\HTML\DOM\Inner\Document::getWrapperNode + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::get + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::has + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::key + * @covers \MensBeam\HTML\DOM\Inner\NodeCache::set + * @covers \MensBeam\HTML\DOM\Inner\Reflection::createFromProtectedConstructor + * @covers \MensBeam\HTML\DOM\Inner\Reflection::getProtectedProperty + * @covers \MensBeam\HTML\DOM\Inner\Reflection::setProtectedProperties + */ public function testProperty_title() { $d = new Document(); $this->assertSame('', $d->title);