HTMLCollection 100% covered

This commit is contained in:
Dustin Wilson 2021-12-15 15:49:14 -06:00
parent 90e07f02d5
commit 6eb07562da
4 changed files with 165 additions and 5 deletions

View file

@ -43,10 +43,43 @@ class HTMLCollection extends Collection {
}
public function offsetGet($offset): ?Element {
return (is_int($offset)) ? $this->item($offset) : $this->namedItem($offset);
if (is_int($offset)) {
return $this->item($offset);
}
# The supported property names are the values from the list returned by these
# steps:
# 1. Let result be an empty list.
# 2. For each element represented by the collection, in tree order:
# 1. If element has an ID which is not in result, append elements ID to
# result.
# 2. If element is in the HTML namespace and has a name attribute whose value is
# neither the empty string nor is in result, append elements name attribute value
# to result.
# 3. Return result.
// The spec is extremely vague as to what to do here, but it seems to expect
// this to be some sort of live private property that the class will poll to
// check for valid property names when trying to access them. This is
// inefficient. Going to do basically the same thing but not return a list of
// every one. It will just search the list instead using the same process.
$document = $this->innerDocument->wrapperNode;
foreach ($this->innerCollection as $node) {
if ($node->getAttribute('id') === $offset) {
return $this->innerDocument->getWrapperNode($node);
}
}
foreach ($this->innerCollection as $node) {
if (!$document instanceof XMLDocument && $node->namespaceURI === null && $node->getAttribute('name') === $offset) {
return $this->innerDocument->getWrapperNode($node);
}
}
return null;
}
public function offsetExists($offset): bool {
return (((is_int($offset)) ? $this->item($offset) : $this->namedItem($offset)) !== null);
return ($this->offsetGet($offset) !== null);
}
}

View file

@ -56,8 +56,6 @@ class NamedNodeMap extends Collection {
# A NamedNodeMap objects supported property names are the return value of running
# these steps:
# 1. Let names be the qualified names of the attributes in this NamedNodeMap objects
# attribute list, with duplicates omitted, in order.
// The spec is extremely vague as to what to do here, but it seems to expect
// this to be some sort of live private property that the class will poll to
// check for valid property names when trying to access them. This is
@ -65,6 +63,8 @@ class NamedNodeMap extends Collection {
// every one. It will just search the element's attribute list instead using the
// same process.
# 1. Let names be the qualified names of the attributes in this NamedNodeMap objects
# attribute list, with duplicates omitted, in order.
# 2. If this NamedNodeMap objects element is in the HTML namespace and its node
# document is an HTML document, then for each name in names:
# 1. Let lowercaseName be name, in ASCII lowercase.
@ -105,7 +105,7 @@ class NamedNodeMap extends Collection {
}
public function offsetExists($offset): bool {
return (((is_int($offset)) ? $this->item($offset) : $this->getNamedItem($offset)) !== null);
return ($this->offsetGet($offset) !== null);
}
public function removeNamedItem(string $qualifiedName): ?Attr {

View file

@ -0,0 +1,126 @@
<?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,
Node
};
/** @covers \MensBeam\HTML\DOM\HTMLCollection */
class TestHTMLCollection extends \PHPUnit\Framework\TestCase {
/**
* @covers \MensBeam\HTML\DOM\HTMLCollection::current
* @covers \MensBeam\HTML\DOM\HTMLCollection::item
* @covers \MensBeam\HTML\DOM\HTMLCollection::offsetExists
* @covers \MensBeam\HTML\DOM\HTMLCollection::offsetGet
*
* @covers \MensBeam\HTML\DOM\Collection::__construct
* @covers \MensBeam\HTML\DOM\Collection::current
* @covers \MensBeam\HTML\DOM\Collection::item
* @covers \MensBeam\HTML\DOM\Collection::key
* @covers \MensBeam\HTML\DOM\Collection::next
* @covers \MensBeam\HTML\DOM\Collection::rewind
* @covers \MensBeam\HTML\DOM\Collection::valid
* @covers \MensBeam\HTML\DOM\Document::__construct
* @covers \MensBeam\HTML\DOM\Document::__get_body
* @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\ParentNode::__get_children
* @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 testIteration(): void {
$d = new Document(<<<HTML
<!DOCTYPE html>
<html>
<body>
<div id="ook">Ook</div>
<div id="eek">Eek</div>
<div id="ack">Ack</div>
<div name="ook">Ook</div>
<div name="poop💩">poop💩</div>
</body>
</html>
HTML, 'UTF-8');
$body = $d->body;
$children = $body->children;
foreach ($children as $key => $child) {
$this->assertTrue($child instanceof Element);
}
}
/**
* @covers \MensBeam\HTML\DOM\HTMLCollection::namedItem
* @covers \MensBeam\HTML\DOM\HTMLCollection::offsetGet
*
* @covers \MensBeam\HTML\DOM\CharacterData::__get_data
* @covers \MensBeam\HTML\DOM\Collection::__construct
* @covers \MensBeam\HTML\DOM\Document::__construct
* @covers \MensBeam\HTML\DOM\Document::__get_body
* @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::__get_firstChild
* @covers \MensBeam\HTML\DOM\Node::getInnerDocument
* @covers \MensBeam\HTML\DOM\Node::hasChildNodes
* @covers \MensBeam\HTML\DOM\Node::postParsingTemplatesFix
* @covers \MensBeam\HTML\DOM\ParentNode::__get_children
* @covers \MensBeam\HTML\DOM\Text::__construct
* @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
*/
public function testMethod_namedItem_offsetGet(): void {
$d = new Document(<<<HTML
<!DOCTYPE html>
<html>
<body>
<div id="ook">Ook</div>
<div id="eek">Eek</div>
<div id="ack">Ack</div>
<div name="ook">Ook</div>
<div name="poop💩">poop💩</div>
</body>
</html>
HTML, 'UTF-8');
$body = $d->body;
$children = $body->children;
$this->assertSame($children[0], $children['ook']);
$this->assertSame($children[0], $children->namedItem('ook'));
$this->assertSame('Ook', $children['ook']->firstChild->data);
$this->assertSame('poop💩', $children['poop💩']->firstChild->data);
$this->assertNull($children['fail']);
$this->assertNull($children->namedItem('fail'));
$this->assertNull($children->namedItem(''));
}
}

View file

@ -25,6 +25,7 @@
<file>cases/TestDOMImplementation.php</file>
<file>cases/TestDOMTokenList.php</file>
<file>cases/TestElement.php</file>
<file>cases/TestHTMLCollection.php</file>
<file>cases/TestInnerDocument.php</file>
<file>cases/TestNamedNodeMap.php</file>
<file>cases/TestNode.php</file>