Browse Source

More tests, started documentation

master
Dustin Wilson 2 years ago
parent
commit
5523e09ab2
  1. 116
      README.md
  2. 90
      composer.lock
  3. 9
      lib/HTMLElement.php
  4. 2
      lib/Node.php
  5. 42
      tests/cases/TestDocument.php
  6. 452
      tests/cases/TestHTMLElement.php
  7. 29
      tests/cases/TestHTMLOrSVGElement.php
  8. 1
      tests/phpunit.dist.xml
  9. 19
      vendor-bin/phpunit/composer.lock
  10. 189
      vendor-bin/robo/composer.lock

116
README.md

@ -11,9 +11,94 @@ Modern DOM library written in PHP for HTML documents. This library is an attempt
## Usage ##
Coming soon
Full documentation for most of the library shouldn't be necessary because it largely follows the specification, but because of how the library is to be used there are a few things that are glaringly different. These will be outlined below.
## Examples ##
### MensBeam\HTML\DOM\Document ###
```php
namespace MensBeam\HTML\DOM;
partial class Document {
use DocumentOrElement, NonElementParentNode, ParentNode, XPathEvaluatorBase;
public function __construct(
string $source = null,
?string $charset = null
);
public function serialize(
?Node $node = null,
array $config = []
): string;
}
```
#### MensBeam\HTML\DOM\Document::__construct ####
Creates a new `MensBeam\HTML\DOM\Document` object.
* `source`: A string representing an HTML document to be parsed.
* `charset`: Character set to be used as the encoding for the document. If a document is parsed its default is 'windows-1251', otherwise 'UTF-8'.
#### MensBeam\HTML\DOM\Document::serialize ####
Converts a node to a string.
* `node`: A node within the document to serialize, defaults to the document itself.
* `config`: A configuration array with the possible keys and value types being:
- `booleanAttributeValues` (`bool|null`): Whether to include the values of boolean attributes on HTML elements during serialization. Per the standard this is `true` by default
- `foreignVoidEndTags` (`bool|null`): Whether to print the end tags of foreign void elements rather than self-closing their start tags. Per the standard this is `true` by default
- `indentStep` (`int|null`): The number of spaces or tabs (depending on setting of indentStep) to indent at each step. This is `1` by default and has no effect unless `reformatWhitespace` is `true`
- `indentWithSpaces` (`bool|null`): Whether to use spaces or tabs to indent. This is `true` by default and has no effect unless `reformatWhitespace` is `true`
- `reformatWhitespace` (`bool|null`): Whether to reformat whitespace (pretty-print) or not. This is `false` by default
### MensBeam\HTML\DOM\Node ###
```php
namespace MensBeam\HTML\DOM;
partial abstract class Node implements \Stringable {
// Common namespace constants provided for convenience
public const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
public const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
public const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
public const XLINK_NAMESPACE = 'http://www.w3.org/1999/xlink';
public const XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
public const XMLNS_NAMESPACE = 'http://www.w3.org/2000/xmlns/';
// Used with MensBeam\HTML\DOM\ParentNode::walk
public const WALK_ACCEPT = 0x01;
public const WALK_REJECT = 0x02;
public const WALK_SKIP_CHILDREN = 0x04;
public const WALK_STOP = 0x08;
}
```
### MensBeam\HTML\DOM\ParentNode ###
```php
namespace MensBeam\HTML\DOM;
partial trait ParentNode {
public function walk(
?\Closure $filter = null,
bool $includeReferenceNode = false
): \Generator;
}
```
#### MensBeam\HTML\DOM\ParentNode::walk ####
Applies the callback filter while walking down the DOM tree and yields nodes matching the filter in a generator.
* `filter`: A callback method to filter the DOM tree. Must return only the following values:
- `Node::WALK_ACCEPT`: Accept the node.
- `Node::WALK_REJECT`: Reject the node.
- `Node::WALK_SKIP_CHILDREN`: Skip the node's children.
- `Node::WALK_STOP`: Stop the walker.
* `includeReferenceNode`: Include `$this` when walking down the tree.
### Examples ###
- Creating a new document:
@ -40,6 +125,33 @@ Coming soon
$d->load('<!DOCTYPE html><html><head><title>Ook</title></head><body><h1>Ook!</h1></body></html>');
```
- Serializing a document:
```php
use MensBeam\HTML\DOM;
$d = new Document('<!DOCTYPE html><html></html>');
echo $d->serialize();
```
or:
```php
use MensBeam\HTML\DOM;
$d = new Document('<!DOCTYPE html><html></html>');
echo $d;
```
- Serializing a document (pretty printing):
```php
use MensBeam\HTML\DOM;
$d = new Document('<!DOCTYPE html><html></html>');
echo $d->serialize($d, [ 'reformatWhitespace' => true ]);
```
## Limitations & Differences from Specification ##
The primary aim of this library is accuracy. However, due either to limitations imposed by PHP's DOM, by assumptions made by the specification that aren't applicable to a PHP library, or simply because of impracticality some changes have needed to be made. These are as follows:

90
composer.lock

@ -12,7 +12,7 @@
"source": {
"type": "git",
"url": "mensbeam-gitea:MensBeam/Framework.git",
"reference": "bf7515f4c5d02ce9919a92a27812af7587a4700e"
"reference": "c9aa6b9659c1607a1242d585aa41caf0aba33e5f"
},
"require": {
"php": ">=7.4"
@ -55,7 +55,7 @@
}
],
"description": "Common classes and traits used in many Mensbeam projects",
"time": "2021-10-21T14:20:02+00:00"
"time": "2021-12-29T16:07:18+00:00"
},
{
"name": "mensbeam/html-parser",
@ -293,16 +293,16 @@
},
{
"name": "symfony/css-selector",
"version": "v5.4.0",
"version": "v5.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
"reference": "44b933f98bb4b5220d10bed9ce5662f8c2d13dcc"
"reference": "cfcbee910e159df402603502fe387e8b677c22fd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/44b933f98bb4b5220d10bed9ce5662f8c2d13dcc",
"reference": "44b933f98bb4b5220d10bed9ce5662f8c2d13dcc",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/cfcbee910e159df402603502fe387e8b677c22fd",
"reference": "cfcbee910e159df402603502fe387e8b677c22fd",
"shasum": ""
},
"require": {
@ -339,7 +339,7 @@
"description": "Converts CSS selectors to XPath expressions",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/css-selector/tree/v5.4.0"
"source": "https://github.com/symfony/css-selector/tree/v5.4.2"
},
"funding": [
{
@ -355,7 +355,7 @@
"type": "tidelift"
}
],
"time": "2021-09-09T08:06:01+00:00"
"time": "2021-12-16T21:58:21+00:00"
},
{
"name": "symfony/polyfill-php80",
@ -1445,16 +1445,16 @@
},
{
"name": "symfony/console",
"version": "v5.4.1",
"version": "v5.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "9130e1a0fc93cb0faadca4ee917171bd2ca9e5f4"
"reference": "a2c6b7ced2eb7799a35375fb9022519282b5405e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/9130e1a0fc93cb0faadca4ee917171bd2ca9e5f4",
"reference": "9130e1a0fc93cb0faadca4ee917171bd2ca9e5f4",
"url": "https://api.github.com/repos/symfony/console/zipball/a2c6b7ced2eb7799a35375fb9022519282b5405e",
"reference": "a2c6b7ced2eb7799a35375fb9022519282b5405e",
"shasum": ""
},
"require": {
@ -1524,7 +1524,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v5.4.1"
"source": "https://github.com/symfony/console/tree/v5.4.2"
},
"funding": [
{
@ -1540,7 +1540,7 @@
"type": "tidelift"
}
],
"time": "2021-12-09T11:22:43+00:00"
"time": "2021-12-20T16:11:12+00:00"
},
{
"name": "symfony/deprecation-contracts",
@ -1611,16 +1611,16 @@
},
{
"name": "symfony/http-foundation",
"version": "v5.4.1",
"version": "v5.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "5dad3780023a707f4c24beac7d57aead85c1ce3c"
"reference": "ce952af52877eaf3eab5d0c08cc0ea865ed37313"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/5dad3780023a707f4c24beac7d57aead85c1ce3c",
"reference": "5dad3780023a707f4c24beac7d57aead85c1ce3c",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/ce952af52877eaf3eab5d0c08cc0ea865ed37313",
"reference": "ce952af52877eaf3eab5d0c08cc0ea865ed37313",
"shasum": ""
},
"require": {
@ -1664,7 +1664,7 @@
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/http-foundation/tree/v5.4.1"
"source": "https://github.com/symfony/http-foundation/tree/v5.4.2"
},
"funding": [
{
@ -1680,20 +1680,20 @@
"type": "tidelift"
}
],
"time": "2021-12-09T12:46:57+00:00"
"time": "2021-12-28T17:15:56+00:00"
},
{
"name": "symfony/mime",
"version": "v5.4.0",
"version": "v5.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
"reference": "d4365000217b67c01acff407573906ff91bcfb34"
"reference": "1bfd938cf9562822c05c4d00e8f92134d3c8e42d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/mime/zipball/d4365000217b67c01acff407573906ff91bcfb34",
"reference": "d4365000217b67c01acff407573906ff91bcfb34",
"url": "https://api.github.com/repos/symfony/mime/zipball/1bfd938cf9562822c05c4d00e8f92134d3c8e42d",
"reference": "1bfd938cf9562822c05c4d00e8f92134d3c8e42d",
"shasum": ""
},
"require": {
@ -1747,7 +1747,7 @@
"mime-type"
],
"support": {
"source": "https://github.com/symfony/mime/tree/v5.4.0"
"source": "https://github.com/symfony/mime/tree/v5.4.2"
},
"funding": [
{
@ -1763,7 +1763,7 @@
"type": "tidelift"
}
],
"time": "2021-11-23T10:19:22+00:00"
"time": "2021-12-28T17:15:56+00:00"
},
{
"name": "symfony/polyfill-ctype",
@ -2420,16 +2420,16 @@
},
{
"name": "symfony/process",
"version": "v5.4.0",
"version": "v5.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "5be20b3830f726e019162b26223110c8f47cf274"
"reference": "2b3ba8722c4aaf3e88011be5e7f48710088fb5e4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/5be20b3830f726e019162b26223110c8f47cf274",
"reference": "5be20b3830f726e019162b26223110c8f47cf274",
"url": "https://api.github.com/repos/symfony/process/zipball/2b3ba8722c4aaf3e88011be5e7f48710088fb5e4",
"reference": "2b3ba8722c4aaf3e88011be5e7f48710088fb5e4",
"shasum": ""
},
"require": {
@ -2462,7 +2462,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v5.4.0"
"source": "https://github.com/symfony/process/tree/v5.4.2"
},
"funding": [
{
@ -2478,7 +2478,7 @@
"type": "tidelift"
}
],
"time": "2021-11-28T15:25:38+00:00"
"time": "2021-12-27T21:01:00+00:00"
},
{
"name": "symfony/service-contracts",
@ -2564,16 +2564,16 @@
},
{
"name": "symfony/string",
"version": "v6.0.1",
"version": "v6.0.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "0cfed595758ec6e0a25591bdc8ca733c1896af32"
"reference": "bae261d0c3ac38a1f802b4dfed42094296100631"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/0cfed595758ec6e0a25591bdc8ca733c1896af32",
"reference": "0cfed595758ec6e0a25591bdc8ca733c1896af32",
"url": "https://api.github.com/repos/symfony/string/zipball/bae261d0c3ac38a1f802b4dfed42094296100631",
"reference": "bae261d0c3ac38a1f802b4dfed42094296100631",
"shasum": ""
},
"require": {
@ -2629,7 +2629,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v6.0.1"
"source": "https://github.com/symfony/string/tree/v6.0.2"
},
"funding": [
{
@ -2645,20 +2645,20 @@
"type": "tidelift"
}
],
"time": "2021-12-08T15:13:44+00:00"
"time": "2021-12-16T22:13:01+00:00"
},
{
"name": "symfony/yaml",
"version": "v5.4.0",
"version": "v5.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "034ccc0994f1ae3f7499fa5b1f2e75d5e7a94efc"
"reference": "b9eb163846a61bb32dfc147f7859e274fab38b58"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/034ccc0994f1ae3f7499fa5b1f2e75d5e7a94efc",
"reference": "034ccc0994f1ae3f7499fa5b1f2e75d5e7a94efc",
"url": "https://api.github.com/repos/symfony/yaml/zipball/b9eb163846a61bb32dfc147f7859e274fab38b58",
"reference": "b9eb163846a61bb32dfc147f7859e274fab38b58",
"shasum": ""
},
"require": {
@ -2704,7 +2704,7 @@
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/yaml/tree/v5.4.0"
"source": "https://github.com/symfony/yaml/tree/v5.4.2"
},
"funding": [
{
@ -2720,7 +2720,7 @@
"type": "tidelift"
}
],
"time": "2021-11-28T15:25:38+00:00"
"time": "2021-12-16T21:58:21+00:00"
},
{
"name": "webuni/front-matter",
@ -2808,5 +2808,5 @@
"ext-dom": "*"
},
"platform-dev": [],
"plugin-api-version": "2.2.0"
"plugin-api-version": "2.1.0"
}

9
lib/HTMLElement.php

@ -437,7 +437,7 @@ class HTMLElement extends Element {
return ($this->getAttribute('spellcheck') === 'true');
}
protected function __set_spellcheck(bool $value): bool {
protected function __set_spellcheck(bool $value): void {
# On setting, if the new value is true, then the element's spellcheck content
# attribute must be set to the literal string "true", otherwise it must be set
# to the literal string "false".
@ -468,7 +468,7 @@ class HTMLElement extends Element {
# element's translation mode is in the same state as its parent element's, if
# any, or in the translate-enabled state, if the element is a document element.
$value = strtolower($this->getAttribute('translate'));
$value = strtolower($this->getAttribute('translate') ?? '');
if ($value === 'yes') {
return true;
} elseif ($value === 'no') {
@ -478,7 +478,10 @@ class HTMLElement extends Element {
$n = $this->innerNode;
$doc = $n->ownerDocument;
while ($n = $n->parentNode) {
if ($n->getAttribute('translate') === 'yes' && $doc->getWrapperNode($n) instanceof HTMLElement) {
// This looks weird but it's faster to check for the method here first because
// getting a wrapper node causes a wrapper element to be created if it doesn't
// already exist. Don't want to create unnecessary wrappers.
if (method_exists($n, 'getAttribute') && $n->getAttribute('translate') === 'yes' && $doc->getWrapperNode($n) instanceof HTMLElement) {
return true;
}
}

2
lib/Node.php

@ -16,7 +16,7 @@ use MensBeam\HTML\DOM\Inner\{
};
abstract class Node {
abstract class Node implements \Stringable {
use MagicProperties, NameCoercion;
// Namespace constants

42
tests/cases/TestDocument.php

@ -619,6 +619,48 @@ class TestDocument extends \PHPUnit\Framework\TestCase {
}
/**
* @covers \MensBeam\HTML\DOM\Document::__get_dir
* @covers \MensBeam\HTML\DOM\Document::__set_dir
*
* @covers \MensBeam\HTML\DOM\Attr::__get_value
* @covers \MensBeam\HTML\DOM\Document::__construct
* @covers \MensBeam\HTML\DOM\Document::__get_documentElement
* @covers \MensBeam\HTML\DOM\Document::load
* @covers \MensBeam\HTML\DOM\DOMImplementation::__construct
* @covers \MensBeam\HTML\DOM\Element::__construct
* @covers \MensBeam\HTML\DOM\Element::__get_localName
* @covers \MensBeam\HTML\DOM\Element::__get_namespaceURI
* @covers \MensBeam\HTML\DOM\Element::__get_prefix
* @covers \MensBeam\HTML\DOM\Element::__get_tagName
* @covers \MensBeam\HTML\DOM\Element::getAttribute
* @covers \MensBeam\HTML\DOM\Element::getAttributeNode
* @covers \MensBeam\HTML\DOM\Element::setAttribute
* @covers \MensBeam\HTML\DOM\HTMLElement::__get_dir
* @covers \MensBeam\HTML\DOM\HTMLElement::__set_dir
* @covers \MensBeam\HTML\DOM\Node::__construct
* @covers \MensBeam\HTML\DOM\Node::__get_ownerDocument
* @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_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 testProperty_dir(): void {
$d = new Document('<!DOCTYPE html><html dir="ltr"></html>');
$this->assertSame('ltr', $d->dir);
$d->dir = 'bullshit';
$this->assertSame('', $d->dir);
}
/**
* @covers \MensBeam\HTML\DOM\Document::__get_doctype
*

452
tests/cases/TestHTMLElement.php

@ -16,6 +16,35 @@ use MensBeam\HTML\DOM\{
/** @covers \MensBeam\HTML\DOM\HTMLElement */
class TestHTMLElement extends \PHPUnit\Framework\TestCase {
/**
* @covers \MensBeam\HTML\DOM\HTMLElement::__get_accessKey
* @covers \MensBeam\HTML\DOM\HTMLElement::__set_accessKey
*
* @covers \MensBeam\HTML\DOM\Attr::__get_value
* @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\Element::__get_namespaceURI
* @covers \MensBeam\HTML\DOM\Element::getAttribute
* @covers \MensBeam\HTML\DOM\Element::getAttributeNode
* @covers \MensBeam\HTML\DOM\Element::setAttribute
* @covers \MensBeam\HTML\DOM\Node::__construct
* @covers \MensBeam\HTML\DOM\Node::__get_ownerDocument
* @covers \MensBeam\HTML\DOM\Node::getInnerDocument
* @covers \MensBeam\HTML\DOM\Node::hasChildNodes
* @covers \MensBeam\HTML\DOM\Node::postParsingTemplatesFix
* @covers \MensBeam\HTML\DOM\NonElementParentNode::getElementById
* @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 testProperty_accessKey(): void {
$d = new Document('<!DOCTYPE html><html><body><a id="ook" href="https://ook.com" accesskey="o"></a></body></html>');
$ook = $d->getElementById('ook');
@ -24,6 +53,39 @@ class TestHTMLElement extends \PHPUnit\Framework\TestCase {
$this->assertSame('e', $ook->accessKey);
}
/**
* @covers \MensBeam\HTML\DOM\HTMLElement::__get_autocapitalize
* @covers \MensBeam\HTML\DOM\HTMLElement::__set_autocapitalize
*
* @covers \MensBeam\HTML\DOM\Collection::__construct
* @covers \MensBeam\HTML\DOM\Collection::item
* @covers \MensBeam\HTML\DOM\Document::__construct
* @covers \MensBeam\HTML\DOM\Document::load
* @covers \MensBeam\HTML\DOM\DocumentOrElement::getElementsByTagName
* @covers \MensBeam\HTML\DOM\DOMImplementation::__construct
* @covers \MensBeam\HTML\DOM\Element::__construct
* @covers \MensBeam\HTML\DOM\Element::__get_namespaceURI
* @covers \MensBeam\HTML\DOM\Element::removeAttribute
* @covers \MensBeam\HTML\DOM\Element::setAttribute
* @covers \MensBeam\HTML\DOM\HTMLCollection::item
* @covers \MensBeam\HTML\DOM\HTMLCollection::offsetGet
* @covers \MensBeam\HTML\DOM\HTMLElement::autoCapitalizationHint
* @covers \MensBeam\HTML\DOM\Node::__construct
* @covers \MensBeam\HTML\DOM\Node::__get_ownerDocument
* @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_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 testProperty_autocapitalize(): void {
$d = new Document('<!DOCTYPE html><html><body><form><input type="text" autocapitalize="on"></form></body></html>');
$ook = $d->getElementsByTagName('input')[0];
@ -41,6 +103,46 @@ class TestHTMLElement extends \PHPUnit\Framework\TestCase {
$this->assertSame('sentences', $ook->autocapitalize);
}
/**
* @covers \MensBeam\HTML\DOM\HTMLElement::__get_contentEditable
* @covers \MensBeam\HTML\DOM\HTMLElement::__set_contentEditable
* @covers \MensBeam\HTML\DOM\HTMLElement::__get_isContentEditable
*
* @covers \MensBeam\HTML\DOM\Attr::__get_value
* @covers \MensBeam\HTML\DOM\Collection::__construct
* @covers \MensBeam\HTML\DOM\Collection::item
* @covers \MensBeam\HTML\DOM\Document::__construct
* @covers \MensBeam\HTML\DOM\Document::__get_body
* @covers \MensBeam\HTML\DOM\Document::__get_designMode
* @covers \MensBeam\HTML\DOM\Document::__set_designMode
* @covers \MensBeam\HTML\DOM\Document::load
* @covers \MensBeam\HTML\DOM\DocumentOrElement::getElementsByTagName
* @covers \MensBeam\HTML\DOM\DOMImplementation::__construct
* @covers \MensBeam\HTML\DOM\Element::__construct
* @covers \MensBeam\HTML\DOM\Element::__get_namespaceURI
* @covers \MensBeam\HTML\DOM\Element::getAttribute
* @covers \MensBeam\HTML\DOM\Element::getAttributeNode
* @covers \MensBeam\HTML\DOM\Element::hasAttribute
* @covers \MensBeam\HTML\DOM\Element::removeAttribute
* @covers \MensBeam\HTML\DOM\Element::setAttribute
* @covers \MensBeam\HTML\DOM\HTMLCollection::item
* @covers \MensBeam\HTML\DOM\HTMLCollection::offsetGet
* @covers \MensBeam\HTML\DOM\Node::__construct
* @covers \MensBeam\HTML\DOM\Node::__get_ownerDocument
* @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_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 testProperty_contentEditable_isContentEditable(): void {
$d = new Document('<!DOCTYPE html><html><body><div></div></body></html>');
$div = $d->getElementsByTagName('div')[0];
@ -62,8 +164,35 @@ class TestHTMLElement extends \PHPUnit\Framework\TestCase {
$d->designMode = 'on';
$this->assertTrue($div->isContentEditable);
$d->body->contentEditable = 'false';
$d->designMode = 'off';
$this->assertFalse($div->isContentEditable);
}
/**
* @covers \MensBeam\HTML\DOM\HTMLElement::__set_contentEditable
*
* @covers \MensBeam\HTML\DOM\Document::__construct
* @covers \MensBeam\HTML\DOM\Document::__get_documentElement
* @covers \MensBeam\HTML\DOM\Document::load
* @covers \MensBeam\HTML\DOM\DOMException::__construct
* @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_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 testProperty_contentEditable__errors(): void {
$this->expectException(DOMException::class);
$this->expectExceptionCode(DOMException::SYNTAX_ERROR);
@ -71,6 +200,36 @@ class TestHTMLElement extends \PHPUnit\Framework\TestCase {
$d->documentElement->contentEditable = 'fail';
}
/**
* @covers \MensBeam\HTML\DOM\HTMLElement::__get_dir
* @covers \MensBeam\HTML\DOM\HTMLElement::__set_dir
*
* @covers \MensBeam\HTML\DOM\Attr::__get_value
* @covers \MensBeam\HTML\DOM\Document::__construct
* @covers \MensBeam\HTML\DOM\Document::__get_documentElement
* @covers \MensBeam\HTML\DOM\Document::load
* @covers \MensBeam\HTML\DOM\DOMImplementation::__construct
* @covers \MensBeam\HTML\DOM\Element::__construct
* @covers \MensBeam\HTML\DOM\Element::__get_namespaceURI
* @covers \MensBeam\HTML\DOM\Element::getAttribute
* @covers \MensBeam\HTML\DOM\Element::getAttributeNode
* @covers \MensBeam\HTML\DOM\Element::setAttribute
* @covers \MensBeam\HTML\DOM\Node::__construct
* @covers \MensBeam\HTML\DOM\Node::__get_ownerDocument
* @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_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 testProperty_dir(): void {
$d = new Document('<!DOCTYPE html><html dir="ltr"></html>');
$html = $d->documentElement;
@ -79,6 +238,45 @@ class TestHTMLElement extends \PHPUnit\Framework\TestCase {
$this->assertSame('', $html->dir);
}
/**
* @covers \MensBeam\HTML\DOM\HTMLElement::__get_draggable
* @covers \MensBeam\HTML\DOM\HTMLElement::__set_draggable
*
* @covers \MensBeam\HTML\DOM\Attr::__get_value
* @covers \MensBeam\HTML\DOM\Collection::__construct
* @covers \MensBeam\HTML\DOM\Collection::item
* @covers \MensBeam\HTML\DOM\Document::__construct
* @covers \MensBeam\HTML\DOM\Document::load
* @covers \MensBeam\HTML\DOM\DocumentOrElement::getElementsByTagName
* @covers \MensBeam\HTML\DOM\DOMImplementation::__construct
* @covers \MensBeam\HTML\DOM\Element::__construct
* @covers \MensBeam\HTML\DOM\Element::__get_localName
* @covers \MensBeam\HTML\DOM\Element::__get_namespaceURI
* @covers \MensBeam\HTML\DOM\Element::__get_prefix
* @covers \MensBeam\HTML\DOM\Element::__get_tagName
* @covers \MensBeam\HTML\DOM\Element::getAttribute
* @covers \MensBeam\HTML\DOM\Element::getAttributeNode
* @covers \MensBeam\HTML\DOM\Element::hasAttribute
* @covers \MensBeam\HTML\DOM\Element::removeAttribute
* @covers \MensBeam\HTML\DOM\Element::setAttribute
* @covers \MensBeam\HTML\DOM\HTMLCollection::item
* @covers \MensBeam\HTML\DOM\HTMLCollection::offsetGet
* @covers \MensBeam\HTML\DOM\Node::__construct
* @covers \MensBeam\HTML\DOM\Node::__get_ownerDocument
* @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_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 testProperty_draggable(): void {
$d = new Document('<!DOCTYPE html><html><body><img src="ook.html"><object data="ook"></object><div></div></body></html>');
$img = $d->getElementsByTagName('img')[0];
@ -102,6 +300,36 @@ class TestHTMLElement extends \PHPUnit\Framework\TestCase {
$this->assertTrue($object->draggable);
}
/**
* @covers \MensBeam\HTML\DOM\HTMLElement::__get_enterKeyHint
* @covers \MensBeam\HTML\DOM\HTMLElement::__set_enterKeyHint
*
* @covers \MensBeam\HTML\DOM\Attr::__get_value
* @covers \MensBeam\HTML\DOM\Document::__construct
* @covers \MensBeam\HTML\DOM\Document::__get_documentElement
* @covers \MensBeam\HTML\DOM\Document::load
* @covers \MensBeam\HTML\DOM\DOMImplementation::__construct
* @covers \MensBeam\HTML\DOM\Element::__construct
* @covers \MensBeam\HTML\DOM\Element::__get_namespaceURI
* @covers \MensBeam\HTML\DOM\Element::getAttribute
* @covers \MensBeam\HTML\DOM\Element::getAttributeNode
* @covers \MensBeam\HTML\DOM\Element::setAttribute
* @covers \MensBeam\HTML\DOM\Node::__construct
* @covers \MensBeam\HTML\DOM\Node::__get_ownerDocument
* @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_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 testProperty_enterKeyHint(): void {
$d = new Document('<!DOCTYPE html><html></html>');
$html = $d->documentElement;
@ -112,6 +340,41 @@ class TestHTMLElement extends \PHPUnit\Framework\TestCase {
$this->assertSame('done', $html->enterKeyHint);
}
/**
* @covers \MensBeam\HTML\DOM\HTMLElement::__get_hidden
* @covers \MensBeam\HTML\DOM\HTMLElement::__set_hidden
*
* @covers \MensBeam\HTML\DOM\Collection::__construct
* @covers \MensBeam\HTML\DOM\Collection::item
* @covers \MensBeam\HTML\DOM\Document::__construct
* @covers \MensBeam\HTML\DOM\Document::__get_documentElement
* @covers \MensBeam\HTML\DOM\Document::load
* @covers \MensBeam\HTML\DOM\DocumentOrElement::getElementsByTagName
* @covers \MensBeam\HTML\DOM\DOMImplementation::__construct
* @covers \MensBeam\HTML\DOM\Element::__construct
* @covers \MensBeam\HTML\DOM\Element::__get_namespaceURI
* @covers \MensBeam\HTML\DOM\Element::getAttributeNode
* @covers \MensBeam\HTML\DOM\Element::hasAttribute
* @covers \MensBeam\HTML\DOM\Element::removeAttribute
* @covers \MensBeam\HTML\DOM\Element::setAttribute
* @covers \MensBeam\HTML\DOM\HTMLCollection::item
* @covers \MensBeam\HTML\DOM\HTMLCollection::offsetGet
* @covers \MensBeam\HTML\DOM\Node::__construct
* @covers \MensBeam\HTML\DOM\Node::__get_ownerDocument
* @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_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 testProperty_hidden(): void {
$d = new Document('<!DOCTYPE html><html><body><div></div></body></html>');
$div = $d->getElementsByTagName('div')[0];
@ -123,6 +386,36 @@ class TestHTMLElement extends \PHPUnit\Framework\TestCase {
$this->assertTrue($div->hidden);
}
/**
* @covers \MensBeam\HTML\DOM\HTMLElement::__get_lang
* @covers \MensBeam\HTML\DOM\HTMLElement::__set_lang
*
* @covers \MensBeam\HTML\DOM\Attr::__get_value
* @covers \MensBeam\HTML\DOM\Document::__construct
* @covers \MensBeam\HTML\DOM\Document::__get_documentElement
* @covers \MensBeam\HTML\DOM\Document::load
* @covers \MensBeam\HTML\DOM\DOMImplementation::__construct
* @covers \MensBeam\HTML\DOM\Element::__construct
* @covers \MensBeam\HTML\DOM\Element::__get_namespaceURI
* @covers \MensBeam\HTML\DOM\Element::getAttribute
* @covers \MensBeam\HTML\DOM\Element::getAttributeNode
* @covers \MensBeam\HTML\DOM\Element::setAttribute
* @covers \MensBeam\HTML\DOM\Node::__construct
* @covers \MensBeam\HTML\DOM\Node::__get_ownerDocument
* @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_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 testProperty_lang(): void {
$d = new Document('<!DOCTYPE html><html></html>');
$html = $d->documentElement;
@ -134,6 +427,7 @@ class TestHTMLElement extends \PHPUnit\Framework\TestCase {
$this->assertSame('ook', $html->lang);
}
/**
* @covers \MensBeam\HTML\DOM\HTMLElement::__get_innerText
* @covers \MensBeam\HTML\DOM\HTMLElement::__set_innerText
@ -202,6 +496,35 @@ class TestHTMLElement extends \PHPUnit\Framework\TestCase {
}
/**
* @covers \MensBeam\HTML\DOM\HTMLElement::__get_inputMode
* @covers \MensBeam\HTML\DOM\HTMLElement::__set_inputMode
*
* @covers \MensBeam\HTML\DOM\Attr::__get_value
* @covers \MensBeam\HTML\DOM\Document::__construct
* @covers \MensBeam\HTML\DOM\Document::__get_documentElement
* @covers \MensBeam\HTML\DOM\Document::load
* @covers \MensBeam\HTML\DOM\DOMImplementation::__construct
* @covers \MensBeam\HTML\DOM\Element::__construct
* @covers \MensBeam\HTML\DOM\Element::__get_namespaceURI
* @covers \MensBeam\HTML\DOM\Element::getAttribute
* @covers \MensBeam\HTML\DOM\Element::getAttributeNode
* @covers \MensBeam\HTML\DOM\Element::setAttribute
* @covers \MensBeam\HTML\DOM\Node::__construct
* @covers \MensBeam\HTML\DOM\Node::__get_ownerDocument
* @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_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 testProperty_inputMode(): void {
$d = new Document('<!DOCTYPE html><html></html>');
$html = $d->documentElement;
@ -238,4 +561,133 @@ class TestHTMLElement extends \PHPUnit\Framework\TestCase {
$h = $d->createElement('html');
$h->outerText = 'fail';
}
/**
* @covers \MensBeam\HTML\DOM\HTMLElement::__get_spellcheck
* @covers \MensBeam\HTML\DOM\HTMLElement::__set_spellcheck
*
* @covers \MensBeam\HTML\DOM\Attr::__get_value
* @covers \MensBeam\HTML\DOM\Document::__construct
* @covers \MensBeam\HTML\DOM\Document::__get_documentElement
* @covers \MensBeam\HTML\DOM\Document::load
* @covers \MensBeam\HTML\DOM\DOMImplementation::__construct
* @covers \MensBeam\HTML\DOM\Element::__construct
* @covers \MensBeam\HTML\DOM\Element::__get_namespaceURI
* @covers \MensBeam\HTML\DOM\Element::getAttribute
* @covers \MensBeam\HTML\DOM\Element::getAttributeNode
* @covers \MensBeam\HTML\DOM\Element::setAttribute
* @covers \MensBeam\HTML\DOM\Node::__construct
* @covers \MensBeam\HTML\DOM\Node::__get_ownerDocument
* @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_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 testProperty_spellcheck(): void {
$d = new Document('<!DOCTYPE html><html></html>');
$html = $d->documentElement;
$this->assertFalse($html->spellcheck);
$html->spellcheck = true;
$this->assertTrue($html->spellcheck);
$html->spellcheck = false;
$this->assertFalse($html->spellcheck);
}
/**
* @covers \MensBeam\HTML\DOM\HTMLElement::__get_title
* @covers \MensBeam\HTML\DOM\HTMLElement::__set_title
*
* @covers \MensBeam\HTML\DOM\Attr::__get_value
* @covers \MensBeam\HTML\DOM\Document::__construct
* @covers \MensBeam\HTML\DOM\Document::__get_documentElement
* @covers \MensBeam\HTML\DOM\Document::load
* @covers \MensBeam\HTML\DOM\DOMImplementation::__construct
* @covers \MensBeam\HTML\DOM\Element::__construct
* @covers \MensBeam\HTML\DOM\Element::__get_namespaceURI
* @covers \MensBeam\HTML\DOM\Element::getAttribute
* @covers \MensBeam\HTML\DOM\Element::getAttributeNode
* @covers \MensBeam\HTML\DOM\Element::setAttribute
* @covers \MensBeam\HTML\DOM\Node::__construct
* @covers \MensBeam\HTML\DOM\Node::__get_ownerDocument
* @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_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 testProperty_title(): void {
$d = new Document('<!DOCTYPE html><html></html>');
$html = $d->documentElement;
$this->assertSame('', $html->title);
$html->title = 'ook';
$this->assertSame('ook', $html->title);
}
/**
* @covers \MensBeam\HTML\DOM\HTMLElement::__get_translate
* @covers \MensBeam\HTML\DOM\HTMLElement::__set_translate
*
* @covers \MensBeam\HTML\DOM\Attr::__get_value
* @covers \MensBeam\HTML\DOM\Collection::__construct
* @covers \MensBeam\HTML\DOM\Collection::item
* @covers \MensBeam\HTML\DOM\Document::__construct
* @covers \MensBeam\HTML\DOM\Document::__get_documentElement
* @covers \MensBeam\HTML\DOM\Document::load
* @covers \MensBeam\HTML\DOM\DocumentOrElement::getElementsByTagName
* @covers \MensBeam\HTML\DOM\DOMImplementation::__construct
* @covers \MensBeam\HTML\DOM\Element::__construct
* @covers \MensBeam\HTML\DOM\Element::__get_namespaceURI
* @covers \MensBeam\HTML\DOM\Element::getAttribute
* @covers \MensBeam\HTML\DOM\Element::getAttributeNode
* @covers \MensBeam\HTML\DOM\Element::removeAttribute
* @covers \MensBeam\HTML\DOM\Element::setAttribute
* @covers \MensBeam\HTML\DOM\HTMLCollection::item
* @covers \MensBeam\HTML\DOM\HTMLCollection::offsetGet
* @covers \MensBeam\HTML\DOM\Node::__construct
* @covers \MensBeam\HTML\DOM\Node::__get_ownerDocument
* @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_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 testProperty_translate(): void {
$d = new Document('<!DOCTYPE html><html><div><span>Ook</span></div></html>');
$html = $d->documentElement;
$span = $d->getElementsByTagName('span')[0];
$this->assertFalse($span->translate);
$span->translate = true;
$this->assertTrue($span->translate);
$span->removeAttribute('translate');
$html->translate = true;
$this->assertTrue($span->translate);
$span->translate = false;
$this->assertFalse($span->translate);
}
}

29
tests/cases/TestHTMLOrSVGElement.php

@ -0,0 +1,29 @@
<?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\HTMLOrSVGElement */
class TestHTMLOrSVGElement extends \PHPUnit\Framework\TestCase {
public function testProperty_autofocus(): void {
$d = new Document('<!DOCTYPE html><html></html>');
$html = $d->documentElement;
$this->assertFalse($html->autofocus);
$html->autofocus = true;
$this->assertTrue($html->autofocus);
$html->autofocus = false;
$this->assertFalse($html->autofocus);
$this->assertFalse($html->hasAttribute('autofocus'));
}
}

1
tests/phpunit.dist.xml

@ -27,6 +27,7 @@
<file>cases/TestElement.php</file>
<file>cases/TestHTMLCollection.php</file>
<file>cases/TestHTMLElement.php</file>
<file>cases/TestHTMLOrSVGElement.php</file>
<file>cases/TestInnerDocument.php</file>
<file>cases/TestNamedNodeMap.php</file>
<file>cases/TestNode.php</file>

19
vendor-bin/phpunit/composer.lock

@ -92,6 +92,9 @@
"require": {
"php": "^7.1 || ^8.0"
},
"replace": {
"myclabs/deep-copy": "self.version"
},
"require-dev": {
"doctrine/collections": "^1.0",
"doctrine/common": "^2.6",
@ -844,16 +847,16 @@
},
{
"name": "phpunit/phpunit",
"version": "9.5.10",
"version": "9.5.11",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "c814a05837f2edb0d1471d6e3f4ab3501ca3899a"
"reference": "2406855036db1102126125537adb1406f7242fdd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c814a05837f2edb0d1471d6e3f4ab3501ca3899a",
"reference": "c814a05837f2edb0d1471d6e3f4ab3501ca3899a",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2406855036db1102126125537adb1406f7242fdd",
"reference": "2406855036db1102126125537adb1406f7242fdd",
"shasum": ""
},
"require": {
@ -931,11 +934,11 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.10"
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.11"
},
"funding": [
{
"url": "https://phpunit.de/donate.html",
"url": "https://phpunit.de/sponsors.html",
"type": "custom"
},
{
@ -943,7 +946,7 @@
"type": "github"
}
],
"time": "2021-09-25T07:38:51+00:00"
"time": "2021-12-25T07:07:57+00:00"
},
{
"name": "sebastian/cli-parser",
@ -2105,5 +2108,5 @@
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.2.0"
"plugin-api-version": "2.1.0"
}

189
vendor-bin/robo/composer.lock

@ -8,27 +8,28 @@
"packages": [
{
"name": "consolidation/annotated-command",
"version": "4.4.0",
"version": "4.5.0",
"source": {
"type": "git",
"url": "https://github.com/consolidation/annotated-command.git",
"reference": "308f6ac178566a1ce9aa90ed908dac90a2c1e707"
"reference": "df01c1f1449c6b46bf87051e0b418bd5d5e44a7a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/consolidation/annotated-command/zipball/308f6ac178566a1ce9aa90ed908dac90a2c1e707",
"reference": "308f6ac178566a1ce9aa90ed908dac90a2c1e707",
"url": "https://api.github.com/repos/consolidation/annotated-command/zipball/df01c1f1449c6b46bf87051e0b418bd5d5e44a7a",
"reference": "df01c1f1449c6b46bf87051e0b418bd5d5e44a7a",
"shasum": ""
},
"require": {
"consolidation/output-formatters": "^4.1.1",
"php": ">=7.1.3",
"psr/log": "^1|^2",
"symfony/console": "^4.4.8|~5.1.0",
"symfony/event-dispatcher": "^4.4.8|^5",
"symfony/finder": "^4.4.8|^5"
"symfony/console": "^4.4.8|^5|^6",
"symfony/event-dispatcher": "^4.4.8|^5|^6",
"symfony/finder": "^4.4.8|^5|^6"
},
"require-dev": {
"composer-runtime-api": "^2.0",
"phpunit/phpunit": "^7.5.20 || ^8 || ^9",
"squizlabs/php_codesniffer": "^3",
"yoast/phpunit-polyfills": "^0.2.0"
@ -57,9 +58,9 @@
"description": "Initialize Symfony Console commands from annotated command class methods.",
"support": {
"issues": "https://github.com/consolidation/annotated-command/issues",
"source": "https://github.com/consolidation/annotated-command/tree/4.4.0"
"source": "https://github.com/consolidation/annotated-command/tree/4.5.0"
},
"time": "2021-09-30T01:08:15+00:00"
"time": "2021-12-27T19:34:17+00:00"
},
{
"name": "consolidation/config",
@ -175,30 +176,30 @@
},
{
"name": "consolidation/output-formatters",
"version": "4.1.2",
"version": "4.2.0",
"source": {
"type": "git",
"url": "https://github.com/consolidation/output-formatters.git",
"reference": "5821e6ae076bf690058a4de6c94dce97398a69c9"
"reference": "27cf221f6e59b1debed0c6c94015e78cd5f10e24"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/consolidation/output-formatters/zipball/5821e6ae076bf690058a4de6c94dce97398a69c9",
"reference": "5821e6ae076bf690058a4de6c94dce97398a69c9",
"url": "https://api.github.com/repos/consolidation/output-formatters/zipball/27cf221f6e59b1debed0c6c94015e78cd5f10e24",
"reference": "27cf221f6e59b1debed0c6c94015e78cd5f10e24",
"shasum": ""
},
"require": {
"dflydev/dot-access-data": "^1.1.0",
"php": ">=7.1.3",
"symfony/console": "^4|^5",
"symfony/finder": "^4|^5"
"symfony/console": "^4|^5|^6",
"symfony/finder": "^4|^5|^6"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.4.2",
"phpunit/phpunit": ">=7",
"squizlabs/php_codesniffer": "^3",
"symfony/var-dumper": "^4",
"symfony/yaml": "^4",
"symfony/var-dumper": "^4|^5|^6",
"symfony/yaml": "^4|^5|^6",
"yoast/phpunit-polyfills": "^0.2.0"
},
"suggest": {
@ -228,9 +229,9 @@
"description": "Format text by applying transformations provided by plug-in formatters.",
"support": {
"issues": "https://github.com/consolidation/output-formatters/issues",
"source": "https://github.com/consolidation/output-formatters/tree/4.1.2"
"source": "https://github.com/consolidation/output-formatters/tree/4.2.0"
},
"time": "2020-12-12T19:04:59+00:00"
"time": "2021-12-27T14:30:41+00:00"
},
{
"name": "consolidation/robo",
@ -764,27 +765,29 @@
},
{
"name": "symfony/console",
"version": "v5.1.11",
"version": "v5.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "d9a267b621c5082e0a6c659d73633b6fd28a8a08"
"reference": "a2c6b7ced2eb7799a35375fb9022519282b5405e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/d9a267b621c5082e0a6c659d73633b6fd28a8a08",
"reference": "d9a267b621c5082e0a6c659d73633b6fd28a8a08",
"url": "https://api.github.com/repos/symfony/console/zipball/a2c6b7ced2eb7799a35375fb9022519282b5405e",
"reference": "a2c6b7ced2eb7799a35375fb9022519282b5405e",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1|^3",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php73": "^1.8",
"symfony/polyfill-php80": "^1.15",
"symfony/service-contracts": "^1.1|^2",
"symfony/string": "^5.1"
"symfony/polyfill-php73": "^1.9",
"symfony/polyfill-php80": "^1.16",
"symfony/service-contracts": "^1.1|^2|^3",
"symfony/string": "^5.1|^6.0"
},
"conflict": {
"psr/log": ">=3",
"symfony/dependency-injection": "<4.4",
"symfony/dotenv": "<5.1",
"symfony/event-dispatcher": "<4.4",
@ -792,16 +795,16 @@
"symfony/process": "<4.4"
},
"provide": {
"psr/log-implementation": "1.0"
"psr/log-implementation": "1.0|2.0"
},
"require-dev": {
"psr/log": "~1.0",
"symfony/config": "^4.4|^5.0",
"symfony/dependency-injection": "^4.4|^5.0",
"symfony/event-dispatcher": "^4.4|^5.0",
"symfony/lock": "^4.4|^5.0",
"symfony/process": "^4.4|^5.0",
"symfony/var-dumper": "^4.4|^5.0"
"psr/log": "^1|^2",
"symfony/config": "^4.4|^5.0|^6.0",
"symfony/dependency-injection": "^4.4|^5.0|^6.0",
"symfony/event-dispatcher": "^4.4|^5.0|^6.0",
"symfony/lock": "^4.4|^5.0|^6.0",
"symfony/process": "^4.4|^5.0|^6.0",
"symfony/var-dumper": "^4.4|^5.0|^6.0"
},
"suggest": {
"psr/log": "For using the console logger",
@ -834,8 +837,14 @@
],
"description": "Eases the creation of beautiful and testable command line interfaces",
"homepage": "https://symfony.com",
"keywords": [
"cli",
"command line",
"console",
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v5.1.11"
"source": "https://github.com/symfony/console/tree/v5.4.2"
},
"funding": [
{
@ -851,29 +860,29 @@
"type": "tidelift"
}
],
"time": "2021-01-27T10:01:46+00:00"
"time": "2021-12-20T16:11:12+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v2.5.0",
"version": "v3.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8"
"reference": "c726b64c1ccfe2896cb7df2e1331c357ad1c8ced"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8",
"reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/c726b64c1ccfe2896cb7df2e1331c357ad1c8ced",
"reference": "c726b64c1ccfe2896cb7df2e1331c357ad1c8ced",
"shasum": ""
},
"require": {
"php": ">=7.1"
"php": ">=8.0.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.5-dev"
"dev-main": "3.0-dev"
},
"thanks": {
"name": "symfony/contracts",
@ -902,7 +911,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.0"
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.0"
},
"funding": [
{
@ -918,7 +927,7 @@
"type": "tidelift"
}
],
"time": "2021-07-12T14:48:14+00:00"
"time": "2021-11-01T23:48:49+00:00"
},
{
"name": "symfony/event-dispatcher",
@ -1150,16 +1159,16 @@
},
{
"name": "symfony/finder",
"version": "v5.4.0",
"version": "v5.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "d2f29dac98e96a98be467627bd49c2efb1bc2590"
"reference": "e77046c252be48c48a40816187ed527703c8f76c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/d2f29dac98e96a98be467627bd49c2efb1bc2590",
"reference": "d2f29dac98e96a98be467627bd49c2efb1bc2590",
"url": "https://api.github.com/repos/symfony/finder/zipball/e77046c252be48c48a40816187ed527703c8f76c",
"reference": "e77046c252be48c48a40816187ed527703c8f76c",
"shasum": ""
},
"require": {
@ -1193,7 +1202,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/finder/tree/v5.4.0"
"source": "https://github.com/symfony/finder/tree/v5.4.2"
},
"funding": [
{
@ -1209,7 +1218,7 @@
"type": "tidelift"
}
],
"time": "2021-11-28T15:25:38+00:00"
"time": "2021-12-15T11:06:13+00:00"
},
{
"name": "symfony/polyfill-ctype",
@ -1699,16 +1708,16 @@
},
{
"name": "symfony/process",
"version": "v5.4.0",
"version": "v5.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "5be20b3830f726e019162b26223110c8f47cf274"
"reference": "2b3ba8722c4aaf3e88011be5e7f48710088fb5e4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/5be20b3830f726e019162b26223110c8f47cf274",
"reference": "5be20b3830f726e019162b26223110c8f47cf274",
"url": "https://api.github.com/repos/symfony/process/zipball/2b3ba8722c4aaf3e88011be5e7f48710088fb5e4",
"reference": "2b3ba8722c4aaf3e88011be5e7f48710088fb5e4",
"shasum": ""
},
"require": {
@ -1741,7 +1750,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v5.4.0"
"source": "https://github.com/symfony/process/tree/v5.4.2"
},
"funding": [
{
@ -1757,26 +1766,25 @@
"type": "tidelift"
}
],
"time": "2021-11-28T15:25:38+00:00"
"time": "2021-12-27T21:01:00+00:00"
},
{
"name": "symfony/service-contracts",
"version": "v2.5.0",
"version": "v2.4.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc"
"reference": "d664541b99d6fb0247ec5ff32e87238582236204"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc",
"reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/d664541b99d6fb0247ec5ff32e87238582236204",
"reference": "d664541b99d6fb0247ec5ff32e87238582236204",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/container": "^1.1",
"symfony/deprecation-contracts": "^2.1"
"psr/container": "^1.1"
},
"conflict": {
"ext-psr": "<1.1|>=2"
@ -1787,7 +1795,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.5-dev"
"dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
@ -1824,7 +1832,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/service-contracts/tree/v2.5.0"
"source": "https://github.com/symfony/service-contracts/tree/v2.4.1"
},
"funding": [
{
@ -1840,38 +1848,37 @@
"type": "tidelift"
}
],
"time": "2021-11-04T16:48:04+00:00"
"time": "2021-11-04T16:37:19+00:00"
},
{
"name": "symfony/string",
"version": "v5.4.0",
"version": "v6.0.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "9ffaaba53c61ba75a3c7a3a779051d1e9ec4fd2d"
"reference": "bae261d0c3ac38a1f802b4dfed42094296100631"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/9ffaaba53c61ba75a3c7a3a779051d1e9ec4fd2d",
"reference": "9ffaaba53c61ba75a3c7a3a779051d1e9ec4fd2d",
"url": "https://api.github.com/repos/symfony/string/zipball/bae261d0c3ac38a1f802b4dfed42094296100631",
"reference": "bae261d0c3ac38a1f802b4dfed42094296100631",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"php": ">=8.0.2",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php80": "~1.15"
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
"symfony/translation-contracts": ">=3.0"
"symfony/translation-contracts": "<2.0"
},
"require-dev": {
"symfony/error-handler": "^4.4|^5.0|^6.0",
"symfony/http-client": "^4.4|^5.0|^6.0",
"symfony/translation-contracts": "^1.1|^2",
"symfony/var-exporter": "^4.4|^5.0|^6.0"
"symfony/error-handler": "^5.4|^6.0",
"symfony/http-client": "^5.4|^6.0",
"symfony/translation-contracts": "^2.0|^3.0",
"symfony/var-exporter": "^5.4|^6.0"
},
"type": "library",
"autoload": {
@ -1910,7 +1917,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v5.4.0"
"source": "https://github.com/symfony/string/tree/v6.0.2"
},
"funding": [
{
@ -1926,32 +1933,32 @@
"type": "tidelift"
}
],
"time": "2021-11-24T10:02:00+00:00"
"time": "2021-12-16T22:13:01+00:00"
},
{
"name": "symfony/yaml",
"version": "v5.3.11",
"version": "v5.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "226638aa877bc4104e619a15f27d8141cd6b4e4a"
"reference": "b9eb163846a61bb32dfc147f7859e274fab38b58"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/226638aa877bc4104e619a15f27d8141cd6b4e4a",
"reference": "226638aa877bc4104e619a15f27d8141cd6b4e4a",
"url": "https://api.github.com/repos/symfony/yaml/zipball/b9eb163846a61bb32dfc147f7859e274fab38b58",
"reference": "b9eb163846a61bb32dfc147f7859e274fab38b58",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1",
"symfony/polyfill-ctype": "~1.8"
"symfony/deprecation-contracts": "^2.1|^3",
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
"symfony/console": "<4.4"
"symfony/console": "<5.3"
},
"require-dev": {
"symfony/console": "^4.4|^5.0"
"symfony/console": "^5.3|^6.0"
},
"suggest": {
"symfony/console": "For validating YAML files using the lint command"
@ -1985,7 +1992,7 @@
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/yaml/tree/v5.3.11"
"source": "https://github.com/symfony/yaml/tree/v5.4.2"
},
"funding": [
{
@ -2001,7 +2008,7 @@
"type": "tidelift"
}
],
"time": "2021-11-20T16:42:42+00:00"
"time": "2021-12-16T21:58:21+00:00"
}
],
"packages-dev": [],
@ -2012,5 +2019,5 @@
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.2.0"
"plugin-api-version": "2.1.0"
}

Loading…
Cancel
Save