diff options
Diffstat (limited to 'testing/web-platform/tests/custom-elements/reactions')
10 files changed, 764 insertions, 0 deletions
diff --git a/testing/web-platform/tests/custom-elements/reactions/Attr.html b/testing/web-platform/tests/custom-elements/reactions/Attr.html new file mode 100644 index 000000000..c9fa37f96 --- /dev/null +++ b/testing/web-platform/tests/custom-elements/reactions/Attr.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<html> +<head> +<title>Custom Elements: CEReactions on Attr interface</title> +<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> +<meta name="assert" content="value of Attr interface must have CEReactions"> +<meta name="help" content="https://dom.spec.whatwg.org/#node"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/custom-elements-helpers.js"></script> +<script src="./resources/reactions.js"></script> +</head> +<body> +<div id="log"></div> +<script> + +testAttributeMutator(function (element, name, value) { + element.attributes[name].value = value; +}, 'value on Attr'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/custom-elements/reactions/ChildNode.html b/testing/web-platform/tests/custom-elements/reactions/ChildNode.html new file mode 100644 index 000000000..756f17229 --- /dev/null +++ b/testing/web-platform/tests/custom-elements/reactions/ChildNode.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html> +<head> +<title>Custom Elements: CEReactions on ChildNode interface</title> +<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> +<meta name="assert" content="before, after, after, replaceWith, and remove of ChildNode interface must have CEReactions"> +<meta name="help" content="https://dom.spec.whatwg.org/#parentnode"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/custom-elements-helpers.js"></script> +<script src="./resources/reactions.js"></script> +</head> +<body> +<div id="log"></div> +<script> + +testNodeConnector(function (newContainer, customElement) { + newContainer.firstChild.before(customElement); +}, 'before on ChildNode'); + +testNodeConnector(function (newContainer, customElement) { + newContainer.firstChild.after(customElement); +}, 'after on ChildNode'); + +testNodeConnector(function (newContainer, customElement) { + newContainer.firstChild.replaceWith(customElement); +}, 'replaceWith on ChildNode'); + +testNodeDisconnector(function (customElement) { + customElement.remove(); +}, 'replaceWith on ChildNode'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/custom-elements/reactions/DOMTokenList.html b/testing/web-platform/tests/custom-elements/reactions/DOMTokenList.html new file mode 100644 index 000000000..38006d3e7 --- /dev/null +++ b/testing/web-platform/tests/custom-elements/reactions/DOMTokenList.html @@ -0,0 +1,217 @@ +<!DOCTYPE html> +<html> +<head> +<title>Custom Elements: CEReactions on DOMTokenList interface</title> +<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> +<meta name="assert" content="add, remove, toggle, replace, and the stringifier of DOMTokenList interface must have CEReactions"> +<meta name="help" content="https://dom.spec.whatwg.org/#node"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/custom-elements-helpers.js"></script> +<script src="./resources/reactions.js"></script> +</head> +<body> +<script> + +test(function () { + var element = define_new_custom_element(['class']); + var instance = document.createElement(element.name); + assert_array_equals(element.takeLog().types(), ['constructed']); + instance.classList.add('foo'); + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['attributeChanged']); + assert_attribute_log_entry(logEntries.last(), {name: 'class', oldValue: null, newValue: 'foo', namespace: null}); +}, 'add on DOMTokenList must enqueue an attributeChanged reaction when adding an attribute'); + +test(function () { + var element = define_new_custom_element(['style']); + var instance = document.createElement(element.name); + assert_array_equals(element.takeLog().types(), ['constructed']); + instance.classList.add('foo'); + assert_array_equals(element.takeLog().types(), []); +}, 'add on DOMTokenList must not enqueue an attributeChanged reaction when adding an unobserved attribute'); + +test(function () { + var element = define_new_custom_element(['class']); + var instance = document.createElement(element.name); + instance.setAttribute('class', 'hello'); + assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']); + instance.classList.add('world'); + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['attributeChanged']); + assert_attribute_log_entry(logEntries.last(), {name: 'class', oldValue: 'hello', newValue: 'hello world', namespace: null}); +}, 'add on DOMTokenList must enqueue an attributeChanged reaction when adding a value to an existing attribute'); + +test(function () { + var element = define_new_custom_element(['contenteditable']); + var instance = document.createElement(element.name); + instance.setAttribute('class', 'hello'); + assert_array_equals(element.takeLog().types(), ['constructed']); + instance.classList.add('world'); + assert_array_equals(element.takeLog().types(), []); +}, 'add on DOMTokenList must not enqueue an attributeChanged reaction when adding a value to an unobserved attribute'); + +test(function () { + var element = define_new_custom_element(['class']); + var instance = document.createElement(element.name); + assert_array_equals(element.takeLog().types(), ['constructed']); + instance.classList.add('hello', 'world'); + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['attributeChanged']); + assert_attribute_log_entry(logEntries.last(), {name: 'class', oldValue: null, newValue: 'hello world', namespace: null}); +}, 'add on DOMTokenList must enqueue exactly one attributeChanged reaction when adding multiple values to an attribute'); + +test(function () { + var element = define_new_custom_element(['class']); + var instance = document.createElement(element.name); + instance.setAttribute('class', 'hello world'); + assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']); + instance.classList.remove('world'); + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['attributeChanged']); + assert_attribute_log_entry(logEntries.last(), {name: 'class', oldValue: 'hello world', newValue: 'hello', namespace: null}); +}, 'remove on DOMTokenList must enqueue an attributeChanged reaction when removing a value from an attribute'); + +test(function () { + var element = define_new_custom_element(['class']); + var instance = document.createElement(element.name); + instance.setAttribute('class', 'hello foo world bar'); + assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']); + instance.classList.remove('hello', 'world'); + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['attributeChanged']); + assert_attribute_log_entry(logEntries.last(), {name: 'class', oldValue: 'hello foo world bar', newValue: 'foo bar', namespace: null}); +}, 'remove on DOMTokenList must enqueue exactly one attributeChanged reaction when removing multiple values to an attribute'); + +test(function () { + var element = define_new_custom_element(['class']); + var instance = document.createElement(element.name); + instance.setAttribute('class', 'hello world'); + assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']); + instance.classList.remove('foo'); + assert_array_equals(element.takeLog().types(), []); +}, 'remove on DOMTokenList must not enqueue an attributeChanged reaction when removing a non-existent value from an attribute'); + +test(function () { + var element = define_new_custom_element(['title']); + var instance = document.createElement(element.name); + instance.setAttribute('class', 'hello world'); + assert_array_equals(element.takeLog().types(), ['constructed']); + instance.classList.remove('world'); + assert_array_equals(element.takeLog().types(), []); +}, 'remove on DOMTokenList must not enqueue an attributeChanged reaction when removing a value from an unobserved attribute'); + +test(function () { + var element = define_new_custom_element(['class']); + var instance = document.createElement(element.name); + instance.setAttribute('class', 'hello'); + assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']); + instance.classList.toggle('world'); + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['attributeChanged']); + assert_attribute_log_entry(logEntries.last(), {name: 'class', oldValue: 'hello', newValue: 'hello world', namespace: null}); +}, 'toggle on DOMTokenList must enqueue an attributeChanged reaction when adding a value to an attribute'); + +test(function () { + var element = define_new_custom_element(['class']); + var instance = document.createElement(element.name); + instance.setAttribute('class', 'hello world'); + assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']); + instance.classList.toggle('world'); + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['attributeChanged']); + assert_attribute_log_entry(logEntries.last(), {name: 'class', oldValue: 'hello world', newValue: 'hello', namespace: null}); +}, 'toggle on DOMTokenList must enqueue an attributeChanged reaction when removing a value from an attribute'); + +test(function () { + var element = define_new_custom_element(['lang']); + var instance = document.createElement(element.name); + instance.setAttribute('class', 'hello world'); + assert_array_equals(element.takeLog().types(), ['constructed']); + instance.classList.toggle('world'); + assert_array_equals(element.takeLog().types(), []); +}, 'remove on DOMTokenList must not enqueue an attributeChanged reaction when removing a value from an unobserved attribute'); + +test(function () { + var element = define_new_custom_element(['class']); + var instance = document.createElement(element.name); + instance.setAttribute('class', 'hello'); + assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']); + instance.classList.replace('hello', 'world'); + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['attributeChanged']); + assert_attribute_log_entry(logEntries.last(), {name: 'class', oldValue: 'hello', newValue: 'world', namespace: null}); +}, 'replace on DOMTokenList must enqueue an attributeChanged reaction when replacing a value in an attribute'); + +test(function () { + var element = define_new_custom_element(['class']); + var instance = document.createElement(element.name); + instance.setAttribute('class', 'hello world'); + assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']); + instance.classList.replace('foo', 'bar'); + assert_array_equals(element.takeLog().types(), []); +}, 'replace on DOMTokenList must not enqueue an attributeChanged reaction when the token to replace does not exist in the attribute'); + +test(function () { + var element = define_new_custom_element(['title']); + var instance = document.createElement(element.name); + instance.setAttribute('class', 'hello'); + assert_array_equals(element.takeLog().types(), ['constructed']); + instance.classList.replace('hello', 'world'); + assert_array_equals(element.takeLog().types(), []); +}, 'replace on DOMTokenList must not enqueue an attributeChanged reaction when replacing a value in an unobserved attribute'); + +test(function () { + var element = define_new_custom_element(['class']); + var instance = document.createElement(element.name); + assert_array_equals(element.takeLog().types(), ['constructed']); + instance.classList = 'hello'; + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['attributeChanged']); + assert_attribute_log_entry(logEntries.last(), {name: 'class', oldValue: null, newValue: 'hello', namespace: null}); +}, 'the stringifier of DOMTokenList must enqueue an attributeChanged reaction when adding an observed attribute'); + +test(function () { + var element = define_new_custom_element(['id']); + var instance = document.createElement(element.name); + instance.setAttribute('class', 'hello'); + assert_array_equals(element.takeLog().types(), ['constructed']); + instance.classList = 'hello'; + var logEntries = element.takeLog(); + assert_array_equals(element.takeLog().types(), []); +}, 'the stringifier of DOMTokenList must not enqueue an attributeChanged reaction when adding an unobserved attribute'); + +test(function () { + var element = define_new_custom_element(['class']); + var instance = document.createElement(element.name); + instance.setAttribute('class', 'hello'); + assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']); + instance.classList = 'world'; + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['attributeChanged']); + assert_attribute_log_entry(logEntries.last(), {name: 'class', oldValue: 'hello', newValue: 'world', namespace: null}); +}, 'the stringifier of DOMTokenList must enqueue an attributeChanged reaction when mutating the value of an observed attribute'); + +test(function () { + var element = define_new_custom_element([]); + var instance = document.createElement(element.name); + instance.setAttribute('class', 'hello'); + assert_array_equals(element.takeLog().types(), ['constructed']); + instance.classList = 'world'; + assert_array_equals(element.takeLog().types(), []); +}, 'the stringifier of DOMTokenList must not enqueue an attributeChanged reaction when mutating the value of an unobserved attribute'); + +test(function () { + var element = define_new_custom_element(['class']); + var instance = document.createElement(element.name); + instance.setAttribute('class', 'hello'); + assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']); + instance.classList = 'hello'; + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['attributeChanged']); + assert_attribute_log_entry(logEntries.last(), {name: 'class', oldValue: 'hello', newValue: 'hello', namespace: null}); +}, 'the stringifier of DOMTokenList must enqueue an attributeChanged reaction when the setter is called with the original value of the attribute'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/custom-elements/reactions/Document.html b/testing/web-platform/tests/custom-elements/reactions/Document.html new file mode 100644 index 000000000..304ec9861 --- /dev/null +++ b/testing/web-platform/tests/custom-elements/reactions/Document.html @@ -0,0 +1,47 @@ +<!DOCTYPE html> +<html> +<head> +<title>Custom Elements: CEReactions on ParentNode interface</title> +<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> +<meta name="assert" content="importNode and adoptNode of Document interface must have CEReactions"> +<meta name="help" content="https://dom.spec.whatwg.org/#document"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/custom-elements-helpers.js"></script> +<script src="./resources/reactions.js"></script> +</head> +<body> +<div id="log"></div> +<script> + +test(function () { + var element = define_new_custom_element(); + var instance = document.createElement(element.name); + assert_array_equals(element.takeLog().types(), ['constructed']); + + var newDoc = document.implementation.createHTMLDocument(); + newDoc.importNode(instance); + + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['constructed']); + assert_equals(logEntries.last().oldDocument, document); + assert_equals(logEntries.last().newDocument, newDoc); +}, 'importNode on Document must construct a new custom element when importing a custom element'); + +test(function () { + var element = define_new_custom_element(); + var instance = document.createElement(element.name); + assert_array_equals(element.takeLog().types(), ['constructed']); + + var newDoc = document.implementation.createHTMLDocument(); + newDoc.adoptNode(instance); + + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['adopted']); + assert_equals(logEntries.last().oldDocument, document); + assert_equals(logEntries.last().newDocument, newDoc); +}, 'adoptNode on Document must enqueue an adopted reaction when importing a custom element'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/custom-elements/reactions/Element.html b/testing/web-platform/tests/custom-elements/reactions/Element.html new file mode 100644 index 000000000..ed627f44e --- /dev/null +++ b/testing/web-platform/tests/custom-elements/reactions/Element.html @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<html> +<head> +<title>Custom Elements: CEReactions on Node interface</title> +<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> +<meta name="assert" content="id, className, slot, setAttribute, setAttributeNS, removeAttribute, removeAttributeNS, setAttributeNode, setAttributeNodeNS, removeAttributeNode, and insertAdjacentElement of Element interface must have CEReactions"> +<meta name="help" content="https://dom.spec.whatwg.org/#element"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/custom-elements-helpers.js"></script> +<script src="./resources/reactions.js"></script> +</head> +<body> +<div id="log"></div> +<script> + +testReflectAttribute('id', 'id', 'foo', 'bar', 'id on Element'); +testReflectAttribute('className', 'class', 'foo', 'bar', 'className on Element'); +testReflectAttribute('slot', 'slot', 'foo', 'bar', 'slot on Element'); + +testAttributeAdder(function (element, name, value) { + element.setAttribute(name, value); +}, 'setAttribute on Element'); + +testAttributeAdder(function (element, name, value) { + element.setAttributeNS(null, name, value); +}, 'setAttributeNS on Element'); + +testAttributeRemover(function (element, name) { + element.removeAttribute(name); +}, 'removeAttribute on Element'); + +testAttributeRemover(function (element, name) { + element.removeAttributeNS(null, name); +}, 'removeAttributeNS on Element'); + +testAttributeAdder(function (element, name, value) { + var attr = document.createAttribute(name); + attr.value = value; + element.setAttributeNode(attr); +}, 'setAttributeNode on Element'); + +testAttributeAdder(function (element, name, value) { + var attr = document.createAttribute(name); + attr.value = value; + element.setAttributeNodeNS(attr); +}, 'setAttributeNodeNS on Element'); + +testAttributeRemover(function (element, name) { + var attr = element.getAttributeNode(name); + if (attr) + element.removeAttributeNode(element.getAttributeNode(name)); +}, 'removeAttributeNode on Element'); + +testNodeConnector(function (newContainer, element) { + newContainer.insertAdjacentElement('afterBegin', element); +}); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/custom-elements/reactions/NamedNodeMap.html b/testing/web-platform/tests/custom-elements/reactions/NamedNodeMap.html new file mode 100644 index 000000000..0ae83e9ab --- /dev/null +++ b/testing/web-platform/tests/custom-elements/reactions/NamedNodeMap.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> +<head> +<title>Custom Elements: CEReactions on NamedNodeMap interface</title> +<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> +<meta name="assert" content="setNamedItem, setNamedItemNS, removeNameditem, and removeNamedItemNS of NamedNodeMap interface must have CEReactions"> +<meta name="help" content="https://dom.spec.whatwg.org/#node"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/custom-elements-helpers.js"></script> +<script src="./resources/reactions.js"></script> +</head> +<body> +<div id="log"></div> +<script> + +testAttributeAdder(function (element, name, value) { + var attr = element.ownerDocument.createAttribute(name); + attr.value = value; + element.attributes.setNamedItem(attr); +}, 'setNamedItem on NamedNodeMap'); + +testAttributeAdder(function (element, name, value) { + var attr = element.ownerDocument.createAttribute(name); + attr.value = value; + element.attributes.setNamedItemNS(attr); +}, 'setNamedItemNS on NamedNodeMap'); + +testAttributeRemover(function (element, name) { + element.attributes.removeNamedItem(name); +}, 'removeNamedItem on NamedNodeMap'); + +testAttributeRemover(function (element, name) { + element.attributes.removeNamedItemNS(null, name); +}, 'removeNamedItemNS on NamedNodeMap'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/custom-elements/reactions/Node.html b/testing/web-platform/tests/custom-elements/reactions/Node.html new file mode 100644 index 000000000..94da3d020 --- /dev/null +++ b/testing/web-platform/tests/custom-elements/reactions/Node.html @@ -0,0 +1,49 @@ +<!DOCTYPE html> +<html> +<head> +<title>Custom Elements: CEReactions on Node interface</title> +<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> +<meta name="assert" content="nodeValue, textContent, normalize, cloneNode, insertBefore, appendChild, replaceChild, and removeChild of Node interface must have CEReactions"> +<meta name="help" content="https://dom.spec.whatwg.org/#node"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/custom-elements-helpers.js"></script> +<script src="./resources/reactions.js"></script> +</head> +<body> +<div id="log"></div> +<script> + +testAttributeMutator(function (element, name, value) { + element.getAttributeNode(name).nodeValue = value; +}, 'nodeValue on Node'); + +testAttributeMutator(function (element, name, value) { + element.getAttributeNode(name).textContent = value; +}, 'textContent on Node'); + +// FIXME: Add a test for normalize() + +testCloner(function (customElement) { + return customElement.cloneNode(false); +}, 'cloneNode on Node'); + +testNodeConnector(function (newContainer, customElement) { + newContainer.insertBefore(customElement, newContainer.firstChild); +}, 'insertBefore on ChildNode'); + +testNodeConnector(function (newContainer, customElement) { + newContainer.appendChild(customElement); +}, 'appendChild on ChildNode'); + +testNodeConnector(function (newContainer, customElement) { + newContainer.replaceChild(customElement, newContainer.firstChild); +}, 'replaceChild on ChildNode'); + +testNodeDisconnector(function (customElement) { + customElement.parentNode.removeChild(customElement); +}, 'removeChild on ChildNode'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/custom-elements/reactions/ParentNode.html b/testing/web-platform/tests/custom-elements/reactions/ParentNode.html new file mode 100644 index 000000000..b143b5a98 --- /dev/null +++ b/testing/web-platform/tests/custom-elements/reactions/ParentNode.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html> +<head> +<title>Custom Elements: CEReactions on ParentNode interface</title> +<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> +<meta name="assert" content="prepend and append of ParentNode interface must have CEReactions"> +<meta name="help" content="https://dom.spec.whatwg.org/#parentnode"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/custom-elements-helpers.js"></script> +<script src="./resources/reactions.js"></script> +</head> +<body> +<div id="log"></div> +<script> + +testNodeConnector(function (newContainer, customElement) { + newContainer.prepend(customElement); +}, 'prepend on ParentNode'); + +testNodeConnector(function (newContainer, customElement) { + newContainer.append(customElement); +}, 'append on ParentNode'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/custom-elements/reactions/Range.html b/testing/web-platform/tests/custom-elements/reactions/Range.html new file mode 100644 index 000000000..82382d520 --- /dev/null +++ b/testing/web-platform/tests/custom-elements/reactions/Range.html @@ -0,0 +1,49 @@ +<!DOCTYPE html> +<html> +<head> +<title>Custom Elements: CEReactions on Range interface</title> +<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> +<meta name="assert" content="deleteContents, extractContents, cloneContents, insertNode, and surroundContents of Range interface must have CEReactions"> +<meta name="help" content="https://dom.spec.whatwg.org/#node"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/custom-elements-helpers.js"></script> +<script src="./resources/reactions.js"></script> +</head> +<body> +<div id="log"></div> +<script> + +testNodeDisconnector(function (customElement) { + var range = document.createRange(); + range.selectNode(customElement); + range.deleteContents(); +}, 'deleteContents on Range'); + +testNodeDisconnector(function (customElement) { + var range = document.createRange(); + range.selectNode(customElement); + range.extractContents(); +}, 'extractContents on Range'); + +testCloner(function (customElement) { + var range = document.createRange(); + range.selectNode(customElement); + range.cloneContents(); +}, 'cloneContents on Range') + +testNodeConnector(function (container, customElement) { + var range = document.createRange(); + range.selectNodeContents(container); + range.insertNode(customElement); +}, 'insertNode on Range'); + +testNodeConnector(function (container, customElement) { + var range = document.createRange(); + range.selectNodeContents(container); + range.surroundContents(customElement); +}, 'insertNode on Range'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/custom-elements/reactions/resources/reactions.js b/testing/web-platform/tests/custom-elements/reactions/resources/reactions.js new file mode 100644 index 000000000..c260dc4f3 --- /dev/null +++ b/testing/web-platform/tests/custom-elements/reactions/resources/reactions.js @@ -0,0 +1,217 @@ + +let testNumber = 1; + +function testNodeConnector(testFunction, name) { + let container = document.createElement('div'); + container.appendChild(document.createElement('div')); + document.body.appendChild(container); + + test(function () { + var element = define_new_custom_element(); + var instance = document.createElement(element.name); + assert_array_equals(element.takeLog().types(), ['constructed']); + testFunction(container, instance); + assert_array_equals(element.takeLog().types(), ['connected']); + }, name + ' must enqueue a connected reaction'); + + test(function () { + var element = define_new_custom_element(); + var instance = document.createElement(element.name); + assert_array_equals(element.takeLog().types(), ['constructed']); + var newDoc = document.implementation.createHTMLDocument(); + testFunction(container, instance); + assert_array_equals(element.takeLog().types(), ['connected']); + testFunction(newDoc.documentElement, instance); + assert_array_equals(element.takeLog().types(), ['disconnected', 'adopted', 'connected']); + }, name + ' must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document'); + + container.parentNode.removeChild(container); +} + +function testNodeDisconnector(testFunction, name) { + let container = document.createElement('div'); + container.appendChild(document.createElement('div')); + document.body.appendChild(container); + + test(function () { + var element = define_new_custom_element(); + var instance = document.createElement(element.name); + assert_array_equals(element.takeLog().types(), ['constructed']); + container.appendChild(instance); + assert_array_equals(element.takeLog().types(), ['connected']); + testFunction(instance); + assert_array_equals(element.takeLog().types(), ['disconnected']); + }, name + ' must enqueue a disconnected reaction'); + + container.parentNode.removeChild(container); +} + +function testCloner(testFunction, name) { + let container = document.createElement('div'); + container.appendChild(document.createElement('div')); + document.body.appendChild(container); + + test(function () { + var element = define_new_custom_element(['id']); + var instance = document.createElement(element.name); + container.appendChild(instance); + + instance.setAttribute('id', 'foo'); + assert_array_equals(element.takeLog().types(), ['constructed', 'connected', 'attributeChanged']); + var newInstance = testFunction(instance); + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['constructed', 'attributeChanged']); + assert_attribute_log_entry(logEntries.last(), {name: 'id', oldValue: null, newValue: 'foo', namespace: null}); + }, name + ' must enqueue an attributeChanged reaction when cloning an element with an observed attribute'); + + test(function () { + var element = define_new_custom_element(['id']); + var instance = document.createElement(element.name); + container.appendChild(instance); + + instance.setAttribute('lang', 'en'); + assert_array_equals(element.takeLog().types(), ['constructed', 'connected']); + var newInstance = testFunction(instance); + assert_array_equals(element.takeLog().types(), ['constructed']); + }, name + ' must not enqueue an attributeChanged reaction when cloning an element with an unobserved attribute'); + + test(function () { + var element = define_new_custom_element(['title', 'class']); + var instance = document.createElement(element.name); + container.appendChild(instance); + + instance.setAttribute('lang', 'en'); + instance.className = 'foo'; + instance.setAttribute('title', 'hello world'); + assert_array_equals(element.takeLog().types(), ['constructed', 'connected', 'attributeChanged', 'attributeChanged']); + var newInstance = testFunction(instance); + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['constructed', 'attributeChanged', 'attributeChanged']); + assert_attribute_log_entry(logEntries[1], {name: 'class', oldValue: null, newValue: 'foo', namespace: null}); + assert_attribute_log_entry(logEntries[2], {name: 'title', oldValue: null, newValue: 'hello world', namespace: null}); + }, name + ' must enqueue an attributeChanged reaction when cloning an element only for observed attributes'); +} + +function testReflectAttribute(jsAttributeName, contentAttributeName, validValue1, validValue2, name) { + test(function () { + var element = define_new_custom_element([contentAttributeName]); + var instance = document.createElement(element.name); + assert_array_equals(element.takeLog().types(), ['constructed']); + instance[jsAttributeName] = validValue1; + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['attributeChanged']); + assert_attribute_log_entry(logEntries.last(), {name: contentAttributeName, oldValue: null, newValue: validValue1, namespace: null}); + }, name + ' must enqueue an attributeChanged reaction when adding ' + contentAttributeName + ' content attribute'); + + test(function () { + var element = define_new_custom_element([contentAttributeName]); + var instance = document.createElement(element.name); + instance[jsAttributeName] = validValue1; + assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']); + instance[jsAttributeName] = validValue2; + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['attributeChanged']); + assert_attribute_log_entry(logEntries.last(), {name: contentAttributeName, oldValue: validValue1, newValue: validValue2, namespace: null}); + }, name + ' must enqueue an attributeChanged reaction when replacing an existing attribute'); +} + +function testAttributeAdder(testFunction, name) { + test(function () { + var element = define_new_custom_element(['id']); + var instance = document.createElement(element.name); + assert_array_equals(element.takeLog().types(), ['constructed']); + testFunction(instance, 'id', 'foo'); + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['attributeChanged']); + assert_attribute_log_entry(logEntries.last(), {name: 'id', oldValue: null, newValue: 'foo', namespace: null}); + }, name + ' must enqueue an attributeChanged reaction when adding an attribute'); + + test(function () { + var element = define_new_custom_element(['class']); + var instance = document.createElement(element.name); + assert_array_equals(element.takeLog().types(), ['constructed']); + testFunction(instance, 'data-lang', 'en'); + assert_array_equals(element.takeLog().types(), []); + }, name + ' must not enqueue an attributeChanged reaction when adding an unobserved attribute'); + + test(function () { + var element = define_new_custom_element(['title']); + var instance = document.createElement(element.name); + instance.setAttribute('title', 'hello'); + assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']); + testFunction(instance, 'title', 'world'); + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['attributeChanged']); + assert_attribute_log_entry(logEntries.last(), {name: 'title', oldValue: 'hello', newValue: 'world', namespace: null}); + }, name + ' must enqueue an attributeChanged reaction when replacing an existing attribute'); + + test(function () { + var element = define_new_custom_element([]); + var instance = document.createElement(element.name); + instance.setAttribute('data-lang', 'zh'); + assert_array_equals(element.takeLog().types(), ['constructed']); + testFunction(instance, 'data-lang', 'en'); + assert_array_equals(element.takeLog().types(), []); + }, name + ' must enqueue an attributeChanged reaction when replacing an existing unobserved attribute'); +} + +function testAttributeMutator(testFunction, name) { + test(function () { + var element = define_new_custom_element(['title']); + var instance = document.createElement(element.name); + instance.setAttribute('title', 'hello'); + assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']); + testFunction(instance, 'title', 'world'); + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['attributeChanged']); + assert_attribute_log_entry(logEntries.last(), {name: 'title', oldValue: 'hello', newValue: 'world', namespace: null}); + }, name + ' must enqueue an attributeChanged reaction when replacing an existing attribute'); + + test(function () { + var element = define_new_custom_element(['class']); + var instance = document.createElement(element.name); + instance.setAttribute('data-lang', 'zh'); + assert_array_equals(element.takeLog().types(), ['constructed']); + testFunction(instance, 'data-lang', 'en'); + assert_array_equals(element.takeLog().types(), []); + }, name + ' must not enqueue an attributeChanged reaction when replacing an existing unobserved attribute'); +} + +function testAttributeRemover(testFunction, name) { + test(function () { + var element = define_new_custom_element(['title']); + var instance = document.createElement(element.name); + assert_array_equals(element.takeLog().types(), ['constructed']); + testFunction(instance, 'title'); + assert_array_equals(element.takeLog().types(), []); + }, name + ' must not enqueue an attributeChanged reaction when removing an attribute that does not exist'); + + test(function () { + var element = define_new_custom_element([]); + var instance = document.createElement(element.name); + instance.setAttribute('data-lang', 'hello'); + assert_array_equals(element.takeLog().types(), ['constructed']); + testFunction(instance, 'data-lang'); + assert_array_equals(element.takeLog().types(), []); + }, name + ' must not enqueue an attributeChanged reaction when removing an unobserved attribute'); + + test(function () { + var element = define_new_custom_element(['title']); + var instance = document.createElement(element.name); + instance.setAttribute('title', 'hello'); + assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']); + testFunction(instance, 'title'); + var logEntries = element.takeLog(); + assert_array_equals(logEntries.types(), ['attributeChanged']); + assert_attribute_log_entry(logEntries.last(), {name: 'title', oldValue: 'hello', newValue: null, namespace: null}); + }, name + ' must enqueue an attributeChanged reaction when removing an existing attribute'); + + test(function () { + var element = define_new_custom_element([]); + var instance = document.createElement(element.name); + instance.setAttribute('data-lang', 'ja'); + assert_array_equals(element.takeLog().types(), ['constructed']); + testFunction(instance, 'data-lang'); + assert_array_equals(element.takeLog().types(), []); + }, name + ' must not enqueue an attributeChanged reaction when removing an existing unobserved attribute'); +} |