Browse Source

Added NodeTrait::isEqualNode

wrapper-classes
Dustin Wilson 3 years ago
parent
commit
1080c7e876
  1. 86
      lib/traits/NodeTrait.php
  2. 53
      tests/cases/TestNodeTrait.php
  3. 2
      tests/phpunit.dist.xml
  4. 1
      vendor-bin/phpunit/composer.lock

86
lib/traits/NodeTrait.php

@ -114,6 +114,92 @@ trait NodeTrait {
return Node::DOCUMENT_POSITION_FOLLOWING;
}
public function isEqualNode(\DOMDocumentType|Node $otherNode): bool {
# The isEqualNode(otherNode) method steps are to return true if otherNode is
# non-null and this equals otherNode; otherwise false.
# A node A equals a node B if all of the following conditions are true:
#
# • A and B implement the same interfaces.
if ($this::class !== $otherNode::class) {
return false;
}
# • The following are equal, switching on the interface A implements:
$thisClass = substr($this::class, strrpos($this::class, '\\') + 1);
switch ($thisClass) {
# - DocumentType
# Its name, public ID, and system ID.
// DEVIATION: $this can never be a \DOMDocumentType seeing as we we cannot extend
// \DOMDocumentType, so there is no need to check for it.
# - Element
# Its namespace, namespace prefix, local name, and its attribute list’s size.
// PCOV is stupid
// @codeCoverageIgnoreStart
case 'Element':
// @codeCoverageIgnoreEnd
if ($this->namespaceURI !== $otherNode->namespaceURI || $this->prefix !== $otherNode->prefix || $this->localName !== $otherNode->localName || $this->attributes->length !== $otherNode->attributes->length) {
return false;
}
# • If A is an element, each attribute in its attribute list has an attribute that
# equals an attribute in B’s attribute list.
foreach ($this->attributes as $key => $attr) {
if (!$attr->isEqualNode($otherNode->attributes[$key])) {
return false;
}
}
break;
# - Attr
# Its namespace, local name, and value.
// PCOV is stupid
// @codeCoverageIgnoreStart
case 'Attr':
// @codeCoverageIgnoreEnd
if ($this->namespaceURI !== $otherNode->namespaceURI || $this->localName !== $otherNode->localName || $this->value !== $otherNode->value) {
return false;
}
break;
# - Text
# - Comment
# Its data.
// PCOV is stupid
// @codeCoverageIgnoreStart
case 'Text':
case 'Comment':
// @codeCoverageIgnoreEnd
if ($this->data !== $otherNode->data) {
return false;
}
break;
}
if ($this instanceof Document || $this instanceof DocumentFragment || $this instanceof Element) {
# • A and B have the same number of children.
if ($this->childNodes->length !== $otherNode->childNodes->length) {
return false;
}
# • Each child of A equals the child of B at the identical index.
foreach ($this->childNodes as $key => $child) {
// Have to work around the fact we cannot extend \DOMDocumentType
if (!$child instanceof \DOMDocumentType) {
if (!$child->isEqualNode($otherNode->childNodes[$key])) {
return false;
}
} else {
$other = $otherNode->childNodes[$key];
if ($child->name !== $other->name || $child->publicId !== $other->publicId || $child->systemId !== $other->systemId) {
return false;
}
}
}
}
return true;
}
// Disable getLineNo
public function getLineNo(): int {
throw new DOMException(DOMException::NOT_SUPPORTED, __METHOD__ . ' is not in the standard, is buggy, and useless');

53
tests/cases/TestBaseNode.php → tests/cases/TestNodeTrait.php

@ -15,8 +15,8 @@ use MensBeam\HTML\DOM\{
};
/** @covers \MensBeam\HTML\DOM\Node */
class TestBaseNode extends \PHPUnit\Framework\TestCase {
/** @covers \MensBeam\HTML\DOM\NodeTrait */
class TestNodeTrait extends \PHPUnit\Framework\TestCase {
/** @covers \MensBeam\HTML\DOM\NodeTrait::compareDocumentPosition */
public function testCompareDocumentPosition(): void {
$d = new Document();
@ -99,4 +99,53 @@ class TestBaseNode extends \PHPUnit\Framework\TestCase {
$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));
}
}

2
tests/phpunit.dist.xml

@ -16,7 +16,6 @@
</coverage>
<testsuites>
<testsuite name="DOM">
<file>cases/TestBaseNode.php</file>
<file>cases/TestChildNode.php</file>
<file>cases/TestDocument.php</file>
<file>cases/TestDocumentFragment.php</file>
@ -24,6 +23,7 @@
<file>cases/TestElement.php</file>
<file>cases/TestElementMap.php</file>
<file>cases/TestLeafNode.php</file>
<file>cases/TestNodeTrait.php</file>
<file>cases/TestParentNode.php</file>
<file>cases/TestTokenList.php</file>
</testsuite>

1
vendor-bin/phpunit/composer.lock

@ -1800,6 +1800,7 @@
"type": "github"
}
],
"abandoned": true,
"time": "2020-09-28T06:45:17+00:00"
},
{

Loading…
Cancel
Save