diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /testing/web-platform/tests/dom/nodes | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'testing/web-platform/tests/dom/nodes')
262 files changed, 16063 insertions, 0 deletions
diff --git a/testing/web-platform/tests/dom/nodes/CharacterData-appendChild.html b/testing/web-platform/tests/dom/nodes/CharacterData-appendChild.html new file mode 100644 index 000000000..db7d51b91 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/CharacterData-appendChild.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Node.appendChild applied to CharacterData</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-appendchild"> +<link rel=help href="https://dom.spec.whatwg.org/#introduction-to-the-dom"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +function create(type) { + switch (type) { + case "Text": return document.createTextNode("test"); break; + case "Comment": return document.createComment("test"); break; + case "ProcessingInstruction": return document.createProcessingInstruction("target", "test"); break; + } +} + +function testNode(type1, type2) { + test(function() { + var node1 = create(type1); + var node2 = create(type2); + assert_throws("HierarchyRequestError", function () { + node1.appendChild(node2); + }, "CharacterData type " + type1 + " must not have children"); + }, type1 + ".appendChild(" + type2 + ")"); +} + +var types = ["Text", "Comment", "ProcessingInstruction"]; +types.forEach(function(type1) { + types.forEach(function(type2) { + testNode(type1, type2); + }); +}); +</script> diff --git a/testing/web-platform/tests/dom/nodes/CharacterData-appendData.html b/testing/web-platform/tests/dom/nodes/CharacterData-appendData.html new file mode 100644 index 000000000..d754218bf --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/CharacterData-appendData.html @@ -0,0 +1,70 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>CharacterData.appendData</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-appenddata"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +function testNode(create, type) { + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.appendData("bar") + assert_equals(node.data, "testbar") + }, type + ".appendData('bar')") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.appendData("") + assert_equals(node.data, "test") + }, type + ".appendData('')") + + test(function() { + var node = create() + assert_equals(node.data, "test") + node.appendData(", append more 資料,測試資料"); + assert_equals(node.data, "test, append more 資料,測試資料"); + assert_equals(node.length, 25); + }, type + ".appendData(non-ASCII)") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.appendData(null) + assert_equals(node.data, "testnull") + }, type + ".appendData(null)") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.appendData(undefined) + assert_equals(node.data, "testundefined") + }, type + ".appendData(undefined)") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.appendData("", "bar") + assert_equals(node.data, "test") + }, type + ".appendData('', 'bar')") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + assert_throws(new TypeError(), function() { node.appendData() }); + assert_equals(node.data, "test") + }, type + ".appendData()") +} + +testNode(function() { return document.createTextNode("test") }, "Text") +testNode(function() { return document.createComment("test") }, "Comment") +</script> diff --git a/testing/web-platform/tests/dom/nodes/CharacterData-data.html b/testing/web-platform/tests/dom/nodes/CharacterData-data.html new file mode 100644 index 000000000..b3b29ea4d --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/CharacterData-data.html @@ -0,0 +1,82 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>CharacterData.data</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +function testNode(create, type) { + test(function() { + var node = create() + assert_equals(node.data, "test") + assert_equals(node.length, 4) + }, type + ".data initial value") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.data = null; + assert_equals(node.data, "") + assert_equals(node.length, 0) + }, type + ".data = null") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.data = undefined; + assert_equals(node.data, "undefined") + assert_equals(node.length, 9) + }, type + ".data = undefined") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.data = 0; + assert_equals(node.data, "0") + assert_equals(node.length, 1) + }, type + ".data = 0") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.data = ""; + assert_equals(node.data, "") + assert_equals(node.length, 0) + }, type + ".data = ''") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.data = "--"; + assert_equals(node.data, "--") + assert_equals(node.length, 2) + }, type + ".data = '--'") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.data = "資料"; + assert_equals(node.data, "資料") + assert_equals(node.length, 2) + }, type + ".data = '資料'") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.data = "🌠 test 🌠 TEST"; + assert_equals(node.data, "🌠 test 🌠 TEST") + assert_equals(node.length, 15) // Counting UTF-16 code units + }, type + ".data = '🌠 test 🌠 TEST'") +} + +testNode(function() { return document.createTextNode("test") }, "Text") +testNode(function() { return document.createComment("test") }, "Comment") +</script> diff --git a/testing/web-platform/tests/dom/nodes/CharacterData-deleteData.html b/testing/web-platform/tests/dom/nodes/CharacterData-deleteData.html new file mode 100644 index 000000000..02ecbe6ab --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/CharacterData-deleteData.html @@ -0,0 +1,95 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>CharacterData.deleteData</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-deletedata"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +function testNode(create, type) { + test(function() { + var node = create() + assert_equals(node.data, "test") + + assert_throws("INDEX_SIZE_ERR", function() { node.deleteData(5, 10) }) + assert_throws("INDEX_SIZE_ERR", function() { node.deleteData(5, 0) }) + assert_throws("INDEX_SIZE_ERR", function() { node.deleteData(-1, 10) }) + assert_throws("INDEX_SIZE_ERR", function() { node.deleteData(-1, 0) }) + }, type + ".deleteData() out of bounds") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.deleteData(0, 2) + assert_equals(node.data, "st") + }, type + ".deleteData() at the start") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.deleteData(2, 10) + assert_equals(node.data, "te") + }, type + ".deleteData() at the end") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.deleteData(1, 1) + assert_equals(node.data, "tst") + }, type + ".deleteData() in the middle") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.deleteData(2, 0) + assert_equals(node.data, "test") + + node.deleteData(0, 0) + assert_equals(node.data, "test") + }, type + ".deleteData() with zero count") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.deleteData(2, -1) + assert_equals(node.data, "te") + }, type + ".deleteData() with small negative count") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.deleteData(1, -0x100000000 + 2) + assert_equals(node.data, "tt") + }, type + ".deleteData() with large negative count") + + test(function() { + var node = create() + node.data = "This is the character data test, append more 資料,更多測試資料"; + + node.deleteData(40, 5); + assert_equals(node.data, "This is the character data test, append 資料,更多測試資料"); + node.deleteData(45, 2); + assert_equals(node.data, "This is the character data test, append 資料,更多資料"); + }, type + ".deleteData() with non-ascii data") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.data = "🌠 test 🌠 TEST" + + node.deleteData(5, 8); // Counting UTF-16 code units + assert_equals(node.data, "🌠 teST"); + }, type + ".deleteData() with non-BMP data") +} + +testNode(function() { return document.createTextNode("test") }, "Text") +testNode(function() { return document.createComment("test") }, "Comment") +</script> diff --git a/testing/web-platform/tests/dom/nodes/CharacterData-insertData.html b/testing/web-platform/tests/dom/nodes/CharacterData-insertData.html new file mode 100644 index 000000000..5777327c2 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/CharacterData-insertData.html @@ -0,0 +1,90 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>CharacterData.insertData</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-insertdata"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +function testNode(create, type) { + test(function() { + var node = create() + assert_equals(node.data, "test") + + assert_throws("INDEX_SIZE_ERR", function() { node.insertData(5, "x") }) + assert_throws("INDEX_SIZE_ERR", function() { node.insertData(5, "") }) + }, type + ".insertData() out of bounds") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + assert_throws("INDEX_SIZE_ERR", function() { node.insertData(-1, "x") }) + assert_throws("INDEX_SIZE_ERR", function() { node.insertData(-0x100000000 + 5, "x") }) + }, type + ".insertData() negative out of bounds") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.insertData(-0x100000000 + 2, "X") + assert_equals(node.data, "teXst") + }, type + ".insertData() negative in bounds") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.insertData(0, "") + assert_equals(node.data, "test") + }, type + ".insertData('')") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.insertData(0, "X") + assert_equals(node.data, "Xtest") + }, type + ".insertData() at the start") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.insertData(2, "X") + assert_equals(node.data, "teXst") + }, type + ".insertData() in the middle") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.insertData(4, "ing") + assert_equals(node.data, "testing") + }, type + ".insertData() at the end") + + test(function() { + var node = create() + node.data = "This is the character data, append more 資料,測試資料"; + + node.insertData(26, " test"); + assert_equals(node.data, "This is the character data test, append more 資料,測試資料"); + node.insertData(48, "更多"); + assert_equals(node.data, "This is the character data test, append more 資料,更多測試資料"); + }, type + ".insertData() with non-ascii data") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.data = "🌠 test 🌠 TEST" + + node.insertData(5, "--"); // Counting UTF-16 code units + assert_equals(node.data, "🌠 te--st 🌠 TEST"); + }, type + ".insertData() with non-BMP data") +} + +testNode(function() { return document.createTextNode("test") }, "Text") +testNode(function() { return document.createComment("test") }, "Comment") +</script> diff --git a/testing/web-platform/tests/dom/nodes/CharacterData-remove.html b/testing/web-platform/tests/dom/nodes/CharacterData-remove.html new file mode 100644 index 000000000..aef9d56bf --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/CharacterData-remove.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>CharacterData.remove</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-childnode-remove"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="ChildNode-remove.js"></script> +<div id=log></div> +<script> +var text, text_parent, + comment, comment_parent, + pi, pi_parent; +setup(function() { + text = document.createTextNode("text"); + text_parent = document.createElement("div"); + comment = document.createComment("comment"); + comment_parent = document.createElement("div"); + pi = document.createProcessingInstruction("foo", "bar"); + pi_parent = document.createElement("div"); +}); +testRemove(text, text_parent, "text"); +testRemove(comment, comment_parent, "comment"); +testRemove(pi, pi_parent, "PI"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/CharacterData-replaceData.html b/testing/web-platform/tests/dom/nodes/CharacterData-replaceData.html new file mode 100644 index 000000000..624ee5f23 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/CharacterData-replaceData.html @@ -0,0 +1,163 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>CharacterData.replaceData</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-replacedata"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +function testNode(create, type) { + // Step 2. + test(function() { + var node = create() + assert_equals(node.data, "test") + + assert_throws("IndexSizeError", function() { node.replaceData(5, 1, "x") }) + assert_throws("IndexSizeError", function() { node.replaceData(5, 0, "") }) + assert_throws("IndexSizeError", function() { node.replaceData(-1, 1, "x") }) + assert_throws("IndexSizeError", function() { node.replaceData(-1, 0, "") }) + assert_equals(node.data, "test") + }, type + ".replaceData() with invalid offset") + + // Step 3. + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.replaceData(2, 10, "yo") + assert_equals(node.data, "teyo") + }, type + ".replaceData() with clamped count") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.replaceData(2, -1, "yo") + assert_equals(node.data, "teyo") + }, type + ".replaceData() with negative clamped count") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.replaceData(0, 0, "yo") + assert_equals(node.data, "yotest") + }, type + ".replaceData() before the start") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.replaceData(0, 2, "y") + assert_equals(node.data, "yst") + }, type + ".replaceData() at the start (shorter)") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.replaceData(0, 2, "yo") + assert_equals(node.data, "yost") + }, type + ".replaceData() at the start (equal length)") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.replaceData(0, 2, "yoa") + assert_equals(node.data, "yoast") + }, type + ".replaceData() at the start (longer)") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.replaceData(1, 2, "o") + assert_equals(node.data, "tot") + }, type + ".replaceData() in the middle (shorter)") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.replaceData(1, 2, "yo") + assert_equals(node.data, "tyot") + }, type + ".replaceData() in the middle (equal length)") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.replaceData(1, 1, "waddup") + assert_equals(node.data, "twaddupst") + node.replaceData(1, 1, "yup") + assert_equals(node.data, "tyupaddupst") + }, type + ".replaceData() in the middle (longer)") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.replaceData(1, 20, "yo") + assert_equals(node.data, "tyo") + }, type + ".replaceData() at the end (shorter)") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.replaceData(2, 20, "yo") + assert_equals(node.data, "teyo") + }, type + ".replaceData() at the end (same length)") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.replaceData(4, 20, "yo") + assert_equals(node.data, "testyo") + }, type + ".replaceData() at the end (longer)") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.replaceData(0, 4, "quux") + assert_equals(node.data, "quux") + }, type + ".replaceData() the whole string") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.replaceData(0, 4, "") + assert_equals(node.data, "") + }, type + ".replaceData() with the empty string") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.data = "This is the character data test, append 資料,更多資料"; + + node.replaceData(33, 6, "other"); + assert_equals(node.data, "This is the character data test, other 資料,更多資料"); + node.replaceData(44, 2, "文字"); + assert_equals(node.data, "This is the character data test, other 資料,更多文字"); + }, type + ".replaceData() with non-ASCII data") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.data = "🌠 test 🌠 TEST" + + node.replaceData(5, 8, "--"); // Counting UTF-16 code units + assert_equals(node.data, "🌠 te--ST"); + }, type + ".replaceData() with non-BMP data") +} + +testNode(function() { return document.createTextNode("test") }, "Text") +testNode(function() { return document.createComment("test") }, "Comment") +</script> diff --git a/testing/web-platform/tests/dom/nodes/CharacterData-substringData.html b/testing/web-platform/tests/dom/nodes/CharacterData-substringData.html new file mode 100644 index 000000000..f20b4b202 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/CharacterData-substringData.html @@ -0,0 +1,137 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>CharacterData.substringData</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-substringdata"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +function testNode(create, type) { + test(function() { + var node = create() + assert_equals(node.data, "test") + + assert_throws(new TypeError(), function() { node.substringData() }) + assert_throws(new TypeError(), function() { node.substringData(0) }) + }, type + ".substringData() with too few arguments") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + assert_equals(node.substringData(0, 1, "test"), "t") + }, type + ".substringData() with too many arguments") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + assert_throws("IndexSizeError", function() { node.substringData(5, 0) }) + assert_throws("IndexSizeError", function() { node.substringData(6, 0) }) + assert_throws("IndexSizeError", function() { node.substringData(-1, 0) }) + }, type + ".substringData() with invalid offset") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + assert_equals(node.substringData(0, 1), "t") + assert_equals(node.substringData(1, 1), "e") + assert_equals(node.substringData(2, 1), "s") + assert_equals(node.substringData(3, 1), "t") + assert_equals(node.substringData(4, 1), "") + }, type + ".substringData() with in-bounds offset") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + assert_equals(node.substringData(0, 0), "") + assert_equals(node.substringData(1, 0), "") + assert_equals(node.substringData(2, 0), "") + assert_equals(node.substringData(3, 0), "") + assert_equals(node.substringData(4, 0), "") + }, type + ".substringData() with zero count") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + assert_equals(node.substringData(0x100000000 + 0, 1), "t") + assert_equals(node.substringData(0x100000000 + 1, 1), "e") + assert_equals(node.substringData(0x100000000 + 2, 1), "s") + assert_equals(node.substringData(0x100000000 + 3, 1), "t") + assert_equals(node.substringData(0x100000000 + 4, 1), "") + }, type + ".substringData() with very large offset") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + assert_equals(node.substringData(-0x100000000 + 2, 1), "s") + }, type + ".substringData() with negative offset") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + assert_equals(node.substringData("test", 3), "tes") + }, type + ".substringData() with string offset") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + assert_equals(node.substringData(0, 1), "t") + assert_equals(node.substringData(0, 2), "te") + assert_equals(node.substringData(0, 3), "tes") + assert_equals(node.substringData(0, 4), "test") + }, type + ".substringData() with in-bounds count") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + assert_equals(node.substringData(0, 5), "test") + assert_equals(node.substringData(2, 20), "st") + }, type + ".substringData() with large count") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + assert_equals(node.substringData(2, 0x100000000 + 1), "s") + }, type + ".substringData() with very large count") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + assert_equals(node.substringData(0, -1), "test") + assert_equals(node.substringData(0, -0x100000000 + 2), "te") + }, type + ".substringData() with negative count") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.data = "This is the character data test, other 資料,更多文字" + + assert_equals(node.substringData(12, 4), "char") + assert_equals(node.substringData(39, 2), "資料") + }, type + ".substringData() with non-ASCII data") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.data = "🌠 test 🌠 TEST" + + assert_equals(node.substringData(5, 8), "st 🌠 TE") // Counting UTF-16 code units + }, type + ".substringData() with non-BMP data") +} + +testNode(function() { return document.createTextNode("test") }, "Text") +testNode(function() { return document.createComment("test") }, "Comment") +</script> diff --git a/testing/web-platform/tests/dom/nodes/CharacterData-surrogates.html b/testing/web-platform/tests/dom/nodes/CharacterData-surrogates.html new file mode 100644 index 000000000..ff1014c5f --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/CharacterData-surrogates.html @@ -0,0 +1,74 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Splitting and joining surrogate pairs in CharacterData methods</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-substringdata"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-replacedata"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-insertdata"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-deletedata"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +function testNode(create, type) { + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.data = "🌠 test 🌠 TEST" + + assert_equals(node.substringData(1, 8), "\uDF20 test \uD83C") + }, type + ".substringData() splitting surrogate pairs") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.data = "🌠 test 🌠 TEST" + + node.replaceData(1, 4, "--"); + assert_equals(node.data, "\uD83C--st 🌠 TEST"); + + node.replaceData(1, 2, "\uDF1F "); + assert_equals(node.data, "🌟 st 🌠 TEST"); + + node.replaceData(5, 2, "---"); + assert_equals(node.data, "🌟 st---\uDF20 TEST"); + + node.replaceData(6, 2, " \uD83D"); + assert_equals(node.data, "🌟 st- 🜠 TEST"); + }, type + ".replaceData() splitting and creating surrogate pairs") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.data = "🌠 test 🌠 TEST" + + node.deleteData(1, 4); + assert_equals(node.data, "\uD83Cst 🌠 TEST"); + + node.deleteData(1, 4); + assert_equals(node.data, "🌠 TEST"); + }, type + ".deleteData() splitting and creating surrogate pairs") + + test(function() { + var node = create() + assert_equals(node.data, "test") + + node.data = "🌠 test 🌠 TEST" + + node.insertData(1, "--"); + assert_equals(node.data, "\uD83C--\uDF20 test 🌠 TEST"); + + node.insertData(1, "\uDF1F "); + assert_equals(node.data, "🌟 --\uDF20 test 🌠 TEST"); + + node.insertData(5, " \uD83D"); + assert_equals(node.data, "🌟 -- 🜠 test 🌠 TEST"); + }, type + ".insertData() splitting and creating surrogate pairs") +} + +testNode(function() { return document.createTextNode("test") }, "Text") +testNode(function() { return document.createComment("test") }, "Comment") +</script> diff --git a/testing/web-platform/tests/dom/nodes/ChildNode-after.html b/testing/web-platform/tests/dom/nodes/ChildNode-after.html new file mode 100644 index 000000000..b5bf7ab5c --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/ChildNode-after.html @@ -0,0 +1,166 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>ChildNode.after</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-childnode-after"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + +function test_after(child, nodeName, innerHTML) { + + test(function() { + var parent = document.createElement('div'); + parent.appendChild(child); + child.after(); + assert_equals(parent.innerHTML, innerHTML); + }, nodeName + '.after() without any argument.'); + + test(function() { + var parent = document.createElement('div'); + parent.appendChild(child); + child.after(null); + var expected = innerHTML + 'null'; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.after() with null as an argument.'); + + test(function() { + var parent = document.createElement('div'); + parent.appendChild(child); + child.after(undefined); + var expected = innerHTML + 'undefined'; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.after() with undefined as an argument.'); + + test(function() { + var parent = document.createElement('div'); + parent.appendChild(child); + child.after(''); + assert_equals(parent.lastChild.data, ''); + }, nodeName + '.after() with the empty string as an argument.'); + + test(function() { + var parent = document.createElement('div'); + parent.appendChild(child); + child.after('text'); + var expected = innerHTML + 'text'; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.after() with only text as an argument.'); + + test(function() { + var parent = document.createElement('div'); + var x = document.createElement('x'); + parent.appendChild(child); + child.after(x); + var expected = innerHTML + '<x></x>'; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.after() with only one element as an argument.'); + + test(function() { + var parent = document.createElement('div'); + var x = document.createElement('x'); + parent.appendChild(child); + child.after(x, 'text'); + var expected = innerHTML + '<x></x>text'; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.after() with one element and text as arguments.'); + + test(function() { + var parent = document.createElement('div'); + parent.appendChild(child); + child.after('text', child); + var expected = 'text' + innerHTML; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.after() with context object itself as the argument.'); + + test(function() { + var parent = document.createElement('div') + var x = document.createElement('x'); + parent.appendChild(x); + parent.appendChild(child); + child.after(child, x); + var expected = innerHTML + '<x></x>'; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.after() with context object itself and node as the arguments, switching positions.'); + + test(function() { + var parent = document.createElement('div'); + var x = document.createElement('x'); + var y = document.createElement('y'); + var z = document.createElement('z'); + parent.appendChild(y); + parent.appendChild(child); + parent.appendChild(x); + child.after(x, y, z); + var expected = innerHTML + '<x></x><y></y><z></z>'; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.after() with all siblings of child as arguments.'); + + test(function() { + var parent = document.createElement('div') + var x = document.createElement('x'); + var y = document.createElement('y'); + var z = document.createElement('z'); + parent.appendChild(child); + parent.appendChild(x); + parent.appendChild(y); + parent.appendChild(z); + child.after(x, y); + var expected = innerHTML + '<x></x><y></y><z></z>'; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.before() with some siblings of child as arguments; no changes in tree; viable sibling is first child.'); + + test(function() { + var parent = document.createElement('div') + var v = document.createElement('v'); + var x = document.createElement('x'); + var y = document.createElement('y'); + var z = document.createElement('z'); + parent.appendChild(child); + parent.appendChild(v); + parent.appendChild(x); + parent.appendChild(y); + parent.appendChild(z); + child.after(v, x); + var expected = innerHTML + '<v></v><x></x><y></y><z></z>'; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.after() with some siblings of child as arguments; no changes in tree.'); + + test(function() { + var parent = document.createElement('div'); + var x = document.createElement('x'); + var y = document.createElement('y'); + parent.appendChild(child); + parent.appendChild(x); + parent.appendChild(y); + child.after(y, x); + var expected = innerHTML + '<y></y><x></x>'; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.after() when pre-insert behaves like append.'); + + test(function() { + var parent = document.createElement('div'); + var x = document.createElement('x'); + var y = document.createElement('y'); + parent.appendChild(child); + parent.appendChild(x); + parent.appendChild(document.createTextNode('1')); + parent.appendChild(y); + child.after(x, '2'); + var expected = innerHTML + '<x></x>21<y></y>'; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.after() with one sibling of child and text as arguments.'); + + test(function() { + var x = document.createElement('x'); + var y = document.createElement('y'); + x.after(y); + assert_equals(x.nextSibling, null); + }, nodeName + '.after() on a child without any parent.'); +} + +test_after(document.createComment('test'), 'Comment', '<!--test-->'); +test_after(document.createElement('test'), 'Element', '<test></test>'); +test_after(document.createTextNode('test'), 'Text', 'test'); + +</script> +</html> diff --git a/testing/web-platform/tests/dom/nodes/ChildNode-before.html b/testing/web-platform/tests/dom/nodes/ChildNode-before.html new file mode 100644 index 000000000..865942446 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/ChildNode-before.html @@ -0,0 +1,166 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>ChildNode.before</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-childnode-before"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + +function test_before(child, nodeName, innerHTML) { + + test(function() { + var parent = document.createElement('div'); + parent.appendChild(child); + child.before(); + assert_equals(parent.innerHTML, innerHTML); + }, nodeName + '.before() without any argument.'); + + test(function() { + var parent = document.createElement('div'); + parent.appendChild(child); + child.before(null); + var expected = 'null' + innerHTML; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.before() with null as an argument.'); + + test(function() { + var parent = document.createElement('div'); + parent.appendChild(child); + child.before(undefined); + var expected = 'undefined' + innerHTML; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.before() with undefined as an argument.'); + + test(function() { + var parent = document.createElement('div'); + parent.appendChild(child); + child.before(''); + assert_equals(parent.firstChild.data, ''); + }, nodeName + '.before() with the empty string as an argument.'); + + test(function() { + var parent = document.createElement('div'); + parent.appendChild(child); + child.before('text'); + var expected = 'text' + innerHTML; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.before() with only text as an argument.'); + + test(function() { + var parent = document.createElement('div'); + var x = document.createElement('x'); + parent.appendChild(child); + child.before(x); + var expected = '<x></x>' + innerHTML; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.before() with only one element as an argument.'); + + test(function() { + var parent = document.createElement('div'); + var x = document.createElement('x'); + parent.appendChild(child); + child.before(x, 'text'); + var expected = '<x></x>text' + innerHTML; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.before() with one element and text as arguments.'); + + test(function() { + var parent = document.createElement('div'); + parent.appendChild(child); + child.before('text', child); + var expected = 'text' + innerHTML; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.before() with context object itself as the argument.'); + + test(function() { + var parent = document.createElement('div') + var x = document.createElement('x'); + parent.appendChild(child); + parent.appendChild(x); + child.before(x, child); + var expected = '<x></x>' + innerHTML; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.before() with context object itself and node as the arguments, switching positions.'); + + test(function() { + var parent = document.createElement('div'); + var x = document.createElement('x'); + var y = document.createElement('y'); + var z = document.createElement('z'); + parent.appendChild(y); + parent.appendChild(child); + parent.appendChild(x); + child.before(x, y, z); + var expected = '<x></x><y></y><z></z>' + innerHTML; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.before() with all siblings of child as arguments.'); + + test(function() { + var parent = document.createElement('div') + var x = document.createElement('x'); + var y = document.createElement('y'); + var z = document.createElement('z'); + parent.appendChild(x); + parent.appendChild(y); + parent.appendChild(z); + parent.appendChild(child); + child.before(y, z); + var expected = '<x></x><y></y><z></z>' + innerHTML; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.before() with some siblings of child as arguments; no changes in tree; viable sibling is first child.'); + + test(function() { + var parent = document.createElement('div') + var v = document.createElement('v'); + var x = document.createElement('x'); + var y = document.createElement('y'); + var z = document.createElement('z'); + parent.appendChild(v); + parent.appendChild(x); + parent.appendChild(y); + parent.appendChild(z); + parent.appendChild(child); + child.before(y, z); + var expected = '<v></v><x></x><y></y><z></z>' + innerHTML; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.before() with some siblings of child as arguments; no changes in tree.'); + + test(function() { + var parent = document.createElement('div'); + var x = document.createElement('x'); + var y = document.createElement('y'); + parent.appendChild(x); + parent.appendChild(y); + parent.appendChild(child); + child.before(y, x); + var expected = '<y></y><x></x>' + innerHTML; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.before() when pre-insert behaves like prepend.'); + + test(function() { + var parent = document.createElement('div'); + var x = document.createElement('x'); + parent.appendChild(x); + parent.appendChild(document.createTextNode('1')); + var y = document.createElement('y'); + parent.appendChild(y); + parent.appendChild(child); + child.before(x, '2'); + var expected = '1<y></y><x></x>2' + innerHTML; + assert_equals(parent.innerHTML, expected); + }, nodeName + '.before() with one sibling of child and text as arguments.'); + + test(function() { + var x = document.createElement('x'); + var y = document.createElement('y'); + x.before(y); + assert_equals(x.previousSibling, null); + }, nodeName + '.before() on a child without any parent.'); +} + +test_before(document.createComment('test'), 'Comment', '<!--test-->'); +test_before(document.createElement('test'), 'Element', '<test></test>'); +test_before(document.createTextNode('test'), 'Text', 'test'); + +</script> +</html> diff --git a/testing/web-platform/tests/dom/nodes/ChildNode-remove.js b/testing/web-platform/tests/dom/nodes/ChildNode-remove.js new file mode 100644 index 000000000..c36ba0d11 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/ChildNode-remove.js @@ -0,0 +1,30 @@ +function testRemove(node, parent, type) { + test(function() { + assert_true("remove" in node); + assert_equals(typeof node.remove, "function"); + assert_equals(node.remove.length, 0); + }, type + " should support remove()"); + test(function() { + assert_equals(node.parentNode, null, "Node should not have a parent"); + assert_equals(node.remove(), undefined); + assert_equals(node.parentNode, null, "Removed new node should not have a parent"); + }, "remove() should work if " + type + " doesn't have a parent"); + test(function() { + assert_equals(node.parentNode, null, "Node should not have a parent"); + parent.appendChild(node); + assert_equals(node.parentNode, parent, "Appended node should have a parent"); + assert_equals(node.remove(), undefined); + assert_equals(node.parentNode, null, "Removed node should not have a parent"); + assert_array_equals(parent.childNodes, [], "Parent should not have children"); + }, "remove() should work if " + type + " does have a parent"); + test(function() { + assert_equals(node.parentNode, null, "Node should not have a parent"); + var before = parent.appendChild(document.createComment("before")); + parent.appendChild(node); + var after = parent.appendChild(document.createComment("after")); + assert_equals(node.parentNode, parent, "Appended node should have a parent"); + assert_equals(node.remove(), undefined); + assert_equals(node.parentNode, null, "Removed node should not have a parent"); + assert_array_equals(parent.childNodes, [before, after], "Parent should have two children left"); + }, "remove() should work if " + type + " does have a parent and siblings"); +} diff --git a/testing/web-platform/tests/dom/nodes/ChildNode-replaceWith.html b/testing/web-platform/tests/dom/nodes/ChildNode-replaceWith.html new file mode 100644 index 000000000..aab8b17f2 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/ChildNode-replaceWith.html @@ -0,0 +1,110 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>ChildNode.replaceWith</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-childnode-replaceWith"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + +function test_replaceWith(child, nodeName, innerHTML) { + + test(function() { + var parent = document.createElement('div'); + parent.appendChild(child); + child.replaceWith(); + assert_equals(parent.innerHTML, ''); + }, nodeName + '.replaceWith() without any argument.'); + + test(function() { + var parent = document.createElement('div'); + parent.appendChild(child); + child.replaceWith(null); + assert_equals(parent.innerHTML, 'null'); + }, nodeName + '.replaceWith() with null as an argument.'); + + test(function() { + var parent = document.createElement('div'); + parent.appendChild(child); + child.replaceWith(undefined); + assert_equals(parent.innerHTML, 'undefined'); + }, nodeName + '.replaceWith() with undefined as an argument.'); + + test(function() { + var parent = document.createElement('div'); + parent.appendChild(child); + child.replaceWith(''); + assert_equals(parent.innerHTML, ''); + }, nodeName + '.replaceWith() with empty string as an argument.'); + + test(function() { + var parent = document.createElement('div'); + parent.appendChild(child); + child.replaceWith('text'); + assert_equals(parent.innerHTML, 'text'); + }, nodeName + '.replaceWith() with only text as an argument.'); + + test(function() { + var parent = document.createElement('div'); + var x = document.createElement('x'); + parent.appendChild(child); + child.replaceWith(x); + assert_equals(parent.innerHTML, '<x></x>'); + }, nodeName + '.replaceWith() with only one element as an argument.'); + + test(function() { + var parent = document.createElement('div'); + var x = document.createElement('x'); + var y = document.createElement('y'); + var z = document.createElement('z'); + parent.appendChild(y); + parent.appendChild(child); + parent.appendChild(x); + child.replaceWith(x, y, z); + assert_equals(parent.innerHTML, '<x></x><y></y><z></z>'); + }, nodeName + '.replaceWith() with sibling of child as arguments.'); + + test(function() { + var parent = document.createElement('div'); + var x = document.createElement('x'); + parent.appendChild(child); + parent.appendChild(x); + parent.appendChild(document.createTextNode('1')); + child.replaceWith(x, '2'); + assert_equals(parent.innerHTML, '<x></x>21'); + }, nodeName + '.replaceWith() with one sibling of child and text as arguments.'); + + test(function() { + var parent = document.createElement('div'); + var x = document.createElement('x'); + parent.appendChild(child); + parent.appendChild(x); + parent.appendChild(document.createTextNode('text')); + child.replaceWith(x, child); + assert_equals(parent.innerHTML, '<x></x>' + innerHTML + 'text'); + }, nodeName + '.replaceWith() with one sibling of child and child itself as arguments.'); + + test(function() { + var parent = document.createElement('div'); + var x = document.createElement('x'); + parent.appendChild(child); + child.replaceWith(x, 'text'); + assert_equals(parent.innerHTML, '<x></x>text'); + }, nodeName + '.replaceWith() with one element and text as arguments.'); + + test(function() { + var parent = document.createElement('div'); + var x = document.createElement('x'); + var y = document.createElement('y'); + parent.appendChild(x); + parent.appendChild(y); + child.replaceWith(x, y); + assert_equals(parent.innerHTML, '<x></x><y></y>'); + }, nodeName + '.replaceWith() on a parentless child with two elements as arguments.'); +} + +test_replaceWith(document.createComment('test'), 'Comment', '<!--test-->'); +test_replaceWith(document.createElement('test'), 'Element', '<test></test>'); +test_replaceWith(document.createTextNode('test'), 'Text', 'test'); + +</script> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Comment-Text-constructor.js b/testing/web-platform/tests/dom/nodes/Comment-Text-constructor.js new file mode 100644 index 000000000..360b9760e --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Comment-Text-constructor.js @@ -0,0 +1,77 @@ +function test_constructor(ctor) { + test(function() { + var object = new window[ctor](); + assert_equals(Object.getPrototypeOf(object), + window[ctor].prototype, "Prototype chain: " + ctor); + assert_equals(Object.getPrototypeOf(Object.getPrototypeOf(object)), + CharacterData.prototype, "Prototype chain: CharacterData"); + assert_equals(Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(object))), + Node.prototype, "Prototype chain: Node"); + }, "new " + ctor + "(): prototype chain"); + + test(function() { + var object = new window[ctor](); + assert_true(object instanceof Node, "Should be a Node"); + assert_true(object instanceof CharacterData, "Should be a CharacterData"); + assert_true(object instanceof window[ctor], "Should be a " + ctor); + }, "new " + ctor + "(): instanceof"); + + test(function() { + var object = new window[ctor](); + assert_equals(object.data, ""); + assert_equals(object.nodeValue, ""); + assert_equals(object.ownerDocument, document); + }, "new " + ctor + "(): no arguments"); + + var arguments = [ + [undefined, ""], + [null, "null"], + [42, "42"], + ["", ""], + ["-", "-"], + ["--", "--"], + ["-->", "-->"], + ["<!--", "<!--"], + ["\u0000", "\u0000"], + ["\u0000test", "\u0000test"], + ["&", "&"], + ]; + + arguments.forEach(function(a) { + var argument = a[0], expected = a[1]; + test(function() { + var object = new window[ctor](argument); + assert_equals(object.data, expected); + assert_equals(object.nodeValue, expected); + assert_equals(object.ownerDocument, document); + }, "new " + ctor + "(): " + format_value(argument)); + }); + + test(function() { + var called = []; + var object = new window[ctor]({ + toString: function() { + called.push("first"); + return "text"; + } + }, { + toString: function() { + called.push("second"); + assert_unreached("Should not look at the second argument."); + } + }); + assert_equals(object.data, "text"); + assert_equals(object.nodeValue, "text"); + assert_equals(object.ownerDocument, document); + assert_array_equals(called, ["first"]); + }, "new " + ctor + "(): two arguments") + + async_test("new " + ctor + "() should get the correct ownerDocument across globals").step(function() { + var iframe = document.createElement("iframe"); + iframe.onload = this.step_func_done(function() { + var object = new iframe.contentWindow[ctor](); + assert_equals(object.ownerDocument, iframe.contentDocument); + }); + document.body.appendChild(iframe); + }); +} diff --git a/testing/web-platform/tests/dom/nodes/Comment-constructor.html b/testing/web-platform/tests/dom/nodes/Comment-constructor.html new file mode 100644 index 000000000..5091316bd --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Comment-constructor.html @@ -0,0 +1,11 @@ +<!doctype html> +<meta charset=utf-8> +<title>Comment constructor</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-comment"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="Comment-Text-constructor.js"></script> +<div id="log"></div> +<script> +test_constructor("Comment"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/DOMImplementation-createDocument.html b/testing/web-platform/tests/dom/nodes/DOMImplementation-createDocument.html new file mode 100644 index 000000000..f4b635871 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/DOMImplementation-createDocument.html @@ -0,0 +1,166 @@ +<!doctype html> +<meta charset=utf-8> +<title>DOMImplementation.createDocument(namespace, qualifiedName, doctype)</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-domimplementation-createdocument"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createelementns"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodetype"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-documentelement"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-doctype"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="Document-createElementNS.js"></script> +<div id="log"></div> +<script> +var htmlNamespace = "http://www.w3.org/1999/xhtml" +var svgNamespace = "http://www.w3.org/2000/svg" +var mathMLNamespace = "http://www.w3.org/1998/Math/MathML" + +// Make DocumentTypes distinct +function my_format_value(val) { + if (val instanceof DocumentType) { + return "DocumentType node <!DOCTYPE " + val.name + + (val.publicId ? " " + val.publicId : "") + + (val.systemId ? " " + val.systemId : "") + + ">"; + } + return format_value(val); +} + +test(function() { + var tests = createElementNS_tests.map(function(t) { + return [t[0], t[1], null, t[2]] + }).concat([ + /* Arrays with four elements: + * the namespace argument + * the qualifiedName argument + * the doctype argument + * the expected exception, or null if none + */ + [null, null, false, new TypeError()], + [null, null, null, null], + [null, "", null, null], + [undefined, null, undefined, null], + [undefined, undefined, undefined, null], + [undefined, "", undefined, null], + ["http://example.com/", null, null, null], + ["http://example.com/", "", null, null], + ["/", null, null, null], + ["/", "", null, null], + ["http://www.w3.org/XML/1998/namespace", null, null, null], + ["http://www.w3.org/XML/1998/namespace", "", null, null], + ["http://www.w3.org/2000/xmlns/", null, null, null], + ["http://www.w3.org/2000/xmlns/", "", null, null], + ["foo:", null, null, null], + ["foo:", "", null, null], + [null, null, document.implementation.createDocumentType("foo", "", ""), null], + [null, null, document.doctype, null], // This causes a horrible WebKit bug (now fixed in trunk). + [null, null, function() { + var foo = document.implementation.createDocumentType("bar", "", ""); + document.implementation.createDocument(null, null, foo); + return foo; + }(), null], // DOCTYPE already associated with a document. + [null, null, function() { + var bar = document.implementation.createDocument(null, null, null); + return bar.implementation.createDocumentType("baz", "", ""); + }(), null], // DOCTYPE created by a different implementation. + [null, null, function() { + var bar = document.implementation.createDocument(null, null, null); + var magic = bar.implementation.createDocumentType("quz", "", ""); + bar.implementation.createDocument(null, null, magic); + return magic; + }(), null], // DOCTYPE created by a different implementation and already associated with a document. + [null, "foo", document.implementation.createDocumentType("foo", "", ""), null], + ["foo", null, document.implementation.createDocumentType("foo", "", ""), null], + ["foo", "bar", document.implementation.createDocumentType("foo", "", ""), null], + [htmlNamespace, "", null, null], + [svgNamespace, "", null, null], + [mathMLNamespace, "", null, null], + [null, "html", null, null], + [null, "svg", null, null], + [null, "math", null, null], + [null, "", document.implementation.createDocumentType("html", + "-//W3C//DTD XHTML 1.0 Transitional//EN", + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd")], + [null, "", document.implementation.createDocumentType("svg", + "-//W3C//DTD SVG 1.1//EN", + "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd")], + [null, "", document.implementation.createDocumentType("math", + "-//W3C//DTD MathML 2.0//EN", + "http://www.w3.org/Math/DTD/mathml2/mathml2.dtd")], + ]) + + tests.forEach(function(t, i) { + var namespace = t[0], qualifiedName = t[1], doctype = t[2], expected = t[3] + test(function() { + if (expected != null) { + assert_throws(expected, function() { document.implementation.createDocument(namespace, qualifiedName, doctype) }) + } else { + var doc = document.implementation.createDocument(namespace, qualifiedName, doctype) + assert_equals(doc.nodeType, Node.DOCUMENT_NODE) + assert_equals(doc.nodeType, doc.DOCUMENT_NODE) + assert_equals(doc.nodeName, "#document") + assert_equals(doc.nodeValue, null) + assert_equals(Object.getPrototypeOf(doc), XMLDocument.prototype) + var omitRootElement = qualifiedName === null || String(qualifiedName) === "" + if (omitRootElement) { + assert_equals(doc.documentElement, null) + } else { + var element = doc.documentElement + assert_not_equals(element, null) + assert_equals(element.nodeType, Node.ELEMENT_NODE) + assert_equals(element.ownerDocument, doc) + var qualified = String(qualifiedName), names = [] + if (qualified.indexOf(":") >= 0) { + names = qualified.split(":", 2) + } else { + names = [null, qualified] + } + assert_equals(element.prefix, names[0]) + assert_equals(element.localName, names[1]) + assert_equals(element.namespaceURI, namespace === undefined ? null : namespace) + } + if (!doctype) { + assert_equals(doc.doctype, null) + } else { + assert_equals(doc.doctype, doctype) + assert_equals(doc.doctype.ownerDocument, doc) + } + assert_equals(doc.childNodes.length, !omitRootElement + !!doctype) + } + }, "createDocument test: " + t.map(my_format_value)) + + if (expected === null) { + test(function() { + var doc = document.implementation.createDocument(namespace, qualifiedName, doctype) + assert_equals(doc.compatMode, "CSS1Compat") + assert_equals(doc.characterSet, "UTF-8") + assert_equals(doc.contentType, namespace == htmlNamespace ? "application/xhtml+xml" + : namespace == svgNamespace ? "image/svg+xml" + : "application/xml") + assert_equals(doc.URL, "about:blank") + assert_equals(doc.documentURI, "about:blank") + assert_equals(doc.createElement("DIV").localName, "DIV"); + }, "createDocument test " + i + ": metadata for " + + [namespace, qualifiedName, doctype].map(my_format_value)) + + test(function() { + var doc = document.implementation.createDocument(namespace, qualifiedName, doctype) + assert_equals(doc.characterSet, "UTF-8", "characterSet"); + assert_equals(doc.charset, "UTF-8", "charset"); + assert_equals(doc.inputEncoding, "UTF-8", "inputEncoding"); + }, "createDocument test " + i + ": characterSet aliases for " + + [namespace, qualifiedName, doctype].map(my_format_value)) + } + }) +}) + +test(function() { + assert_throws(new TypeError(), function() { + document.implementation.createDocument() + }, "createDocument() should throw") + + assert_throws(new TypeError(), function() { + document.implementation.createDocument('') + }, "createDocument('') should throw") +}, "createDocument with missing arguments"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/DOMImplementation-createDocumentType.html b/testing/web-platform/tests/dom/nodes/DOMImplementation-createDocumentType.html new file mode 100644 index 000000000..ac79ddd73 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/DOMImplementation-createDocumentType.html @@ -0,0 +1,123 @@ +<!doctype html> +<meta charset=utf-8> +<title>DOMImplementation.createDocumentType(qualifiedName, publicId, systemId)</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-name"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-publicid"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-systemid"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-ownerdocument"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + var tests = [ + ["", "", "", "INVALID_CHARACTER_ERR"], + ["test:root", "1234", "", null], + ["test:root", "1234", "test", null], + ["test:root", "test", "", null], + ["test:root", "test", "test", null], + ["_:_", "", "", null], + ["_:h0", "", "", null], + ["_:test", "", "", null], + ["_:_.", "", "", null], + ["_:a-", "", "", null], + ["l_:_", "", "", null], + ["ns:_0", "", "", null], + ["ns:a0", "", "", null], + ["ns0:test", "", "", null], + ["ns:EEE.", "", "", null], + ["ns:_-", "", "", null], + ["a.b:c", "", "", null], + ["a-b:c.j", "", "", null], + ["a-b:c", "", "", null], + ["foo", "", "", null], + ["1foo", "", "", "INVALID_CHARACTER_ERR"], + ["foo1", "", "", null], + ["f1oo", "", "", null], + ["@foo", "", "", "INVALID_CHARACTER_ERR"], + ["foo@", "", "", "INVALID_CHARACTER_ERR"], + ["f@oo", "", "", "INVALID_CHARACTER_ERR"], + ["edi:{", "", "", "INVALID_CHARACTER_ERR"], + ["edi:}", "", "", "INVALID_CHARACTER_ERR"], + ["edi:~", "", "", "INVALID_CHARACTER_ERR"], + ["edi:'", "", "", "INVALID_CHARACTER_ERR"], + ["edi:!", "", "", "INVALID_CHARACTER_ERR"], + ["edi:@", "", "", "INVALID_CHARACTER_ERR"], + ["edi:#", "", "", "INVALID_CHARACTER_ERR"], + ["edi:$", "", "", "INVALID_CHARACTER_ERR"], + ["edi:%", "", "", "INVALID_CHARACTER_ERR"], + ["edi:^", "", "", "INVALID_CHARACTER_ERR"], + ["edi:&", "", "", "INVALID_CHARACTER_ERR"], + ["edi:*", "", "", "INVALID_CHARACTER_ERR"], + ["edi:(", "", "", "INVALID_CHARACTER_ERR"], + ["edi:)", "", "", "INVALID_CHARACTER_ERR"], + ["edi:+", "", "", "INVALID_CHARACTER_ERR"], + ["edi:=", "", "", "INVALID_CHARACTER_ERR"], + ["edi:[", "", "", "INVALID_CHARACTER_ERR"], + ["edi:]", "", "", "INVALID_CHARACTER_ERR"], + ["edi:\\", "", "", "INVALID_CHARACTER_ERR"], + ["edi:/", "", "", "INVALID_CHARACTER_ERR"], + ["edi:;", "", "", "INVALID_CHARACTER_ERR"], + ["edi:`", "", "", "INVALID_CHARACTER_ERR"], + ["edi:<", "", "", "INVALID_CHARACTER_ERR"], + ["edi:>", "", "", "INVALID_CHARACTER_ERR"], + ["edi:,", "", "", "INVALID_CHARACTER_ERR"], + ["edi:a ", "", "", "INVALID_CHARACTER_ERR"], + ["edi:\"", "", "", "INVALID_CHARACTER_ERR"], + ["{", "", "", "INVALID_CHARACTER_ERR"], + ["}", "", "", "INVALID_CHARACTER_ERR"], + ["'", "", "", "INVALID_CHARACTER_ERR"], + ["~", "", "", "INVALID_CHARACTER_ERR"], + ["`", "", "", "INVALID_CHARACTER_ERR"], + ["@", "", "", "INVALID_CHARACTER_ERR"], + ["#", "", "", "INVALID_CHARACTER_ERR"], + ["$", "", "", "INVALID_CHARACTER_ERR"], + ["%", "", "", "INVALID_CHARACTER_ERR"], + ["^", "", "", "INVALID_CHARACTER_ERR"], + ["&", "", "", "INVALID_CHARACTER_ERR"], + ["*", "", "", "INVALID_CHARACTER_ERR"], + ["(", "", "", "INVALID_CHARACTER_ERR"], + [")", "", "", "INVALID_CHARACTER_ERR"], + ["f:oo", "", "", null], + [":foo", "", "", "NAMESPACE_ERR"], + ["foo:", "", "", "NAMESPACE_ERR"], + ["prefix::local", "", "", "NAMESPACE_ERR"], + ["foo", "foo", "", null], + ["foo", "", "foo", null], + ["foo", "f'oo", "", null], + ["foo", "", "f'oo", null], + ["foo", 'f"oo', "", null], + ["foo", "", 'f"oo', null], + ["foo", "f'o\"o", "", null], + ["foo", "", "f'o\"o", null], + ["foo", "foo>", "", null], + ["foo", "", "foo>", null] + ] + + var doc = document.implementation.createHTMLDocument("title"); + var doTest = function(aDocument, aQualifiedName, aPublicId, aSystemId) { + var doctype = aDocument.implementation.createDocumentType(aQualifiedName, aPublicId, aSystemId); + assert_equals(doctype.name, aQualifiedName, "name") + assert_equals(doctype.nodeName, aQualifiedName, "nodeName") + assert_equals(doctype.publicId, aPublicId, "publicId") + assert_equals(doctype.systemId, aSystemId, "systemId") + assert_equals(doctype.ownerDocument, aDocument, "ownerDocument") + assert_equals(doctype.nodeValue, null, "nodeValue") + } + tests.forEach(function(t) { + var qualifiedName = t[0], publicId = t[1], systemId = t[2], expected = t[3] + test(function() { + if (expected) { + assert_throws(expected, function() { + document.implementation.createDocumentType(qualifiedName, publicId, systemId) + }) + } else { + doTest(document, qualifiedName, publicId, systemId); + doTest(doc, qualifiedName, publicId, systemId); + } + }, "createDocumentType(" + format_value(qualifiedName) + ", " + format_value(publicId) + ", " + format_value(systemId) + ") should " + + (expected ? "throw " + expected : "work")); + }); +}) +</script> diff --git a/testing/web-platform/tests/dom/nodes/DOMImplementation-createHTMLDocument.html b/testing/web-platform/tests/dom/nodes/DOMImplementation-createHTMLDocument.html new file mode 100644 index 000000000..57f475c9c --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/DOMImplementation-createHTMLDocument.html @@ -0,0 +1,90 @@ +<!DOCTYPE html> +<meta charset=windows-1252> +<!-- Using windows-1252 to ensure that DOMImplementation.createHTMLDocument() + doesn't inherit utf-8 from the parent document. --> +<title>DOMImplementation.createHTMLDocument</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-name"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-publicid"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-systemid"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-documentelement"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="DOMImplementation-createHTMLDocument.js"></script> +<div id="log"></div> +<script> +createHTMLDocuments(function(doc, expectedtitle, normalizedtitle) { + assert_true(doc instanceof Document, "Should be a Document") + assert_true(doc instanceof Node, "Should be a Node") + assert_equals(doc.childNodes.length, 2, + "Document should have two child nodes") + + var doctype = doc.doctype + assert_true(doctype instanceof DocumentType, + "Doctype should be a DocumentType") + assert_true(doctype instanceof Node, "Doctype should be a Node") + assert_equals(doctype.name, "html") + assert_equals(doctype.publicId, "") + assert_equals(doctype.systemId, "") + + var documentElement = doc.documentElement + assert_true(documentElement instanceof HTMLHtmlElement, + "Document element should be a HTMLHtmlElement") + assert_equals(documentElement.childNodes.length, 2, + "Document element should have two child nodes") + assert_equals(documentElement.localName, "html") + assert_equals(documentElement.tagName, "HTML") + + var head = documentElement.firstChild + assert_true(head instanceof HTMLHeadElement, + "Head should be a HTMLHeadElement") + assert_equals(head.localName, "head") + assert_equals(head.tagName, "HEAD") + + if (expectedtitle !== undefined) { + assert_equals(head.childNodes.length, 1) + + var title = head.firstChild + assert_true(title instanceof HTMLTitleElement, + "Title should be a HTMLTitleElement") + assert_equals(title.localName, "title") + assert_equals(title.tagName, "TITLE") + assert_equals(title.childNodes.length, 1) + assert_equals(title.firstChild.data, expectedtitle) + } else { + assert_equals(head.childNodes.length, 0) + } + + var body = documentElement.lastChild + assert_true(body instanceof HTMLBodyElement, + "Body should be a HTMLBodyElement") + assert_equals(body.localName, "body") + assert_equals(body.tagName, "BODY") + assert_equals(body.childNodes.length, 0) +}) + +test(function() { + var doc = document.implementation.createHTMLDocument("test"); + assert_equals(doc.URL, "about:blank"); + assert_equals(doc.documentURI, "about:blank"); + assert_equals(doc.compatMode, "CSS1Compat"); + assert_equals(doc.characterSet, "UTF-8"); + assert_equals(doc.contentType, "text/html"); + assert_equals(doc.createElement("DIV").localName, "div"); +}, "createHTMLDocument(): metadata") + +test(function() { + var doc = document.implementation.createHTMLDocument("test"); + assert_equals(doc.characterSet, "UTF-8", "characterSet"); + assert_equals(doc.charset, "UTF-8", "charset"); + assert_equals(doc.inputEncoding, "UTF-8", "inputEncoding"); +}, "createHTMLDocument(): characterSet aliases") + +test(function() { + var doc = document.implementation.createHTMLDocument("test"); + var a = doc.createElement("a"); + // In UTF-8: 0xC3 0xA4 + a.href = "http://example.org/?\u00E4"; + assert_equals(a.href, "http://example.org/?%C3%A4"); +}, "createHTMLDocument(): URL parsing") +</script> diff --git a/testing/web-platform/tests/dom/nodes/DOMImplementation-createHTMLDocument.js b/testing/web-platform/tests/dom/nodes/DOMImplementation-createHTMLDocument.js new file mode 100644 index 000000000..3e7e9aa9b --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/DOMImplementation-createHTMLDocument.js @@ -0,0 +1,25 @@ +function createHTMLDocuments(checkDoc) { + var tests = [ + ["", "", ""], + [null, "null", "null"], + [undefined, undefined, ""], + ["foo bar baz", "foo bar baz", "foo bar baz"], + ["foo\t\tbar baz", "foo\t\tbar baz", "foo bar baz"], + ["foo\n\nbar baz", "foo\n\nbar baz", "foo bar baz"], + ["foo\f\fbar baz", "foo\f\fbar baz", "foo bar baz"], + ["foo\r\rbar baz", "foo\r\rbar baz", "foo bar baz"], + ] + + tests.forEach(function(t, i) { + var title = t[0], expectedtitle = t[1], normalizedtitle = t[2] + test(function() { + var doc = document.implementation.createHTMLDocument(title); + checkDoc(doc, expectedtitle, normalizedtitle) + }, "createHTMLDocument test " + i + ": " + t.map(function(el) { return format_value(el) })) + }) + + test(function() { + var doc = document.implementation.createHTMLDocument(); + checkDoc(doc, undefined, "") + }, "Missing title argument"); +} diff --git a/testing/web-platform/tests/dom/nodes/DOMImplementation-hasFeature.html b/testing/web-platform/tests/dom/nodes/DOMImplementation-hasFeature.html new file mode 100644 index 000000000..637565a60 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/DOMImplementation-hasFeature.html @@ -0,0 +1,155 @@ +<!doctype html> +<meta charset=utf-8> +<title>DOMImplementation.hasFeature(feature, version)</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + var tests = [ + [], + ["Core"], + ["XML"], + ["org.w3c.svg"], + ["org.w3c.dom.svg"], + ["http://www.w3.org/TR/SVG11/feature#Script"], + ["Core", "1.0"], + ["Core", "2.0"], + ["Core", "3.0"], + ["Core", "100.0"], + ["XML", "1.0"], + ["XML", "2.0"], + ["XML", "3.0"], + ["XML", "100.0"], + ["Core", "1"], + ["Core", "2"], + ["Core", "3"], + ["Core", "100"], + ["XML", "1"], + ["XML", "2"], + ["XML", "3"], + ["XML", "100"], + ["Core", "1.1"], + ["Core", "2.1"], + ["Core", "3.1"], + ["Core", "100.1"], + ["XML", "1.1"], + ["XML", "2.1"], + ["XML", "3.1"], + ["XML", "100.1"], + ["Core", ""], + ["XML", ""], + ["core", ""], + ["xml", ""], + ["CoRe", ""], + ["XmL", ""], + [" Core", ""], + [" XML", ""], + ["Core ", ""], + ["XML ", ""], + ["Co re", ""], + ["XM L", ""], + ["aCore", ""], + ["aXML", ""], + ["Corea", ""], + ["XMLa", ""], + ["Coare", ""], + ["XMaL", ""], + ["Core", " "], + ["XML", " "], + ["Core", " 1.0"], + ["Core", " 2.0"], + ["Core", " 3.0"], + ["Core", " 100.0"], + ["XML", " 1.0"], + ["XML", " 2.0"], + ["XML", " 3.0"], + ["XML", " 100.0"], + ["Core", "1.0 "], + ["Core", "2.0 "], + ["Core", "3.0 "], + ["Core", "100.0 "], + ["XML", "1.0 "], + ["XML", "2.0 "], + ["XML", "3.0 "], + ["XML", "100.0 "], + ["Core", "1. 0"], + ["Core", "2. 0"], + ["Core", "3. 0"], + ["Core", "100. 0"], + ["XML", "1. 0"], + ["XML", "2. 0"], + ["XML", "3. 0"], + ["XML", "100. 0"], + ["Core", "a1.0"], + ["Core", "a2.0"], + ["Core", "a3.0"], + ["Core", "a100.0"], + ["XML", "a1.0"], + ["XML", "a2.0"], + ["XML", "a3.0"], + ["XML", "a100.0"], + ["Core", "1.0a"], + ["Core", "2.0a"], + ["Core", "3.0a"], + ["Core", "100.0a"], + ["XML", "1.0a"], + ["XML", "2.0a"], + ["XML", "3.0a"], + ["XML", "100.0a"], + ["Core", "1.a0"], + ["Core", "2.a0"], + ["Core", "3.a0"], + ["Core", "100.a0"], + ["XML", "1.a0"], + ["XML", "2.a0"], + ["XML", "3.a0"], + ["XML", "100.a0"], + ["Core", 1], + ["Core", 2], + ["Core", 3], + ["Core", 100], + ["XML", 1], + ["XML", 2], + ["XML", 3], + ["XML", 100], + ["Core", null], + ["XML", null], + ["core", null], + ["xml", null], + ["CoRe", null], + ["XmL", null], + [" Core", null], + [" XML", null], + ["Core ", null], + ["XML ", null], + ["Co re", null], + ["XM L", null], + ["aCore", null], + ["aXML", null], + ["Corea", null], + ["XMLa", null], + ["Coare", null], + ["XMaL", null], + ["Core", undefined], + ["XML", undefined], + ["This is filler text.", ""], + [null, ""], + [undefined, ""], + ["org.w3c.svg", ""], + ["org.w3c.svg", "1.0"], + ["org.w3c.svg", "1.1"], + ["org.w3c.dom.svg", ""], + ["org.w3c.dom.svg", "1.0"], + ["org.w3c.dom.svg", "1.1"], + ["http://www.w3.org/TR/SVG11/feature#Script", "7.5"], + ]; + tests.forEach(function(data) { + test(function() { + assert_equals(document.implementation.hasFeature + .apply(document.implementation, data), true) + }, "hasFeature(" + data.map(format_value).join(", ") + ")") + }) +}) +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-Element-getElementsByTagName.js b/testing/web-platform/tests/dom/nodes/Document-Element-getElementsByTagName.js new file mode 100644 index 000000000..edbac646d --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-Element-getElementsByTagName.js @@ -0,0 +1,193 @@ +function test_getElementsByTagName(context, element) { + // TODO: getElementsByTagName("*") + test(function() { + assert_false(context.getElementsByTagName("html") instanceof NodeList, + "Should not return a NodeList") + assert_true(context.getElementsByTagName("html") instanceof HTMLCollection, + "Should return an HTMLCollection") + }, "Interfaces") + + test(function() { + var firstCollection = context.getElementsByTagName("html"), + secondCollection = context.getElementsByTagName("html") + assert_true(firstCollection !== secondCollection || + firstCollection === secondCollection) + }, "Caching is allowed") + + test(function() { + var l = context.getElementsByTagName("nosuchtag") + l[5] = "foopy" + assert_equals(l[5], undefined) + assert_equals(l.item(5), null) + }, "Shouldn't be able to set unsigned properties on a HTMLCollection (non-strict mode)") + + test(function() { + var l = context.getElementsByTagName("nosuchtag") + assert_throws(new TypeError(), function() { + "use strict"; + l[5] = "foopy" + }) + assert_equals(l[5], undefined) + assert_equals(l.item(5), null) + }, "Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode)") + + test(function() { + var l = context.getElementsByTagName("nosuchtag") + var fn = l.item; + assert_equals(fn, HTMLCollection.prototype.item); + l.item = "pass" + assert_equals(l.item, "pass") + assert_equals(HTMLCollection.prototype.item, fn); + }, "Should be able to set expando shadowing a proto prop (item)") + + test(function() { + var l = context.getElementsByTagName("nosuchtag") + var fn = l.namedItem; + assert_equals(fn, HTMLCollection.prototype.namedItem); + l.namedItem = "pass" + assert_equals(l.namedItem, "pass") + assert_equals(HTMLCollection.prototype.namedItem, fn); + }, "Should be able to set expando shadowing a proto prop (namedItem)") + + test(function() { + var t1 = element.appendChild(document.createElement("pre")); + t1.id = "x"; + var t2 = element.appendChild(document.createElement("pre")); + t2.setAttribute("name", "y"); + var t3 = element.appendChild(document.createElementNS("", "pre")); + t3.setAttribute("id", "z"); + var t4 = element.appendChild(document.createElementNS("", "pre")); + t4.setAttribute("name", "w"); + this.add_cleanup(function() { + element.removeChild(t1) + element.removeChild(t2) + element.removeChild(t3) + element.removeChild(t4) + }); + + var list = context.getElementsByTagName('pre'); + var pre = list[0]; + assert_equals(pre.id, "x"); + + var exposedNames = { 'x': 0, 'y': 1, 'z': 2 }; + for (var exposedName in exposedNames) { + assert_equals(list[exposedName], list[exposedNames[exposedName]]); + assert_equals(list[exposedName], list.namedItem(exposedName)); + assert_true(exposedName in list, "'" + exposedName + "' in list"); + assert_true(list.hasOwnProperty(exposedName), + "list.hasOwnProperty('" + exposedName + "')"); + } + + var unexposedNames = ["w"]; + for (var unexposedName of unexposedNames) { + assert_false(unexposedName in list); + assert_false(list.hasOwnProperty(unexposedName)); + assert_equals(list[unexposedName], undefined); + assert_equals(list.namedItem(unexposedName), null); + } + + assert_array_equals(Object.getOwnPropertyNames(list).sort(), + ["0", "1", "2", "3", "x", "y", "z"]); + + var desc = Object.getOwnPropertyDescriptor(list, '0'); + assert_equals(typeof desc, "object", "descriptor should be an object"); + assert_true(desc.enumerable, "desc.enumerable"); + assert_true(desc.configurable, "desc.configurable"); + + desc = Object.getOwnPropertyDescriptor(list, 'x'); + assert_equals(typeof desc, "object", "descriptor should be an object"); + assert_false(desc.enumerable, "desc.enumerable"); + assert_true(desc.configurable, "desc.configurable"); + }, "hasOwnProperty, getOwnPropertyDescriptor, getOwnPropertyNames") + + test(function() { + assert_equals(document.createElementNS("http://www.w3.org/1999/xhtml", "i").localName, "i") // Sanity + var t = element.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "I")) + this.add_cleanup(function() {element.removeChild(t)}) + assert_equals(t.localName, "I") + assert_equals(t.tagName, "I") + assert_equals(context.getElementsByTagName("I").length, 0) + assert_equals(context.getElementsByTagName("i").length, 0) + }, "HTML element with uppercase tagName never matches in HTML Documents") + + test(function() { + var t = element.appendChild(document.createElementNS("test", "st")) + this.add_cleanup(function() {element.removeChild(t)}) + assert_array_equals(context.getElementsByTagName("st"), [t]) + assert_array_equals(context.getElementsByTagName("ST"), []) + }, "Element in non-HTML namespace, no prefix, lowercase name") + + test(function() { + var t = element.appendChild(document.createElementNS("test", "ST")) + this.add_cleanup(function() {element.removeChild(t)}) + assert_array_equals(context.getElementsByTagName("ST"), [t]) + assert_array_equals(context.getElementsByTagName("st"), []) + }, "Element in non-HTML namespace, no prefix, uppercase name") + + test(function() { + var t = element.appendChild(document.createElementNS("test", "te:st")) + this.add_cleanup(function() {element.removeChild(t)}) + assert_array_equals(context.getElementsByTagName("st"), []) + assert_array_equals(context.getElementsByTagName("ST"), []) + assert_array_equals(context.getElementsByTagName("te:st"), [t]) + assert_array_equals(context.getElementsByTagName("te:ST"), []) + }, "Element in non-HTML namespace, prefix, lowercase name") + + test(function() { + var t = element.appendChild(document.createElementNS("test", "te:ST")) + this.add_cleanup(function() {element.removeChild(t)}) + assert_array_equals(context.getElementsByTagName("st"), []) + assert_array_equals(context.getElementsByTagName("ST"), []) + assert_array_equals(context.getElementsByTagName("te:st"), []) + assert_array_equals(context.getElementsByTagName("te:ST"), [t]) + }, "Element in non-HTML namespace, prefix, uppercase name") + + test(function() { + var t = element.appendChild(document.createElement("aÇ")) + this.add_cleanup(function() {element.removeChild(t)}) + assert_equals(t.localName, "aÇ") + assert_array_equals(context.getElementsByTagName("AÇ"), [t], "All uppercase input") + assert_array_equals(context.getElementsByTagName("aÇ"), [t], "Ascii lowercase input") + assert_array_equals(context.getElementsByTagName("aç"), [], "All lowercase input") + }, "Element in HTML namespace, no prefix, non-ascii characters in name") + + test(function() { + var t = element.appendChild(document.createElementNS("test", "AÇ")) + this.add_cleanup(function() {element.removeChild(t)}) + assert_array_equals(context.getElementsByTagName("AÇ"), [t]) + assert_array_equals(context.getElementsByTagName("aÇ"), []) + assert_array_equals(context.getElementsByTagName("aç"), []) + }, "Element in non-HTML namespace, non-ascii characters in name") + + test(function() { + var t = element.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "test:aÇ")) + this.add_cleanup(function() {element.removeChild(t)}) + assert_array_equals(context.getElementsByTagName("TEST:AÇ"), [t], "All uppercase input") + assert_array_equals(context.getElementsByTagName("test:aÇ"), [t], "Ascii lowercase input") + assert_array_equals(context.getElementsByTagName("test:aç"), [], "All lowercase input") + }, "Element in HTML namespace, prefix, non-ascii characters in name") + + test(function() { + var t = element.appendChild(document.createElementNS("test", "TEST:AÇ")) + this.add_cleanup(function() {element.removeChild(t)}) + assert_array_equals(context.getElementsByTagName("TEST:AÇ"), [t], "All uppercase input") + assert_array_equals(context.getElementsByTagName("test:aÇ"), [], "Ascii lowercase input") + assert_array_equals(context.getElementsByTagName("test:aç"), [], "All lowercase input") + }, "Element in non-HTML namespace, prefix, non-ascii characters in name") + + test(function() { + var actual = context.getElementsByTagName("*"); + var expected = []; + var get_elements = function(node) { + for (var i = 0; i < node.childNodes.length; i++) { + var child = node.childNodes[i]; + if (child.nodeType === child.ELEMENT_NODE) { + expected.push(child); + get_elements(child); + } + } + } + get_elements(context); + assert_array_equals(actual, expected); + }, "getElementsByTagName('*')") +} diff --git a/testing/web-platform/tests/dom/nodes/Document-Element-getElementsByTagNameNS.js b/testing/web-platform/tests/dom/nodes/Document-Element-getElementsByTagNameNS.js new file mode 100644 index 000000000..a1bb31587 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-Element-getElementsByTagNameNS.js @@ -0,0 +1,128 @@ +function test_getElementsByTagNameNS(context, element) { + test(function() { + assert_false(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "html") instanceof NodeList, "NodeList") + assert_true(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "html") instanceof HTMLCollection, "HTMLCollection") + var firstCollection = context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "html"), + secondCollection = context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "html") + assert_true(firstCollection !== secondCollection || firstCollection === secondCollection, + "Caching is allowed.") + }) + + test(function() { + var t = element.appendChild(document.createElementNS("test", "body")) + this.add_cleanup(function() {element.removeChild(t)}) + var actual = context.getElementsByTagNameNS("*", "body"); + var expected = []; + var get_elements = function(node) { + for (var i = 0; i < node.childNodes.length; i++) { + var child = node.childNodes[i]; + if (child.nodeType === child.ELEMENT_NODE) { + if (child.localName == "body") { + expected.push(child); + } + get_elements(child); + } + } + } + get_elements(context); + assert_array_equals(actual, expected); + }, "getElementsByTagNameNS('*', 'body')") + + test(function() { + assert_array_equals(context.getElementsByTagNameNS("", "*"), []); + var t = element.appendChild(document.createElementNS("", "body")) + this.add_cleanup(function() {element.removeChild(t)}) + assert_array_equals(context.getElementsByTagNameNS("", "*"), [t]); + }, "Empty string namespace") + + test(function() { + var t = element.appendChild(document.createElementNS("test", "body")) + this.add_cleanup(function() {element.removeChild(t)}) + assert_array_equals(context.getElementsByTagNameNS("test", "body"), [t]); + }, "body element in test namespace, no prefix") + + test(function() { + var t = element.appendChild(document.createElementNS("test", "test:body")) + this.add_cleanup(function() {element.removeChild(t)}) + assert_array_equals(context.getElementsByTagNameNS("test", "body"), [t]); + }, "body element in test namespace, prefix") + + test(function() { + var t = element.appendChild(document.createElementNS("test", "BODY")) + this.add_cleanup(function() {element.removeChild(t)}) + assert_array_equals(context.getElementsByTagNameNS("test", "BODY"), [t]); + assert_array_equals(context.getElementsByTagNameNS("test", "body"), []); + }, "BODY element in test namespace, no prefix") + + test(function() { + var t = element.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "abc")) + this.add_cleanup(function() {element.removeChild(t)}) + assert_array_equals(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "abc"), [t]); + assert_array_equals(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "ABC"), []); + assert_array_equals(context.getElementsByTagNameNS("test", "ABC"), []); + }, "abc element in html namespace") + + test(function() { + var t = element.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "ABC")) + this.add_cleanup(function() {element.removeChild(t)}) + assert_array_equals(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "abc"), []); + assert_array_equals(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "ABC"), [t]); + }, "ABC element in html namespace") + + test(function() { + var t = element.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "AÇ")) + this.add_cleanup(function() {element.removeChild(t)}) + assert_array_equals(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "AÇ"), [t]); + assert_array_equals(context.getElementsByTagNameNS("test", "aÇ"), []); + assert_array_equals(context.getElementsByTagNameNS("test", "aç"), []); + }, "AÇ, case sensitivity") + + test(function() { + var t = element.appendChild(document.createElementNS("test", "test:BODY")) + this.add_cleanup(function() {element.removeChild(t)}) + assert_array_equals(context.getElementsByTagNameNS("test", "BODY"), [t]); + assert_array_equals(context.getElementsByTagNameNS("test", "body"), []); + }, "BODY element in test namespace, prefix") + + test(function() { + var t = element.appendChild(document.createElementNS("test", "test:test")) + this.add_cleanup(function() {element.removeChild(t)}) + var actual = context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "*"); + var expected = []; + var get_elements = function(node) { + for (var i = 0; i < node.childNodes.length; i++) { + var child = node.childNodes[i]; + if (child.nodeType === child.ELEMENT_NODE) { + if (child !== t) { + expected.push(child); + } + get_elements(child); + } + } + } + get_elements(context); + assert_array_equals(actual, expected); + }, "getElementsByTagNameNS('http://www.w3.org/1999/xhtml', '*')") + + test(function() { + var actual = context.getElementsByTagNameNS("*", "*"); + var expected = []; + var get_elements = function(node) { + for (var i = 0; i < node.childNodes.length; i++) { + var child = node.childNodes[i]; + if (child.nodeType === child.ELEMENT_NODE) { + expected.push(child); + get_elements(child); + } + } + } + get_elements(context); + assert_array_equals(actual, expected); + }, "getElementsByTagNameNS('*', '*')") + + test(function() { + assert_array_equals(context.getElementsByTagNameNS("**", "*"), []); + assert_array_equals(context.getElementsByTagNameNS(null, "0"), []); + assert_array_equals(context.getElementsByTagNameNS(null, "div"), []); + }, "Empty lists") +} diff --git a/testing/web-platform/tests/dom/nodes/Document-URL.sub.html b/testing/web-platform/tests/dom/nodes/Document-URL.sub.html new file mode 100644 index 000000000..8e9601107 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-URL.sub.html @@ -0,0 +1,18 @@ +<!doctype html> +<meta charset=utf-8> +<title>Document.URL with redirect</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var iframe = document.createElement("iframe"); + iframe.src = "/common/redirect.py?location=/common/blank.html"; + document.body.appendChild(iframe); + this.add_cleanup(function() { document.body.removeChild(iframe); }); + iframe.onload = this.step_func_done(function() { + assert_equals(iframe.contentDocument.URL, + "http://{{host}}:{{ports[http][0]}}/common/blank.html"); + }); +}) +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-adoptNode.html b/testing/web-platform/tests/dom/nodes/Document-adoptNode.html new file mode 100644 index 000000000..584d5d9fe --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-adoptNode.html @@ -0,0 +1,50 @@ +<!doctype html> +<meta charset=utf-8> +<title>Document.adoptNode</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-adoptnode"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<!--creates an element with local name "x<": --><x<>x</x<> +<script> +test(function() { + var y = document.getElementsByTagName("x<")[0] + var child = y.firstChild + assert_equals(y.parentNode, document.body) + assert_equals(y.ownerDocument, document) + assert_equals(document.adoptNode(y), y) + assert_equals(y.parentNode, null) + assert_equals(y.firstChild, child) + assert_equals(y.ownerDocument, document) + assert_equals(child.ownerDocument, document) + var doc = document.implementation.createDocument(null, null, null) + assert_equals(doc.adoptNode(y), y) + assert_equals(y.parentNode, null) + assert_equals(y.firstChild, child) + assert_equals(y.ownerDocument, doc) + assert_equals(child.ownerDocument, doc) +}, "Adopting an Element called 'x<' should work.") + +test(function() { + var x = document.createElement(":good:times:") + assert_equals(document.adoptNode(x), x); + var doc = document.implementation.createDocument(null, null, null) + assert_equals(doc.adoptNode(x), x) + assert_equals(x.parentNode, null) + assert_equals(x.ownerDocument, doc) +}, "Adopting an Element called ':good:times:' should work.") + +test(function() { + var doctype = document.doctype; + assert_equals(doctype.parentNode, document) + assert_equals(doctype.ownerDocument, document) + assert_equals(document.adoptNode(doctype), doctype) + assert_equals(doctype.parentNode, null) + assert_equals(doctype.ownerDocument, document) +}, "Explicitly adopting a DocumentType should work.") + +test(function() { + var doc = document.implementation.createDocument(null, null, null) + assert_throws("NOT_SUPPORTED_ERR", function() { document.adoptNode(doc) }) +}, "Adopting a Document should throw.") +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-characterSet-normalization.html b/testing/web-platform/tests/dom/nodes/Document-characterSet-normalization.html new file mode 100644 index 000000000..746792fb7 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-characterSet-normalization.html @@ -0,0 +1,373 @@ +<!doctype html> +<title>document.characterSet (inputEncoding and charset as aliases) normalization tests</title> +<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name> +<meta name=timeout content=long> +<div id=log></div> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<style>iframe { display: none }</style> +<script> +"use strict"; + +// Taken straight from https://encoding.spec.whatwg.org/ +var encodingMap = { + "UTF-8": [ + "unicode-1-1-utf-8", + "utf-8", + "utf8", + // As we use <meta>, utf-16 will map to utf-8 per + // https://html.spec.whatwg.org/multipage/#documentEncoding + "utf-16", + "utf-16le", + "utf-16be", + ], + "IBM866": [ + "866", + "cp866", + "csibm866", + "ibm866", + ], + "ISO-8859-2": [ + "csisolatin2", + "iso-8859-2", + "iso-ir-101", + "iso8859-2", + "iso88592", + "iso_8859-2", + "iso_8859-2:1987", + "l2", + "latin2", + ], + "ISO-8859-3": [ + "csisolatin3", + "iso-8859-3", + "iso-ir-109", + "iso8859-3", + "iso88593", + "iso_8859-3", + "iso_8859-3:1988", + "l3", + "latin3", + ], + "ISO-8859-4": [ + "csisolatin4", + "iso-8859-4", + "iso-ir-110", + "iso8859-4", + "iso88594", + "iso_8859-4", + "iso_8859-4:1988", + "l4", + "latin4", + ], + "ISO-8859-5": [ + "csisolatincyrillic", + "cyrillic", + "iso-8859-5", + "iso-ir-144", + "iso8859-5", + "iso88595", + "iso_8859-5", + "iso_8859-5:1988", + ], + "ISO-8859-6": [ + "arabic", + "asmo-708", + "csiso88596e", + "csiso88596i", + "csisolatinarabic", + "ecma-114", + "iso-8859-6", + "iso-8859-6-e", + "iso-8859-6-i", + "iso-ir-127", + "iso8859-6", + "iso88596", + "iso_8859-6", + "iso_8859-6:1987", + ], + "ISO-8859-7": [ + "csisolatingreek", + "ecma-118", + "elot_928", + "greek", + "greek8", + "iso-8859-7", + "iso-ir-126", + "iso8859-7", + "iso88597", + "iso_8859-7", + "iso_8859-7:1987", + "sun_eu_greek", + ], + "ISO-8859-8": [ + "csiso88598e", + "csisolatinhebrew", + "hebrew", + "iso-8859-8", + "iso-8859-8-e", + "iso-ir-138", + "iso8859-8", + "iso88598", + "iso_8859-8", + "iso_8859-8:1988", + "visual", + ], + "ISO-8859-8-I": [ + "csiso88598i", + "iso-8859-8-i", + "logical", + ], + "ISO-8859-10": [ + "csisolatin6", + "iso-8859-10", + "iso-ir-157", + "iso8859-10", + "iso885910", + "l6", + "latin6", + ], + "ISO-8859-13": [ + "iso-8859-13", + "iso8859-13", + "iso885913", + ], + "ISO-8859-14": [ + "iso-8859-14", + "iso8859-14", + "iso885914", + ], + "ISO-8859-15": [ + "csisolatin9", + "iso-8859-15", + "iso8859-15", + "iso885915", + "iso_8859-15", + "l9", + ], + "ISO-8859-16": [ + "iso-8859-16", + ], + "KOI8-R": [ + "cskoi8r", + "koi", + "koi8", + "koi8-r", + "koi8_r", + ], + "KOI8-U": [ + "koi8-ru", + "koi8-u", + ], + "macintosh": [ + "csmacintosh", + "mac", + "macintosh", + "x-mac-roman", + ], + "windows-874": [ + "dos-874", + "iso-8859-11", + "iso8859-11", + "iso885911", + "tis-620", + "windows-874", + ], + "windows-1250": [ + "cp1250", + "windows-1250", + "x-cp1250", + ], + "windows-1251": [ + "cp1251", + "windows-1251", + "x-cp1251", + ], + "windows-1252": [ + "ansi_x3.4-1968", + "ascii", + "cp1252", + "cp819", + "csisolatin1", + "ibm819", + "iso-8859-1", + "iso-ir-100", + "iso8859-1", + "iso88591", + "iso_8859-1", + "iso_8859-1:1987", + "l1", + "latin1", + "us-ascii", + "windows-1252", + "x-cp1252", + // As we use <meta>, x-user-defined will map to windows-1252 per + // https://html.spec.whatwg.org/multipage/#documentEncoding + "x-user-defined" + ], + "windows-1253": [ + "cp1253", + "windows-1253", + "x-cp1253", + ], + "windows-1254": [ + "cp1254", + "csisolatin5", + "iso-8859-9", + "iso-ir-148", + "iso8859-9", + "iso88599", + "iso_8859-9", + "iso_8859-9:1989", + "l5", + "latin5", + "windows-1254", + "x-cp1254", + ], + "windows-1255": [ + "cp1255", + "windows-1255", + "x-cp1255", + ], + "windows-1256": [ + "cp1256", + "windows-1256", + "x-cp1256", + ], + "windows-1257": [ + "cp1257", + "windows-1257", + "x-cp1257", + ], + "windows-1258": [ + "cp1258", + "windows-1258", + "x-cp1258", + ], + "x-mac-cyrillic": [ + "x-mac-cyrillic", + "x-mac-ukrainian", + ], + "GBK": [ + "chinese", + "csgb2312", + "csiso58gb231280", + "gb2312", + "gb_2312", + "gb_2312-80", + "gbk", + "iso-ir-58", + "x-gbk", + ], + "gb18030": [ + "gb18030", + ], + "Big5": [ + "big5", + "big5-hkscs", + "cn-big5", + "csbig5", + "x-x-big5", + ], + "EUC-JP": [ + "cseucpkdfmtjapanese", + "euc-jp", + "x-euc-jp", + ], + "ISO-2022-JP": [ + "csiso2022jp", + "iso-2022-jp", + ], + "Shift_JIS": [ + "csshiftjis", + "ms932", + "ms_kanji", + "shift-jis", + "shift_jis", + "sjis", + "windows-31j", + "x-sjis", + ], + "EUC-KR": [ + "cseuckr", + "csksc56011987", + "euc-kr", + "iso-ir-149", + "korean", + "ks_c_5601-1987", + "ks_c_5601-1989", + "ksc5601", + "ksc_5601", + "windows-949", + ], + "replacement": [ + "csiso2022kr", + "hz-gb-2312", + "iso-2022-cn", + "iso-2022-cn-ext", + "iso-2022-kr", + ], +}; + +// Add spaces and mix up case +Object.keys(encodingMap).forEach(function(name) { + var lower = encodingMap[name]; + var upper = encodingMap[name].map(function(s) { return s.toUpperCase() }); + var mixed = encodingMap[name].map(function(s) { + var ret = ""; + for (var i = 0; i < s.length; i += 2) { + ret += s[i].toUpperCase(); + if (i + 1 < s.length) { + ret += s[i + 1]; + } + } + return ret; + }); + var spacey = encodingMap[name].map(function(s) { + return " \t\n\f\r" + s + " \t\n\f\r"; + }); + encodingMap[name] = []; + for (var i = 0; i < lower.length; i++) { + encodingMap[name].push(lower[i]); + /* + if (lower[i] != upper[i]) { + encodingMap[name].push(upper[i]); + } + if (lower[i] != mixed[i] && upper[i] != mixed[i]) { + encodingMap[name].push(mixed[i]); + } + encodingMap[name].push(spacey[i]); + */ + } +}); + +Object.keys(encodingMap).forEach(function(name) { + encodingMap[name].forEach(function(label) { + var iframe = document.createElement("iframe"); + var t = async_test("Name " + format_value(name) + + " has label " + format_value(label) + " (characterSet)"); + var t2 = async_test("Name " + format_value(name) + + " has label " + format_value(label) + " (inputEncoding)"); + var t3 = async_test("Name " + format_value(name) + + " has label " + format_value(label) + " (charset)"); + iframe.src = "encoding.py?label=" + label; + iframe.onload = function() { + t.step(function() { + assert_equals(iframe.contentDocument.characterSet, name); + }); + t2.step(function() { + assert_equals(iframe.contentDocument.inputEncoding, name); + }); + t3.step(function() { + assert_equals(iframe.contentDocument.charset, name); + }); + document.body.removeChild(iframe); + t.done(); + t2.done(); + t3.done(); + }; + document.body.appendChild(iframe); + }); +}); +</script> +<!-- vim: set expandtab tabstop=2 shiftwidth=2: --> diff --git a/testing/web-platform/tests/dom/nodes/Document-constructor.html b/testing/web-platform/tests/dom/nodes/Document-constructor.html new file mode 100644 index 000000000..11549da4a --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-constructor.html @@ -0,0 +1,53 @@ +<!doctype html> +<meta charset=windows-1252> +<!-- Using windows-1252 to ensure that new Document() doesn't inherit utf-8 + from the parent document. --> +<title>Document constructor</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + var doc = new Document(); + assert_true(doc instanceof Node, "Should be a Node"); + assert_true(doc instanceof Document, "Should be a Document"); + assert_false(doc instanceof XMLDocument, "Should not be an XMLDocument"); + assert_equals(Object.getPrototypeOf(doc), Document.prototype, + "Document should be the primary interface"); +}, "new Document(): interfaces") + +test(function() { + var doc = new Document(); + assert_equals(doc.firstChild, null, "firstChild"); + assert_equals(doc.lastChild, null, "lastChild"); + assert_equals(doc.doctype, null, "doctype"); + assert_equals(doc.documentElement, null, "documentElement"); + assert_array_equals(doc.childNodes, [], "childNodes"); +}, "new Document(): children") + +test(function() { + var doc = new Document(); + assert_equals(doc.URL, "about:blank"); + assert_equals(doc.documentURI, "about:blank"); + assert_equals(doc.compatMode, "CSS1Compat"); + assert_equals(doc.characterSet, "UTF-8"); + assert_equals(doc.contentType, "application/xml"); + assert_equals(doc.createElement("DIV").localName, "DIV"); +}, "new Document(): metadata") + +test(function() { + var doc = new Document(); + assert_equals(doc.characterSet, "UTF-8", "characterSet"); + assert_equals(doc.charset, "UTF-8", "charset"); + assert_equals(doc.inputEncoding, "UTF-8", "inputEncoding"); +}, "new Document(): characterSet aliases") + +test(function() { + var doc = new Document(); + var a = doc.createElement("a"); + // In UTF-8: 0xC3 0xA4 + a.href = "http://example.org/?\u00E4"; + assert_equals(a.href, "http://example.org/?%C3%A4"); +}, "new Document(): URL parsing") +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_bmp.html b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_bmp.html new file mode 100644 index 000000000..828643741 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_bmp.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>BMP document.contentType === 'image/bmp'</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var iframe = document.createElement('iframe'); + iframe.addEventListener('load', this.step_func_done(function() { + assert_equals(iframe.contentDocument.contentType, "image/bmp"); + }), false); + iframe.src = "../resources/t.bmp"; + document.body.appendChild(iframe); +}); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_css.html b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_css.html new file mode 100644 index 000000000..0eb35edd5 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_css.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>CSS document.contentType === 'text/css'</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var iframe = document.createElement('iframe'); + iframe.addEventListener('load', this.step_func_done(function() { + assert_equals(iframe.contentDocument.contentType, "text/css"); + }), false); + iframe.src = "../resources/style.css"; + document.body.appendChild(iframe); +}); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_01.html b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_01.html new file mode 100644 index 000000000..79c63644d --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_01.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>Data URI document.contentType === 'text/plain' when data URI MIME type is not set</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var iframe = document.createElement('iframe'); + iframe.addEventListener('load', this.step_func_done(function() { + assert_equals(iframe.contentDocument.contentType, "text/plain"); + }), false); + iframe.src = "data:;,<!DOCTYPE html>"; + document.body.appendChild(iframe); +}); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_02.html b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_02.html new file mode 100644 index 000000000..2e82c7c1f --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_02.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>Data URI document.contentType === 'text/html' when data URI MIME type is set</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var iframe = document.createElement('iframe'); + iframe.addEventListener('load', this.step_func_done(function() { + assert_equals(iframe.contentDocument.contentType, "text/html"); + }), false); + iframe.src = "data:text/html;charset=utf-8,<!DOCTYPE html>"; + document.body.appendChild(iframe); +}); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_gif.html b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_gif.html new file mode 100644 index 000000000..8dd66dae5 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_gif.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>GIF document.contentType === 'image/gif'</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var iframe = document.createElement('iframe'); + iframe.addEventListener('load', this.step_func_done(function() { + assert_equals(iframe.contentDocument.contentType, "image/gif"); + }), false); + iframe.src = "../resources/t.gif"; + document.body.appendChild(iframe); +}); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_html.html b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_html.html new file mode 100644 index 000000000..2b2d7263e --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_html.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>HTM document.contentType === 'text/html'</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var iframe = document.createElement('iframe'); + iframe.addEventListener('load', this.step_func_done(function() { + assert_equals(iframe.contentDocument.contentType, "text/html"); + }), false); + iframe.src = "../resources/blob.htm"; + document.body.appendChild(iframe); +}); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_javascripturi.html b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_javascripturi.html new file mode 100644 index 000000000..956589615 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_javascripturi.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<title>Javascript URI document.contentType === 'text/html'</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var iframe = document.createElement('iframe'); + iframe.addEventListener('load', this.step_func_done(function() { + assert_equals(iframe.contentDocument.contentType, "text/html"); + assert_equals(iframe.contentDocument.documentElement.textContent, "text/html"); + }), false); + iframe.src = "javascript:document.contentType"; + document.body.appendChild(iframe); +}); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_jpg.html b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_jpg.html new file mode 100644 index 000000000..13f57ec8b --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_jpg.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>JPG document.contentType === 'image/jpeg'</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var iframe = document.createElement('iframe'); + iframe.addEventListener('load', this.step_func_done(function() { + assert_equals(iframe.contentDocument.contentType, "image/jpeg"); + }), false); + iframe.src = "../resources/t.jpg"; + document.body.appendChild(iframe); +}); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_01.html b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_01.html new file mode 100644 index 000000000..87885efba --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_01.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>Custom document.contentType === 'text/xml' when explicitly set to this value</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var iframe = document.createElement('iframe'); + iframe.addEventListener('load', this.step_func_done(function() { + assert_equals(iframe.contentDocument.contentType, "text/xml"); + }), false); + iframe.src = "../support/contenttype_setter.py?type=text&subtype=xml"; + document.body.appendChild(iframe); +}); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_02.html b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_02.html new file mode 100644 index 000000000..33870147f --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_02.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>Custom document.contentType === 'text/html' when explicitly set to this value and an attempt is made to override this value in an HTML meta header</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var iframe = document.createElement('iframe'); + iframe.addEventListener('load', this.step_func_done(function() { + assert_equals(iframe.contentDocument.contentType, "text/html"); + }), false); + iframe.src = "../support/contenttype_setter.py?type=text&subtype=html&mimeHead=text%2Fxml"; + document.body.appendChild(iframe); +}); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_png.html b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_png.html new file mode 100644 index 000000000..a214ad3e9 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_png.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>PNG document.contentType === 'image/png'</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var iframe = document.createElement('iframe'); + iframe.addEventListener('load', this.step_func_done(function() { + assert_equals(iframe.contentDocument.contentType, "image/png"); + }), false); + iframe.src = "../resources/t.png"; + document.body.appendChild(iframe); +}); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_txt.html b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_txt.html new file mode 100644 index 000000000..f40f641fb --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_txt.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>TXT document.contentType === 'text/plain'</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var iframe = document.createElement('iframe'); + iframe.addEventListener('load', this.step_func_done(function() { + assert_equals(iframe.contentDocument.contentType, "text/plain"); + }), false); + iframe.src = "../resources/blob.txt"; + document.body.appendChild(iframe); +}); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_xml.html b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_xml.html new file mode 100644 index 000000000..c382de849 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/contenttype_xml.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>XML document.contentType === 'application/xml'</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var iframe = document.createElement('iframe'); + iframe.addEventListener('load', this.step_func_done(function() { + assert_equals(iframe.contentDocument.contentType, "application/xml"); + }), false); + iframe.src = "../resources/blob.xml"; + document.body.appendChild(iframe); +}); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/createDocument.html b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/createDocument.html new file mode 100644 index 000000000..78a952de4 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/createDocument.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<title>document.implementation.createDocument: document.contentType === 'application/xhtml+xml'</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +test(function() { + var doc = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", null); + assert_equals(doc.contentType, "application/xhtml+xml"); +}); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/createHTMLDocument.html b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/createHTMLDocument.html new file mode 100644 index 000000000..185e3c8c9 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/createHTMLDocument.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<title>document.implementation.createHTMLDocument: document.contentType === 'text/html'</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +test(function() { + var doc = document.implementation.createHTMLDocument("test"); + assert_equals(doc.contentType, "text/html"); +}); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/xhr_responseType_document.html b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/xhr_responseType_document.html new file mode 100644 index 000000000..c2fb6c19f --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/contentType/xhr_responseType_document.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<title>XHR - retrieve HTML document: document.contentType === 'application/xml'</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +async_test(function() { + var xhr = new XMLHttpRequest(); + xhr.open("GET", "../resources/blob.xml"); + xhr.responseType = "document"; + xhr.onload = this.step_func_done(function(response) { + assert_equals(xhr.readyState, 4); + assert_equals(xhr.status, 200); + assert_equals(xhr.responseXML.contentType, "application/xml"); + }); + xhr.send(null); +}); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/resources/blob.htm b/testing/web-platform/tests/dom/nodes/Document-contentType/resources/blob.htm new file mode 100644 index 000000000..9d235ed07 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/resources/blob.htm @@ -0,0 +1 @@ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/resources/blob.txt b/testing/web-platform/tests/dom/nodes/Document-contentType/resources/blob.txt new file mode 100644 index 000000000..9d235ed07 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/resources/blob.txt @@ -0,0 +1 @@ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/resources/blob.xml b/testing/web-platform/tests/dom/nodes/Document-contentType/resources/blob.xml new file mode 100644 index 000000000..0922ed14b --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/resources/blob.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<blob>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</blob>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/resources/lib.js b/testing/web-platform/tests/dom/nodes/Document-contentType/resources/lib.js new file mode 100644 index 000000000..c41d336c0 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/resources/lib.js @@ -0,0 +1 @@ +var t;
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/resources/style.css b/testing/web-platform/tests/dom/nodes/Document-contentType/resources/style.css new file mode 100644 index 000000000..bb4ff575b --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/resources/style.css @@ -0,0 +1,12 @@ +.unknown +{ + background-color:lightblue; +} +.pass +{ + background-color:lime; +} +.fail +{ + background-color:red; +} diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/resources/t.bmp b/testing/web-platform/tests/dom/nodes/Document-contentType/resources/t.bmp Binary files differnew file mode 100644 index 000000000..5697c0aef --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/resources/t.bmp diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/resources/t.gif b/testing/web-platform/tests/dom/nodes/Document-contentType/resources/t.gif Binary files differnew file mode 100644 index 000000000..91f269207 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/resources/t.gif diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/resources/t.jpg b/testing/web-platform/tests/dom/nodes/Document-contentType/resources/t.jpg Binary files differnew file mode 100644 index 000000000..72b51899e --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/resources/t.jpg diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/resources/t.png b/testing/web-platform/tests/dom/nodes/Document-contentType/resources/t.png Binary files differnew file mode 100644 index 000000000..447d9e301 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/resources/t.png diff --git a/testing/web-platform/tests/dom/nodes/Document-contentType/support/contenttype_setter.py b/testing/web-platform/tests/dom/nodes/Document-contentType/support/contenttype_setter.py new file mode 100644 index 000000000..02eff653c --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-contentType/support/contenttype_setter.py @@ -0,0 +1,20 @@ +def main(request, response): + type = request.GET.first("type", None) + subtype = request.GET.first("subtype", None) + if type and subtype: + response.headers["Content-Type"] = type + "/" + subtype + + removeContentType = request.GET.first("removeContentType", None) + if removeContentType: + try: + del response.headers["Content-Type"] + except KeyError: + pass + + content = '<head>' + mimeHead = request.GET.first("mime", None); + if mimeHead: + content += '<meta http-equiv="Content-Type" content="%s; charset=utf-8"/>' % mimeHead + content += "</head>" + + return content diff --git a/testing/web-platform/tests/dom/nodes/Document-createAttribute.html b/testing/web-platform/tests/dom/nodes/Document-createAttribute.html new file mode 100644 index 000000000..b5afa6ed7 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createAttribute.html @@ -0,0 +1,43 @@ +<!doctype html> +<meta charset=utf-8> +<title>Document.createAttribute</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=attributes.js></script> +<script src=productions.js></script> +<div id=log> +<script> +var xml_document; +setup(function() { + xml_document = document.implementation.createDocument(null, null, null); +}); + +invalid_names.forEach(function(name) { + test(function() { + assert_throws("INVALID_CHARACTER_ERR", function() { + document.createAttribute(name, "test"); + }); + }, "HTML document.createAttribute(" + format_value(name) + ")"); + + test(function() { + assert_throws("INVALID_CHARACTER_ERR", function() { + xml_document.createAttribute(name, "test"); + }); + }, "XML document.createAttribute(" + format_value(name) + ")"); +}); + +var tests = ["title", "TITLE", null, undefined]; +tests.forEach(function(name) { + test(function() { + var attribute = document.createAttribute(name); + attr_is(attribute, "", String(name).toLowerCase(), null, null, String(name).toLowerCase()); + assert_equals(attribute.ownerElement, null); + }, "HTML document.createAttribute(" + format_value(name) + ")"); + + test(function() { + var attribute = xml_document.createAttribute(name); + attr_is(attribute, "", String(name), null, null, String(name)); + assert_equals(attribute.ownerElement, null); + }, "XML document.createAttribute(" + format_value(name) + ")"); +}); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-createComment-createTextNode.js b/testing/web-platform/tests/dom/nodes/Document-createComment-createTextNode.js new file mode 100644 index 000000000..62a38d380 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createComment-createTextNode.js @@ -0,0 +1,22 @@ +function test_create(method, iface, nodeType, nodeName) { + ["\u000b", "a -- b", "a-", "-b", null, undefined].forEach(function(value) { + test(function() { + var c = document[method](value); + var expected = String(value); + assert_true(c instanceof iface); + assert_true(c instanceof CharacterData); + assert_true(c instanceof Node); + assert_equals(c.ownerDocument, document); + assert_equals(c.data, expected, "data"); + assert_equals(c.nodeValue, expected, "nodeValue"); + assert_equals(c.textContent, expected, "textContent"); + assert_equals(c.length, expected.length); + assert_equals(c.nodeType, nodeType); + assert_equals(c.nodeName, nodeName); + assert_equals(c.hasChildNodes(), false); + assert_equals(c.childNodes.length, 0); + assert_equals(c.firstChild, null); + assert_equals(c.lastChild, null); + }, method + "(" + format_value(value) + ")"); + }); +} diff --git a/testing/web-platform/tests/dom/nodes/Document-createComment.html b/testing/web-platform/tests/dom/nodes/Document-createComment.html new file mode 100644 index 000000000..a175c3a2f --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createComment.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Document.createComment</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createcomment"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-ownerdocument"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodevalue"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-textcontent"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-length"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodetype"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-haschildnodes"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-childnodes"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-firstchild"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-lastchild"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="Document-createComment-createTextNode.js"></script> +<div id="log"></div> +<script> +test_create("createComment", Comment, 8, "#comment"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.html b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.html new file mode 100644 index 000000000..b80a99a78 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.html @@ -0,0 +1 @@ +<math></math>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.svg b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.svg new file mode 100644 index 000000000..b80a99a78 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.svg @@ -0,0 +1 @@ +<math></math>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.xhtml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.xhtml new file mode 100644 index 000000000..b80a99a78 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.xhtml @@ -0,0 +1 @@ +<math></math>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.xml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.xml new file mode 100644 index 000000000..b80a99a78 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.xml @@ -0,0 +1 @@ +<math></math>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.html b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.html new file mode 100644 index 000000000..dc1ced5b6 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.html @@ -0,0 +1 @@ +<svg></svg>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.svg b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.svg new file mode 100644 index 000000000..dc1ced5b6 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.svg @@ -0,0 +1 @@ +<svg></svg>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.xhtml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.xhtml new file mode 100644 index 000000000..dc1ced5b6 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.xhtml @@ -0,0 +1 @@ +<svg></svg>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.xml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.xml new file mode 100644 index 000000000..dc1ced5b6 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.xml @@ -0,0 +1 @@ +<svg></svg>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.html b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.html new file mode 100644 index 000000000..6c70bcfe4 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.html @@ -0,0 +1 @@ +<html></html>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.svg b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.svg new file mode 100644 index 000000000..6c70bcfe4 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.svg @@ -0,0 +1 @@ +<html></html>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.xhtml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.xhtml new file mode 100644 index 000000000..6c70bcfe4 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.xhtml @@ -0,0 +1 @@ +<html></html>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.xml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.xml new file mode 100644 index 000000000..6c70bcfe4 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.xml @@ -0,0 +1 @@ +<html></html>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/empty.html b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/empty.html new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/empty.html diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/empty.svg b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/empty.svg new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/empty.svg diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/empty.xhtml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/empty.xhtml new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/empty.xhtml diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/empty.xml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/empty.xml new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/empty.xml diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/generate.py b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/generate.py new file mode 100755 index 000000000..88c4da198 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/generate.py @@ -0,0 +1,77 @@ +#!/usr/bin/python +import os +import sys + +THIS_NAME = "generate.py" + +# Note: these lists must be kept in sync with the lists in +# Document-createElement-namespace.html, and this script must be run whenever +# the lists are updated. (We could keep the lists in a shared JSON file, but +# seems like too much effort.) +FILES = ( + ("empty", ""), + ("minimal_html", "<!doctype html><title></title>"), + + ("xhtml", '<html xmlns="http://www.w3.org/1999/xhtml"></html>'), + ("svg", '<svg xmlns="http://www.w3.org/2000/svg"></svg>'), + ("mathml", '<mathml xmlns="http://www.w3.org/1998/Math/MathML"></mathml>'), + + ("bare_xhtml", "<html></html>"), + ("bare_svg", "<svg></svg>"), + ("bare_mathml", "<math></math>"), + + ("xhtml_ns_removed", """\ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head><script> + var newRoot = document.createElementNS(null, "html"); + document.removeChild(document.documentElement); + document.appendChild(newRoot); + </script></head> +</html> +"""), + ("xhtml_ns_changed", """\ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head><script> + var newRoot = document.createElementNS("http://www.w3.org/2000/svg", "abc"); + document.removeChild(document.documentElement); + document.appendChild(newRoot); + </script></head> +</html> +"""), +) + +EXTENSIONS = ( + "html", + "xhtml", + "xml", + "svg", + # Was not able to get server MIME type working properly :( + #"mml", +) + +def __main__(): + if len(sys.argv) > 1: + print "No arguments expected, aborting" + return + + if not os.access(THIS_NAME, os.F_OK): + print "Must be run from the directory of " + THIS_NAME + ", aborting" + return + + for name in os.listdir("."): + if name == THIS_NAME: + continue + os.remove(name) + + manifest = open("MANIFEST", "w") + + for name, contents in FILES: + for extension in EXTENSIONS: + f = open(name + "." + extension, "w") + f.write(contents) + f.close() + manifest.write("support " + name + "." + extension + "\n") + + manifest.close() + +__main__() diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/mathml.html b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/mathml.html new file mode 100644 index 000000000..0bec8e99e --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/mathml.html @@ -0,0 +1 @@ +<mathml xmlns="http://www.w3.org/1998/Math/MathML"></mathml>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/mathml.svg b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/mathml.svg new file mode 100644 index 000000000..0bec8e99e --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/mathml.svg @@ -0,0 +1 @@ +<mathml xmlns="http://www.w3.org/1998/Math/MathML"></mathml>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/mathml.xhtml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/mathml.xhtml new file mode 100644 index 000000000..0bec8e99e --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/mathml.xhtml @@ -0,0 +1 @@ +<mathml xmlns="http://www.w3.org/1998/Math/MathML"></mathml>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/mathml.xml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/mathml.xml new file mode 100644 index 000000000..0bec8e99e --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/mathml.xml @@ -0,0 +1 @@ +<mathml xmlns="http://www.w3.org/1998/Math/MathML"></mathml>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.html b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.html new file mode 100644 index 000000000..a33d9859a --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.html @@ -0,0 +1 @@ +<!doctype html><title></title>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.svg b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.svg new file mode 100644 index 000000000..a33d9859a --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.svg @@ -0,0 +1 @@ +<!doctype html><title></title>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.xhtml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.xhtml new file mode 100644 index 000000000..a33d9859a --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.xhtml @@ -0,0 +1 @@ +<!doctype html><title></title>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.xml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.xml new file mode 100644 index 000000000..a33d9859a --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.xml @@ -0,0 +1 @@ +<!doctype html><title></title>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/svg.html b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/svg.html new file mode 100644 index 000000000..64def4af7 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/svg.html @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg"></svg>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/svg.svg b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/svg.svg new file mode 100644 index 000000000..64def4af7 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/svg.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg"></svg>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/svg.xhtml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/svg.xhtml new file mode 100644 index 000000000..64def4af7 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/svg.xhtml @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg"></svg>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/svg.xml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/svg.xml new file mode 100644 index 000000000..64def4af7 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/svg.xml @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg"></svg>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml.html b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml.html new file mode 100644 index 000000000..1cba99824 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml.html @@ -0,0 +1 @@ +<html xmlns="http://www.w3.org/1999/xhtml"></html>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml.svg b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml.svg new file mode 100644 index 000000000..1cba99824 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml.svg @@ -0,0 +1 @@ +<html xmlns="http://www.w3.org/1999/xhtml"></html>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml.xhtml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml.xhtml new file mode 100644 index 000000000..1cba99824 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml.xhtml @@ -0,0 +1 @@ +<html xmlns="http://www.w3.org/1999/xhtml"></html>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml.xml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml.xml new file mode 100644 index 000000000..1cba99824 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml.xml @@ -0,0 +1 @@ +<html xmlns="http://www.w3.org/1999/xhtml"></html>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.html b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.html new file mode 100644 index 000000000..b228c7f74 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.html @@ -0,0 +1,7 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head><script> + var newRoot = document.createElementNS("http://www.w3.org/2000/svg", "abc"); + document.removeChild(document.documentElement); + document.appendChild(newRoot); + </script></head> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.svg b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.svg new file mode 100644 index 000000000..b228c7f74 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.svg @@ -0,0 +1,7 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head><script> + var newRoot = document.createElementNS("http://www.w3.org/2000/svg", "abc"); + document.removeChild(document.documentElement); + document.appendChild(newRoot); + </script></head> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.xhtml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.xhtml new file mode 100644 index 000000000..b228c7f74 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.xhtml @@ -0,0 +1,7 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head><script> + var newRoot = document.createElementNS("http://www.w3.org/2000/svg", "abc"); + document.removeChild(document.documentElement); + document.appendChild(newRoot); + </script></head> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.xml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.xml new file mode 100644 index 000000000..b228c7f74 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.xml @@ -0,0 +1,7 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head><script> + var newRoot = document.createElementNS("http://www.w3.org/2000/svg", "abc"); + document.removeChild(document.documentElement); + document.appendChild(newRoot); + </script></head> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.html b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.html new file mode 100644 index 000000000..dba395fed --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.html @@ -0,0 +1,7 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head><script> + var newRoot = document.createElementNS(null, "html"); + document.removeChild(document.documentElement); + document.appendChild(newRoot); + </script></head> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.svg b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.svg new file mode 100644 index 000000000..dba395fed --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.svg @@ -0,0 +1,7 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head><script> + var newRoot = document.createElementNS(null, "html"); + document.removeChild(document.documentElement); + document.appendChild(newRoot); + </script></head> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.xhtml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.xhtml new file mode 100644 index 000000000..dba395fed --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.xhtml @@ -0,0 +1,7 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head><script> + var newRoot = document.createElementNS(null, "html"); + document.removeChild(document.documentElement); + document.appendChild(newRoot); + </script></head> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.xml b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.xml new file mode 100644 index 000000000..dba395fed --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.xml @@ -0,0 +1,7 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head><script> + var newRoot = document.createElementNS(null, "html"); + document.removeChild(document.documentElement); + document.appendChild(newRoot); + </script></head> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement-namespace.html b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace.html new file mode 100644 index 000000000..add66bf9a --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement-namespace.html @@ -0,0 +1,119 @@ +<!doctype html> +<title>document.createElement() namespace tests</title> +<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name> +<div id=log></div> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script> +"use strict"; +/** + * This tests the namespace of elements created by the Document interface's + * createElement() method. See bug: + * https://www.w3.org/Bugs/Public/show_bug.cgi?id=19431 + */ + +/** + * Test that an element created using the Document object doc has the namespace + * that would be expected for the given contentType. + */ +function testDoc(doc, contentType) { + if (doc.contentType !== undefined) { + // Sanity check + assert_equals(doc.contentType, contentType, + "Wrong MIME type returned from doc.contentType"); + } + + var expectedNamespace = contentType == "text/html" || + contentType == "application/xhtml+xml" + ? "http://www.w3.org/1999/xhtml" : null; + + assert_equals(doc.createElement("x").namespaceURI, expectedNamespace); +} + +// First test various objects we create in JS +test(function() { + testDoc(document, "text/html") +}, "Created element's namespace in current document"); +test(function() { + testDoc(document.implementation.createHTMLDocument(""), "text/html"); +}, "Created element's namespace in created HTML document"); +test(function() { + testDoc(document.implementation.createDocument(null, "", null), + "application/xml"); +}, "Created element's namespace in created XML document"); +test(function() { + testDoc(document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", null), + "application/xhtml+xml"); +}, "Created element's namespace in created XHTML document"); +test(function() { + testDoc(document.implementation.createDocument("http://www.w3.org/2000/svg", "svg", null), + "image/svg+xml"); +}, "Created element's namespace in created SVG document"); +test(function() { + testDoc(document.implementation.createDocument("http://www.w3.org/1998/Math/MathML", "math", null), + "application/xml"); +}, "Created element's namespace in created MathML document"); + +// Second also test document created by DOMParser +test(function() { + testDoc(new DOMParser().parseFromString("", "text/html"), "text/html"); +}, "Created element's namespace in created HTML document by DOMParser ('text/html')"); +test(function() { + testDoc(new DOMParser().parseFromString("<root/>", "text/xml"), "text/xml"); +}, "Created element's namespace in created XML document by DOMParser ('text/xml')"); +test(function() { + testDoc(new DOMParser().parseFromString("<root/>", "application/xml"), "application/xml"); +}, "Created element's namespace in created XML document by DOMParser ('application/xml')"); +test(function() { + testDoc(new DOMParser().parseFromString("<html/>", "application/xhtml+xml"), "application/xhtml+xml"); +}, "Created element's namespace in created XHTML document by DOMParser ('application/xhtml+xml')"); +test(function() { + testDoc(new DOMParser().parseFromString("<math/>", "image/svg+xml"), "image/svg+xml"); +}, "Created element's namespace in created SVG document by DOMParser ('image/svg+xml')"); + +// Now for various externally-loaded files. Note: these lists must be kept +// synced with the lists in generate.py in the subdirectory, and that script +// must be run whenever the lists are updated. (We could keep the lists in a +// shared JSON file, but it seems like too much effort.) +var testExtensions = { + html: "text/html", + xhtml: "application/xhtml+xml", + xml: "application/xml", + svg: "image/svg+xml", + // Was not able to get server MIME type working properly :( + //mml: "application/mathml+xml", +}; + +var tests = [ + "empty", + "minimal_html", + + "xhtml", + "svg", + "mathml", + + "bare_xhtml", + "bare_svg", + "bare_mathml", + + "xhtml_ns_removed", + "xhtml_ns_changed", +]; + +tests.forEach(function(testName) { + Object.keys(testExtensions).forEach(function(ext) { + var iframe = document.createElement("iframe"); + iframe.src = "Document-createElement-namespace-tests/" + + testName + "." + ext; + var t = async_test("Created element's namespace in " + testName + "." + ext); + iframe.onload = function() { + t.step(function() { + testDoc(iframe.contentDocument, testExtensions[ext]); + }); + document.body.removeChild(iframe); + t.done(); + }; + document.body.appendChild(iframe); + }); +}); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-createElement.html b/testing/web-platform/tests/dom/nodes/Document-createElement.html new file mode 100644 index 000000000..bacaff0f6 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElement.html @@ -0,0 +1,157 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Document.createElement</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createelement"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-element-localname"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-element-tagname"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-element-prefix"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-element-namespaceuri"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<iframe src="/common/dummy.xml"></iframe> +<iframe src="/common/dummy.xhtml"></iframe> +<script> +function toASCIIUppercase(str) { + var diff = "a".charCodeAt(0) - "A".charCodeAt(0); + var res = ""; + for (var i = 0; i < str.length; ++i) { + if ("a" <= str[i] && str[i] <= "z") { + res += String.fromCharCode(str.charCodeAt(i) - diff); + } else { + res += str[i]; + } + } + return res; +} +function toASCIILowercase(str) { + var diff = "a".charCodeAt(0) - "A".charCodeAt(0); + var res = ""; + for (var i = 0; i < str.length; ++i) { + if ("A" <= str[i] && str[i] <= "Z") { + res += String.fromCharCode(str.charCodeAt(i) + diff); + } else { + res += str[i]; + } + } + return res; +} +var HTMLNS = "http://www.w3.org/1999/xhtml", + valid = [ + undefined, + null, + "foo", + "f1oo", + "foo1", + "f\u0BC6", + "foo\u0BC6", + ":", + ":foo", + "f:oo", + "foo:", + "f:o:o", + "f::oo", + "f::oo:", + "foo:0", + "foo:_", + // combining char after :, invalid QName but valid Name + "foo:\u0BC6", + "foo:foo\u0BC6", + "foo\u0BC6:foo", + "xml", + "xmlns", + "xmlfoo", + "xml:foo", + "xmlns:foo", + "xmlfoo:bar", + "svg", + "math", + "FOO", + // Test that non-ASCII chars don't get uppercased/lowercased + "mar\u212a", + "\u0130nput", + "\u0131nput", + ], + invalid = [ + "", + "1foo", + "1:foo", + "fo o", + "\u0BC6foo", + "}foo", + "f}oo", + "foo}", + "\ufffffoo", + "f\uffffoo", + "foo\uffff", + "<foo", + "foo>", + "<foo>", + "f<oo", + "-foo", + ".foo", + "\u0BC6", + ] + +var xmlIframe = document.querySelector('[src="/common/dummy.xml"]'); +var xhtmlIframe = document.querySelector('[src="/common/dummy.xhtml"]'); + +function getWin(desc) { + if (desc == "HTML document") { + return window; + } + if (desc == "XML document") { + assert_equals(xmlIframe.contentDocument.documentElement.textContent, + "Dummy XML document", "XML document didn't load"); + return xmlIframe.contentWindow; + } + if (desc == "XHTML document") { + assert_equals(xhtmlIframe.contentDocument.documentElement.textContent, + "Dummy XHTML document", "XHTML document didn't load"); + return xhtmlIframe.contentWindow; + } +} + + +valid.forEach(function(t) { + ["HTML document", "XML document", "XHTML document"].forEach(function(desc) { + async_test(function(testObj) { + window.addEventListener("load", function() { + testObj.step(function() { + var win = getWin(desc); + var doc = win.document; + var elt = doc.createElement(t) + assert_true(elt instanceof win.Element, "instanceof Element") + assert_true(elt instanceof win.Node, "instanceof Node") + assert_equals(elt.localName, + desc == "HTML document" ? toASCIILowercase(String(t)) + : String(t), + "localName") + assert_equals(elt.tagName, + desc == "HTML document" ? toASCIIUppercase(String(t)) + : String(t), + "tagName") + assert_equals(elt.prefix, null, "prefix") + assert_equals(elt.namespaceURI, + desc == "XML document" ? null : HTMLNS, "namespaceURI") + }); + testObj.done(); + }); + }, "createElement(" + format_value(t) + ") in " + desc); + }); +}); +invalid.forEach(function(arg) { + ["HTML document", "XML document", "XHTML document"].forEach(function(desc) { + async_test(function(testObj) { + window.addEventListener("load", function() { + testObj.step(function() { + var doc = getWin(desc).document; + assert_throws("InvalidCharacterError", + function() { doc.createElement(arg) }) + }); + testObj.done(); + }); + }, "createElement(" + format_value(arg) + ") in " + desc); + }); +}); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-createElementNS.html b/testing/web-platform/tests/dom/nodes/Document-createElementNS.html new file mode 100644 index 000000000..68341bcd4 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElementNS.html @@ -0,0 +1,226 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Document.createElementNS</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createelementns"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="Document-createElementNS.js"></script> +<div id="log"></div> +<iframe src="/common/dummy.xml"></iframe> +<iframe src="/common/dummy.xhtml"></iframe> +<script> +var tests = createElementNS_tests.concat([ + /* Arrays with three elements: + * the namespace argument + * the qualifiedName argument + * the expected exception, or null if none + */ + ["", "", "INVALID_CHARACTER_ERR"], + [null, null, null], + [null, "", "INVALID_CHARACTER_ERR"], + [undefined, null, null], + [undefined, "", "INVALID_CHARACTER_ERR"], + ["http://example.com/", null, null], + ["http://example.com/", "", "INVALID_CHARACTER_ERR"], + ["/", null, null], + ["/", "", "INVALID_CHARACTER_ERR"], + ["http://www.w3.org/XML/1998/namespace", null, null], + ["http://www.w3.org/XML/1998/namespace", "", "INVALID_CHARACTER_ERR"], + ["http://www.w3.org/2000/xmlns/", null, "NAMESPACE_ERR"], + ["http://www.w3.org/2000/xmlns/", "", "INVALID_CHARACTER_ERR"], + ["foo:", null, null], + ["foo:", "", "INVALID_CHARACTER_ERR"], +]) + +var xmlIframe = document.querySelector('[src="/common/dummy.xml"]'); +var xhtmlIframe = document.querySelector('[src="/common/dummy.xhtml"]'); + +function runTest(t, i, desc) { + async_test(function(testObj) { + window.addEventListener("load", function() { + testObj.step(function() { + var doc; + if (desc == "HTML document") { + doc = document; + } else if (desc == "XML document") { + doc = xmlIframe.contentDocument; + // Make sure we're testing the right document + assert_equals(doc.documentElement.textContent, "Dummy XML document"); + } else if (desc == "XHTML document") { + doc = xhtmlIframe.contentDocument; + assert_equals(doc.documentElement.textContent, "Dummy XHTML document"); + } + var namespace = t[0], qualifiedName = t[1], expected = t[2] + if (expected != null) { + assert_throws(expected, function() { doc.createElementNS(namespace, qualifiedName) }) + } else { + var element = doc.createElementNS(namespace, qualifiedName) + assert_not_equals(element, null) + assert_equals(element.nodeType, Node.ELEMENT_NODE) + assert_equals(element.nodeType, element.ELEMENT_NODE) + assert_equals(element.nodeValue, null) + assert_equals(element.ownerDocument, doc) + var qualified = String(qualifiedName), names = [] + if (qualified.indexOf(":") >= 0) { + names = qualified.split(":", 2) + } else { + names = [null, qualified] + } + assert_equals(element.prefix, names[0]) + assert_equals(element.localName, names[1]) + assert_equals(element.tagName, qualified) + assert_equals(element.nodeName, qualified) + assert_equals(element.namespaceURI, + namespace === undefined || namespace === "" ? null + : namespace) + } + }); + testObj.done(); + }); + }, "createElementNS test in " + desc + ": " + t.map(format_value)) +} + +tests.forEach(function(t, i) { + runTest(t, i, "HTML document") + runTest(t, i, "XML document") + runTest(t, i, "XHTML document") +}) + + +test(function() { + var HTMLNS = "http://www.w3.org/1999/xhtml"; + var element = document.createElementNS(HTMLNS, "span"); + assert_equals(element.namespaceURI, HTMLNS); + assert_equals(element.prefix, null); + assert_equals(element.localName, "span"); + assert_equals(element.tagName, "SPAN"); + assert_true(element instanceof Node, "Should be a Node"); + assert_true(element instanceof Element, "Should be an Element"); + assert_true(element instanceof HTMLElement, "Should be an HTMLElement"); + assert_true(element instanceof HTMLSpanElement, "Should be an HTMLSpanElement"); +}, "Lower-case HTML element without a prefix"); + +test(function() { + var HTMLNS = "http://www.w3.org/1999/xhtml"; + var element = document.createElementNS(HTMLNS, "html:span"); + assert_equals(element.namespaceURI, HTMLNS); + assert_equals(element.prefix, "html"); + assert_equals(element.localName, "span"); + assert_equals(element.tagName, "HTML:SPAN"); + assert_true(element instanceof Node, "Should be a Node"); + assert_true(element instanceof Element, "Should be an Element"); + assert_true(element instanceof HTMLElement, "Should be an HTMLElement"); + assert_true(element instanceof HTMLSpanElement, "Should be an HTMLSpanElement"); +}, "Lower-case HTML element with a prefix"); + +test(function() { + var element = document.createElementNS("test", "span"); + assert_equals(element.namespaceURI, "test"); + assert_equals(element.prefix, null); + assert_equals(element.localName, "span"); + assert_equals(element.tagName, "span"); + assert_true(element instanceof Node, "Should be a Node"); + assert_true(element instanceof Element, "Should be an Element"); + assert_false(element instanceof HTMLElement, "Should not be an HTMLElement"); + assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement"); +}, "Lower-case non-HTML element without a prefix"); + +test(function() { + var element = document.createElementNS("test", "html:span"); + assert_equals(element.namespaceURI, "test"); + assert_equals(element.prefix, "html"); + assert_equals(element.localName, "span"); + assert_equals(element.tagName, "html:span"); + assert_true(element instanceof Node, "Should be a Node"); + assert_true(element instanceof Element, "Should be an Element"); + assert_false(element instanceof HTMLElement, "Should not be an HTMLElement"); + assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement"); +}, "Lower-case non-HTML element with a prefix"); + +test(function() { + var HTMLNS = "http://www.w3.org/1999/xhtml"; + var element = document.createElementNS(HTMLNS, "SPAN"); + assert_equals(element.namespaceURI, HTMLNS); + assert_equals(element.prefix, null); + assert_equals(element.localName, "SPAN"); + assert_equals(element.tagName, "SPAN"); + assert_true(element instanceof Node, "Should be a Node"); + assert_true(element instanceof Element, "Should be an Element"); + assert_true(element instanceof HTMLElement, "Should be an HTMLElement"); + assert_true(element instanceof HTMLUnknownElement, "Should be an HTMLUnknownElement"); + assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement"); +}, "Upper-case HTML element without a prefix"); + +test(function() { + var HTMLNS = "http://www.w3.org/1999/xhtml"; + var element = document.createElementNS(HTMLNS, "html:SPAN"); + assert_equals(element.namespaceURI, HTMLNS); + assert_equals(element.prefix, "html"); + assert_equals(element.localName, "SPAN"); + assert_equals(element.tagName, "HTML:SPAN"); + assert_true(element instanceof Node, "Should be a Node"); + assert_true(element instanceof Element, "Should be an Element"); + assert_true(element instanceof HTMLElement, "Should be an HTMLElement"); + assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement"); +}, "Upper-case HTML element with a prefix"); + +test(function() { + var element = document.createElementNS("test", "SPAN"); + assert_equals(element.namespaceURI, "test"); + assert_equals(element.prefix, null); + assert_equals(element.localName, "SPAN"); + assert_equals(element.tagName, "SPAN"); + assert_true(element instanceof Node, "Should be a Node"); + assert_true(element instanceof Element, "Should be an Element"); + assert_false(element instanceof HTMLElement, "Should not be an HTMLElement"); + assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement"); +}, "Upper-case non-HTML element without a prefix"); + +test(function() { + var element = document.createElementNS("test", "html:SPAN"); + assert_equals(element.namespaceURI, "test"); + assert_equals(element.prefix, "html"); + assert_equals(element.localName, "SPAN"); + assert_equals(element.tagName, "html:SPAN"); + assert_true(element instanceof Node, "Should be a Node"); + assert_true(element instanceof Element, "Should be an Element"); + assert_false(element instanceof HTMLElement, "Should not be an HTMLElement"); + assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement"); +}, "Upper-case non-HTML element with a prefix"); + +test(function() { + var element = document.createElementNS(null, "span"); + assert_equals(element.namespaceURI, null); + assert_equals(element.prefix, null); + assert_equals(element.localName, "span"); + assert_equals(element.tagName, "span"); + assert_true(element instanceof Node, "Should be a Node"); + assert_true(element instanceof Element, "Should be an Element"); + assert_false(element instanceof HTMLElement, "Should not be an HTMLElement"); + assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement"); +}, "null namespace"); + +test(function() { + var element = document.createElementNS(undefined, "span"); + assert_equals(element.namespaceURI, null); + assert_equals(element.prefix, null); + assert_equals(element.localName, "span"); + assert_equals(element.tagName, "span"); + assert_true(element instanceof Node, "Should be a Node"); + assert_true(element instanceof Element, "Should be an Element"); + assert_false(element instanceof HTMLElement, "Should not be an HTMLElement"); + assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement"); +}, "undefined namespace"); + +test(function() { + var element = document.createElementNS("", "span"); + assert_equals(element.namespaceURI, null); + assert_equals(element.prefix, null); + assert_equals(element.localName, "span"); + assert_equals(element.tagName, "span"); + assert_true(element instanceof Node, "Should be a Node"); + assert_true(element instanceof Element, "Should be an Element"); + assert_false(element instanceof HTMLElement, "Should not be an HTMLElement"); + assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement"); +}, "empty string namespace"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-createElementNS.js b/testing/web-platform/tests/dom/nodes/Document-createElementNS.js new file mode 100644 index 000000000..b390712aa --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createElementNS.js @@ -0,0 +1,185 @@ +var createElementNS_tests = [ + /* Arrays with three elements: + * the namespace argument + * the qualifiedName argument + * the expected exception, or null if none + */ + [null, null, null], + [null, undefined, null], + [null, "foo", null], + [null, "1foo", "INVALID_CHARACTER_ERR"], + [null, "f1oo", null], + [null, "foo1", null], + [null, "\u0BC6foo", "INVALID_CHARACTER_ERR"], + [null, "}foo", "INVALID_CHARACTER_ERR"], + [null, "f}oo", "INVALID_CHARACTER_ERR"], + [null, "foo}", "INVALID_CHARACTER_ERR"], + [null, "\uFFFFfoo", "INVALID_CHARACTER_ERR"], + [null, "f\uFFFFoo", "INVALID_CHARACTER_ERR"], + [null, "foo\uFFFF", "INVALID_CHARACTER_ERR"], + [null, "<foo", "INVALID_CHARACTER_ERR"], + [null, "foo>", "INVALID_CHARACTER_ERR"], + [null, "<foo>", "INVALID_CHARACTER_ERR"], + [null, "f<oo", "INVALID_CHARACTER_ERR"], + [null, "^^", "INVALID_CHARACTER_ERR"], + [null, "fo o", "INVALID_CHARACTER_ERR"], + [null, "-foo", "INVALID_CHARACTER_ERR"], + [null, ".foo", "INVALID_CHARACTER_ERR"], + [null, ":foo", "NAMESPACE_ERR"], + [null, "f:oo", "NAMESPACE_ERR"], + [null, "foo:", "NAMESPACE_ERR"], + [null, "f:o:o", "NAMESPACE_ERR"], + [null, ":", "NAMESPACE_ERR"], + [null, "xml", null], + [null, "xmlns", "NAMESPACE_ERR"], + [null, "xmlfoo", null], + [null, "xml:foo", "NAMESPACE_ERR"], + [null, "xmlns:foo", "NAMESPACE_ERR"], + [null, "xmlfoo:bar", "NAMESPACE_ERR"], + [null, "null:xml", "NAMESPACE_ERR"], + ["", null, null], + ["", ":foo", "NAMESPACE_ERR"], + ["", "f:oo", "NAMESPACE_ERR"], + ["", "foo:", "NAMESPACE_ERR"], + [undefined, null, null], + [undefined, undefined, null], + [undefined, "foo", null], + [undefined, "1foo", "INVALID_CHARACTER_ERR"], + [undefined, "f1oo", null], + [undefined, "foo1", null], + [undefined, ":foo", "NAMESPACE_ERR"], + [undefined, "f:oo", "NAMESPACE_ERR"], + [undefined, "foo:", "NAMESPACE_ERR"], + [undefined, "f::oo", "NAMESPACE_ERR"], + [undefined, "xml", null], + [undefined, "xmlns", "NAMESPACE_ERR"], + [undefined, "xmlfoo", null], + [undefined, "xml:foo", "NAMESPACE_ERR"], + [undefined, "xmlns:foo", "NAMESPACE_ERR"], + [undefined, "xmlfoo:bar", "NAMESPACE_ERR"], + ["http://example.com/", "foo", null], + ["http://example.com/", "1foo", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "<foo>", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "fo<o", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "-foo", "INVALID_CHARACTER_ERR"], + ["http://example.com/", ".foo", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "f1oo", null], + ["http://example.com/", "foo1", null], + ["http://example.com/", ":foo", "NAMESPACE_ERR"], + ["http://example.com/", "f:oo", null], + ["http://example.com/", "f:o:o", "NAMESPACE_ERR"], + ["http://example.com/", "foo:", "NAMESPACE_ERR"], + ["http://example.com/", "f::oo", "NAMESPACE_ERR"], + ["http://example.com/", "a:0", "NAMESPACE_ERR"], + ["http://example.com/", "0:a", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "a:_", null], + ["http://example.com/", "a:\u0BC6", "NAMESPACE_ERR"], + ["http://example.com/", "\u0BC6:a", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "a:a\u0BC6", null], + ["http://example.com/", "a\u0BC6:a", null], + ["http://example.com/", "xml:test", "NAMESPACE_ERR"], + ["http://example.com/", "xmlns:test", "NAMESPACE_ERR"], + ["http://example.com/", "test:xmlns", null], + ["http://example.com/", "xmlns", "NAMESPACE_ERR"], + ["http://example.com/", "_:_", null], + ["http://example.com/", "_:h0", null], + ["http://example.com/", "_:test", null], + ["http://example.com/", "l_:_", null], + ["http://example.com/", "ns:_0", null], + ["http://example.com/", "ns:a0", null], + ["http://example.com/", "ns0:test", null], + ["http://example.com/", "a.b:c", null], + ["http://example.com/", "a-b:c", null], + ["http://example.com/", "xml", null], + ["http://example.com/", "xmlns", "NAMESPACE_ERR"], + ["http://example.com/", "XMLNS", null], + ["http://example.com/", "xmlfoo", null], + ["http://example.com/", "xml:foo", "NAMESPACE_ERR"], + ["http://example.com/", "XML:foo", null], + ["http://example.com/", "xmlns:foo", "NAMESPACE_ERR"], + ["http://example.com/", "XMLNS:foo", null], + ["http://example.com/", "xmlfoo:bar", null], + ["http://example.com/", "prefix::local", "NAMESPACE_ERR"], + ["http://example.com/", "namespaceURI:{", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:}", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:~", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:'", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:!", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:@", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:#", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:$", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:%", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:^", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:&", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:*", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:(", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:)", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:+", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:=", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:[", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:]", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:\\", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:/", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:;", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:`", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:<", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:>", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:,", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:a ", "INVALID_CHARACTER_ERR"], + ["http://example.com/", "namespaceURI:\"", "INVALID_CHARACTER_ERR"], + ["/", "foo", null], + ["/", "1foo", "INVALID_CHARACTER_ERR"], + ["/", "f1oo", null], + ["/", "foo1", null], + ["/", ":foo", "NAMESPACE_ERR"], + ["/", "f:oo", null], + ["/", "foo:", "NAMESPACE_ERR"], + ["/", "xml", null], + ["/", "xmlns", "NAMESPACE_ERR"], + ["/", "xmlfoo", null], + ["/", "xml:foo", "NAMESPACE_ERR"], + ["/", "xmlns:foo", "NAMESPACE_ERR"], + ["/", "xmlfoo:bar", null], + ["http://www.w3.org/XML/1998/namespace", "foo", null], + ["http://www.w3.org/XML/1998/namespace", "1foo", "INVALID_CHARACTER_ERR"], + ["http://www.w3.org/XML/1998/namespace", "f1oo", null], + ["http://www.w3.org/XML/1998/namespace", "foo1", null], + ["http://www.w3.org/XML/1998/namespace", ":foo", "NAMESPACE_ERR"], + ["http://www.w3.org/XML/1998/namespace", "f:oo", null], + ["http://www.w3.org/XML/1998/namespace", "foo:", "NAMESPACE_ERR"], + ["http://www.w3.org/XML/1998/namespace", "xml", null], + ["http://www.w3.org/XML/1998/namespace", "xmlns", "NAMESPACE_ERR"], + ["http://www.w3.org/XML/1998/namespace", "xmlfoo", null], + ["http://www.w3.org/XML/1998/namespace", "xml:foo", null], + ["http://www.w3.org/XML/1998/namespace", "xmlns:foo", "NAMESPACE_ERR"], + ["http://www.w3.org/XML/1998/namespace", "xmlfoo:bar", null], + ["http://www.w3.org/XML/1998/namespaces", "xml:foo", "NAMESPACE_ERR"], + ["http://www.w3.org/xml/1998/namespace", "xml:foo", "NAMESPACE_ERR"], + ["http://www.w3.org/2000/xmlns/", "foo", "NAMESPACE_ERR"], + ["http://www.w3.org/2000/xmlns/", "1foo", "INVALID_CHARACTER_ERR"], + ["http://www.w3.org/2000/xmlns/", "f1oo", "NAMESPACE_ERR"], + ["http://www.w3.org/2000/xmlns/", "foo1", "NAMESPACE_ERR"], + ["http://www.w3.org/2000/xmlns/", ":foo", "NAMESPACE_ERR"], + ["http://www.w3.org/2000/xmlns/", "f:oo", "NAMESPACE_ERR"], + ["http://www.w3.org/2000/xmlns/", "foo:", "NAMESPACE_ERR"], + ["http://www.w3.org/2000/xmlns/", "xml", "NAMESPACE_ERR"], + ["http://www.w3.org/2000/xmlns/", "xmlns", null], + ["http://www.w3.org/2000/xmlns/", "xmlfoo", "NAMESPACE_ERR"], + ["http://www.w3.org/2000/xmlns/", "xml:foo", "NAMESPACE_ERR"], + ["http://www.w3.org/2000/xmlns/", "xmlns:foo", null], + ["http://www.w3.org/2000/xmlns/", "xmlfoo:bar", "NAMESPACE_ERR"], + ["http://www.w3.org/2000/xmlns/", "foo:xmlns", "NAMESPACE_ERR"], + ["foo:", "foo", null], + ["foo:", "1foo", "INVALID_CHARACTER_ERR"], + ["foo:", "f1oo", null], + ["foo:", "foo1", null], + ["foo:", ":foo", "NAMESPACE_ERR"], + ["foo:", "f:oo", null], + ["foo:", "foo:", "NAMESPACE_ERR"], + ["foo:", "xml", null], + ["foo:", "xmlns", "NAMESPACE_ERR"], + ["foo:", "xmlfoo", null], + ["foo:", "xml:foo", "NAMESPACE_ERR"], + ["foo:", "xmlns:foo", "NAMESPACE_ERR"], + ["foo:", "xmlfoo:bar", null], +] diff --git a/testing/web-platform/tests/dom/nodes/Document-createEvent.html b/testing/web-platform/tests/dom/nodes/Document-createEvent.html new file mode 100644 index 000000000..29a2c010e --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createEvent.html @@ -0,0 +1,154 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Document.createEvent</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createevent"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="Document-createEvent.js"></script> +<div id="log"></div> +<script> +function testAlias(arg, iface) { + var ev; + test(function() { + ev = document.createEvent(arg); + assert_true(ev instanceof window[iface]); + assert_true(ev instanceof Event); + }, arg + " should be an alias for " + iface + "."); + test(function() { + assert_equals(ev.type, "", + "type should be initialized to the empty string"); + assert_equals(ev.target, null, + "target should be initialized to null"); + assert_equals(ev.currentTarget, null, + "currentTarget should be initialized to null"); + assert_equals(ev.eventPhase, 0, + "eventPhase should be initialized to NONE (0)"); + assert_equals(ev.bubbles, false, + "bubbles should be initialized to false"); + assert_equals(ev.cancelable, false, + "cancelable should be initialized to false"); + assert_equals(ev.defaultPrevented, false, + "defaultPrevented should be initialized to false"); + assert_equals(ev.isTrusted, false, + "isTrusted should be initialized to false"); + }, "createEvent('" + arg + "') should be initialized correctly."); +} +for (var alias in aliases) { + var iface = aliases[alias]; + testAlias(alias, iface); + testAlias(alias.toLowerCase(), iface); + testAlias(alias.toUpperCase(), iface); + + if (alias[alias.length - 1] != "s") { + var plural = alias + "s"; + if (!(plural in aliases)) { + test(function () { + assert_throws("NOT_SUPPORTED_ERR", function () { + var evt = document.createEvent(plural); + }); + }, 'Should throw NOT_SUPPORTED_ERR for pluralized legacy event interface "' + plural + '"'); + } + } +} + +test(function() { + assert_throws("NOT_SUPPORTED_ERR", function() { + var evt = document.createEvent("foo"); + }); + assert_throws("NOT_SUPPORTED_ERR", function() { + // 'LATIN CAPITAL LETTER I WITH DOT ABOVE' (U+0130) + var evt = document.createEvent("U\u0130Event"); + }); + assert_throws("NOT_SUPPORTED_ERR", function() { + // 'LATIN SMALL LETTER DOTLESS I' (U+0131) + var evt = document.createEvent("U\u0131Event"); + }); +}, "Should throw NOT_SUPPORTED_ERR for unrecognized arguments"); + +/* + * The following are event interfaces which do actually exist, but must still + * throw since they're absent from the table in the spec for + * document.createEvent(). This list is not exhaustive, but includes all + * interfaces that it is known some UA does or did not throw for. + */ +var someNonCreateableEvents = [ + "AnimationPlaybackEvent", + "AnimationPlayerEvent", + "ApplicationCacheErrorEvent", + "AudioProcessingEvent", + "AutocompleteErrorEvent", + "BeforeInstallPromptEvent", + "BlobEvent", + "ClipboardEvent", + "CommandEvent", + "DataContainerEvent", + "DeviceLightEvent", + "ExtendableEvent", + "ExtendableMessageEvent", + "FetchEvent", + "FontFaceSetLoadEvent", + "GamepadEvent", + "GeofencingEvent", + "InstallEvent", + "KeyEvent", + "MIDIConnectionEvent", + "MIDIMessageEvent", + "MediaEncryptedEvent", + "MediaKeyEvent", + "MediaKeyMessageEvent", + "MediaQueryListEvent", + "MediaStreamEvent", + "MediaStreamTrackEvent", + "MouseScrollEvent", + "MutationEvent", + "NotificationEvent", + "NotifyPaintEvent", + "OfflineAudioCompletionEvent", + "OrientationEvent", + "PageTransition", // Yes, with no "Event" + "PointerEvent", + "PopUpEvent", + "PresentationConnectionAvailableEvent", + "PresentationConnectionCloseEvent", + "PromiseRejectionEvent", + "PushEvent", + "RTCDTMFToneChangeEvent", + "RTCDataChannelEvent", + "RTCIceCandidateEvent", + "RelatedEvent", + "ResourceProgressEvent", + "SVGEvent", + "ScrollAreaEvent", + "SecurityPolicyViolationEvent", + "ServicePortConnectEvent", + "ServiceWorkerMessageEvent", + "SimpleGestureEvent", + "SpeechRecognitionError", + "SpeechRecognitionEvent", + "SpeechSynthesisEvent", + "SyncEvent", + "TimeEvent", + "WebKitAnimationEvent", + "WebKitTransitionEvent", + "XULCommandEvent", +]; +someNonCreateableEvents.forEach(function (eventInterface) { + // SVGEvents is allowed, but not SVGEvent. Make sure we only test if it's + // not whitelisted. + if (!(eventInterface in aliases)) { + test(function () { + assert_throws("NOT_SUPPORTED_ERR", function () { + var evt = document.createEvent(eventInterface); + }); + }, 'Should throw NOT_SUPPORTED_ERR for non-legacy event interface "' + eventInterface + '"'); + } + + if (!(eventInterface + "s" in aliases)) { + test(function () { + assert_throws("NOT_SUPPORTED_ERR", function () { + var evt = document.createEvent(eventInterface + "s"); + }); + }, 'Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "' + eventInterface + 's"'); + } +}); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-createEvent.js b/testing/web-platform/tests/dom/nodes/Document-createEvent.js new file mode 100644 index 000000000..e55487ada --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createEvent.js @@ -0,0 +1,36 @@ +var aliases = { + "AnimationEvent": "AnimationEvent", + "BeforeUnloadEvent": "BeforeUnloadEvent", + "CloseEvent": "CloseEvent", + "CompositionEvent": "CompositionEvent", + "CustomEvent": "CustomEvent", + "DeviceMotionEvent": "DeviceMotionEvent", + "DeviceOrientationEvent": "DeviceOrientationEvent", + "DragEvent": "DragEvent", + "ErrorEvent": "ErrorEvent", + "Event": "Event", + "Events": "Event", + "FocusEvent": "FocusEvent", + "HashChangeEvent": "HashChangeEvent", + "HTMLEvents": "Event", + "IDBVersionChangeEvent": "IDBVersionChangeEvent", + "KeyboardEvent": "KeyboardEvent", + "MessageEvent": "MessageEvent", + "MouseEvent": "MouseEvent", + "MouseEvents": "MouseEvent", + "PageTransitionEvent": "PageTransitionEvent", + "PopStateEvent": "PopStateEvent", + "ProgressEvent": "ProgressEvent", + "StorageEvent": "StorageEvent", + "SVGEvents": "Event", + "SVGZoomEvent": "SVGZoomEvent", + "SVGZoomEvents": "SVGZoomEvent", + "TextEvent": "CompositionEvent", + "TouchEvent": "TouchEvent", + "TrackEvent": "TrackEvent", + "TransitionEvent": "TransitionEvent", + "UIEvent": "UIEvent", + "UIEvents": "UIEvent", + "WebGLContextEvent": "WebGLContextEvent", + "WheelEvent": "WheelEvent", +}; diff --git a/testing/web-platform/tests/dom/nodes/Document-createProcessingInstruction-xhtml.xhtml b/testing/web-platform/tests/dom/nodes/Document-createProcessingInstruction-xhtml.xhtml new file mode 100644 index 000000000..d06f70fdc --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createProcessingInstruction-xhtml.xhtml @@ -0,0 +1,15 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>Document.createProcessingInstruction in XML documents</title> +<link rel="help" href="https://dom.spec.whatwg.org/#dom-document-createprocessinginstruction"/> +<link rel="help" href="https://dom.spec.whatwg.org/#dom-processinginstruction-target"/> +<link rel="help" href="https://dom.spec.whatwg.org/#dom-characterdata-data"/> +<link rel="help" href="https://dom.spec.whatwg.org/#dom-node-ownerdocument"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="log"/> +<script src="Document-createProcessingInstruction.js"/> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Document-createProcessingInstruction.html b/testing/web-platform/tests/dom/nodes/Document-createProcessingInstruction.html new file mode 100644 index 000000000..c57a792fa --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createProcessingInstruction.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Document.createProcessingInstruction in HTML documents</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createprocessinginstruction"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-processinginstruction-target"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-ownerdocument"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script src="Document-createProcessingInstruction.js"></script> diff --git a/testing/web-platform/tests/dom/nodes/Document-createProcessingInstruction.js b/testing/web-platform/tests/dom/nodes/Document-createProcessingInstruction.js new file mode 100644 index 000000000..114ac35d9 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createProcessingInstruction.js @@ -0,0 +1,39 @@ +test(function() { + var invalid = [ + ["A", "?>"], + ["\u00B7A", "x"], + ["\u00D7A", "x"], + ["A\u00D7", "x"], + ["\\A", "x"], + ["\f", "x"], + [0, "x"], + ["0", "x"] + ], + valid = [ + ["xml:fail", "x"], + ["A\u00B7A", "x"], + ["a0", "x"] + ] + + for (var i = 0, il = invalid.length; i < il; i++) { + test(function() { + assert_throws("INVALID_CHARACTER_ERR", function() { + document.createProcessingInstruction(invalid[i][0], invalid[i][1]) + }) + }, "Should throw an INVALID_CHARACTER_ERR for target " + + format_value(invalid[i][0]) + " and data " + + format_value(invalid[i][1]) + ".") + } + for (var i = 0, il = valid.length; i < il; ++i) { + test(function() { + var pi = document.createProcessingInstruction(valid[i][0], valid[i][1]); + assert_equals(pi.target, valid[i][0]); + assert_equals(pi.data, valid[i][1]); + assert_equals(pi.ownerDocument, document); + assert_true(pi instanceof ProcessingInstruction); + assert_true(pi instanceof Node); + }, "Should get a ProcessingInstruction for target " + + format_value(valid[i][0]) + " and data " + + format_value(valid[i][1]) + ".") + } +}) diff --git a/testing/web-platform/tests/dom/nodes/Document-createTextNode.html b/testing/web-platform/tests/dom/nodes/Document-createTextNode.html new file mode 100644 index 000000000..ccc1b1b77 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createTextNode.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Document.createTextNode</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createtextnode"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-ownerdocument"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodevalue"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-textcontent"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-length"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodetype"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-haschildnodes"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-childnodes"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-firstchild"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-lastchild"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="Document-createComment-createTextNode.js"></script> +<div id="log"></div> +<script> +test_create("createTextNode", Text, 3, "#text"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-createTreeWalker.html b/testing/web-platform/tests/dom/nodes/Document-createTreeWalker.html new file mode 100644 index 000000000..f8f04b068 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-createTreeWalker.html @@ -0,0 +1,42 @@ +<!doctype html> +<meta charset=utf-8> +<title>Document.createTreeWalker</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<script> +test(function() { + assert_throws(new TypeError(), function() { + document.createTreeWalker(); + }); +}, "Required arguments to createTreeWalker should be required."); +test(function() { + var tw = document.createTreeWalker(document.body); + assert_equals(tw.root, document.body); + assert_equals(tw.currentNode, document.body); + assert_equals(tw.whatToShow, 0xFFFFFFFF); + assert_equals(tw.filter, null); +}, "Optional arguments to createTreeWalker should be optional (1 passed)."); +test(function() { + var tw = document.createTreeWalker(document.body, 42); + assert_equals(tw.root, document.body); + assert_equals(tw.currentNode, document.body); + assert_equals(tw.whatToShow, 42); + assert_equals(tw.filter, null); +}, "Optional arguments to createTreeWalker should be optional (2 passed)."); +test(function() { + var tw = document.createTreeWalker(document.body, 42, null); + assert_equals(tw.root, document.body); + assert_equals(tw.currentNode, document.body); + assert_equals(tw.whatToShow, 42); + assert_equals(tw.filter, null); +}, "Optional arguments to createTreeWalker should be optional (3 passed, null)."); +test(function() { + var fn = function() {}; + var tw = document.createTreeWalker(document.body, 42, fn); + assert_equals(tw.root, document.body); + assert_equals(tw.currentNode, document.body); + assert_equals(tw.whatToShow, 42); + assert_equals(tw.filter, fn); +}, "Optional arguments to createTreeWalker should be optional (3 passed, function)."); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-doctype.html b/testing/web-platform/tests/dom/nodes/Document-doctype.html new file mode 100644 index 000000000..75bfd8506 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-doctype.html @@ -0,0 +1,21 @@ +<!-- comment --> +<!doctype html> +<meta charset=utf-8> +<title>Document.doctype</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-doctype"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + assert_true(document.doctype instanceof DocumentType, + "Doctype should be a DocumentType"); + assert_equals(document.doctype, document.childNodes[1]); +}, "Window document with doctype"); + +test(function() { + var newdoc = new Document(); + newdoc.appendChild(newdoc.createElement("html")); + assert_equals(newdoc.doctype, null); +}, "new Document()"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-getElementById.html b/testing/web-platform/tests/dom/nodes/Document-getElementById.html new file mode 100644 index 000000000..1dec4c085 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-getElementById.html @@ -0,0 +1,350 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Document.getElementById</title> +<link rel="author" title="Tetsuharu OHZEKI" href="mailto:saneyuki.snyk@gmail.com"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-getelementbyid"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> + <div id="log"></div> + + <!-- test 0 --> + <div id=""></div> + + <!-- test 1 --> + <div id="test1"></div> + + <!-- test 5 --> + <div id="test5" data-name="1st"> + <p id="test5" data-name="2nd">P</p> + <input id="test5" type="submit" value="Submit" data-name="3rd"> + </div> + + <!-- test 15 --> + <div id="outer"> + <div id="middle"> + <div id="inner"></div> + </div> + </div> + +<script> + var gBody = document.getElementsByTagName("body")[0]; + + test(function() { + assert_equals(document.getElementById(""), null); + }, "Calling document.getElementById with an empty string argument."); + + test(function() { + var element = document.createElement("div"); + element.setAttribute("id", "null"); + document.body.appendChild(element); + this.add_cleanup(function() { document.body.removeChild(element) }); + assert_equals(document.getElementById(null), element); + }, "Calling document.getElementById with a null argument."); + + test(function() { + var element = document.createElement("div"); + element.setAttribute("id", "undefined"); + document.body.appendChild(element); + this.add_cleanup(function() { document.body.removeChild(element) }); + assert_equals(document.getElementById(undefined), element); + }, "Calling document.getElementById with an undefined argument."); + + + test(function() { + var bar = document.getElementById("test1"); + assert_not_equals(bar, null, "should not be null"); + assert_equals(bar.tagName, "DIV", "should have expected tag name."); + assert_true(bar instanceof HTMLDivElement, "should be a valid Element instance"); + }, "on static page"); + + + test(function() { + var TEST_ID = "test2"; + + var test = document.createElement("div"); + test.setAttribute("id", TEST_ID); + gBody.appendChild(test); + + // test: appended element + var result = document.getElementById(TEST_ID); + assert_not_equals(result, null, "should not be null."); + assert_equals(result.tagName, "DIV", "should have appended element's tag name"); + assert_true(result instanceof HTMLDivElement, "should be a valid Element instance"); + + // test: removed element + gBody.removeChild(test); + var removed = document.getElementById(TEST_ID); + // `document.getElementById()` returns `null` if there is none. + // https://dom.spec.whatwg.org/#dom-nonelementparentnode-getelementbyid + assert_equals(removed, null, "should not get removed element."); + }, "Document.getElementById with a script-inserted element"); + + + test(function() { + // setup fixtures. + var TEST_ID = "test3"; + var test = document.createElement("div"); + test.setAttribute("id", TEST_ID); + gBody.appendChild(test); + + // update id + var UPDATED_ID = "test3-updated"; + test.setAttribute("id", UPDATED_ID); + var e = document.getElementById(UPDATED_ID); + assert_equals(e, test, "should get the element with id."); + + var old = document.getElementById(TEST_ID); + assert_equals(old, null, "shouldn't get the element by the old id."); + + // remove id. + test.removeAttribute("id"); + var e2 = document.getElementById(UPDATED_ID); + assert_equals(e2, null, "should return null when the passed id is none in document."); + }, "update `id` attribute via setAttribute/removeAttribute"); + + + test(function() { + var TEST_ID = "test4-should-not-exist"; + + var e = document.createElement('div'); + e.setAttribute("id", TEST_ID); + + assert_equals(document.getElementById(TEST_ID), null, "should be null"); + document.body.appendChild(e); + assert_equals(document.getElementById(TEST_ID), e, "should be the appended element"); + }, "Ensure that the id attribute only affects elements present in a document"); + + + test(function() { + // the method should return the 1st element. + var TEST_ID = "test5"; + var target = document.getElementById(TEST_ID); + assert_not_equals(target, null, "should not be null"); + assert_equals(target.getAttribute("data-name"), "1st", "should return the 1st"); + + // even if after the new element was appended. + var element4 = document.createElement("div"); + element4.setAttribute("id", TEST_ID); + element4.setAttribute("data-name", "4th"); + gBody.appendChild(element4); + var target2 = document.getElementById(TEST_ID); + assert_not_equals(target2, null, "should not be null"); + assert_equals(target2.getAttribute("data-name"), "1st", "should be the 1st"); + + // should return the next element after removed the subtree including the 1st element. + target2.parentNode.removeChild(target2); + var target3 = document.getElementById(TEST_ID); + assert_not_equals(target3, null, "should not be null"); + assert_equals(target3.getAttribute("data-name"), "4th", "should be the 4th"); + }, "in tree order, within the context object's tree"); + + + test(function() { + var TEST_ID = "test6"; + var s = document.createElement("div"); + s.setAttribute("id", TEST_ID); + // append to Element, not Document. + document.createElement("div").appendChild(s); + + assert_equals(document.getElementById(TEST_ID), null, "should be null"); + }, "Modern browsers optimize this method with using internal id cache. " + + "This test checks that their optimization should effect only append to `Document`, not append to `Node`."); + + + test(function() { + var TEST_ID = "test7" + var element = document.createElement("div"); + element.setAttribute("id", TEST_ID); + gBody.appendChild(element); + + var target = document.getElementById(TEST_ID); + assert_equals(target, element, "should return the element before changing the value"); + + element.attributes[0].value = TEST_ID + "-updated"; + var target2 = document.getElementById(TEST_ID); + assert_equals(target2, null, "should return null after updated id via Attr.value"); + var target3 = document.getElementById(TEST_ID + "-updated"); + assert_equals(target3, element, "should be equal to the updated element."); + }, "changing attribute's value via `Attr` gotten from `Element.attribute`."); + + + test(function() { + var TEST_ID = "test8"; + + // setup fixture + var element = document.createElement("div"); + element.setAttribute("id", TEST_ID + "-fixture"); + gBody.appendChild(element); + + // add id-ed element with using innerHTML + element.innerHTML = "<div id='"+ TEST_ID +"'></div>"; + var test = document.getElementById(TEST_ID); + assert_equals(test, element.firstChild, "should not be null"); + assert_equals(test.tagName, "DIV", "should have expected tag name."); + assert_true(test instanceof HTMLDivElement, "should be a valid Element instance"); + }, "add id attribute via innerHTML"); + + + test(function() { + var TEST_ID = "test9"; + + // add fixture + var fixture = document.createElement("div"); + fixture.setAttribute("id", TEST_ID + "-fixture"); + gBody.appendChild(fixture); + + var element = document.createElement("div"); + element.setAttribute("id", TEST_ID); + fixture.appendChild(element); + + // check 'getElementById' should get the 'element' + assert_equals(document.getElementById(TEST_ID), element, "should not be null"); + + // remove id-ed element with using innerHTML (clear 'element') + fixture.innerHTML = ""; + var test = document.getElementById(TEST_ID); + assert_equals(test, null, "should be null."); + }, "remove id attribute via innerHTML"); + + + test(function() { + var TEST_ID = "test10"; + + // setup fixture + var element = document.createElement("div"); + element.setAttribute("id", TEST_ID + "-fixture"); + gBody.appendChild(element); + + // add id-ed element with using outerHTML + element.outerHTML = "<div id='"+ TEST_ID +"'></div>"; + var test = document.getElementById(TEST_ID); + assert_not_equals(test, null, "should not be null"); + assert_equals(test.tagName, "DIV", "should have expected tag name."); + assert_true(test instanceof HTMLDivElement,"should be a valid Element instance"); + }, "add id attribute via outerHTML"); + + + test(function() { + var TEST_ID = "test11"; + + var element = document.createElement("div"); + element.setAttribute("id", TEST_ID); + gBody.appendChild(element); + + var test = document.getElementById(TEST_ID); + assert_equals(test, element, "should be equal to the appended element."); + + // remove id-ed element with using outerHTML + element.outerHTML = "<div></div>"; + var test = document.getElementById(TEST_ID); + assert_equals(test, null, "should be null."); + }, "remove id attribute via outerHTML"); + + + test(function() { + // setup fixtures. + var TEST_ID = "test12"; + var test = document.createElement("div"); + test.id = TEST_ID; + gBody.appendChild(test); + + // update id + var UPDATED_ID = TEST_ID + "-updated"; + test.id = UPDATED_ID; + var e = document.getElementById(UPDATED_ID); + assert_equals(e, test, "should get the element with id."); + + var old = document.getElementById(TEST_ID); + assert_equals(old, null, "shouldn't get the element by the old id."); + + // remove id. + test.id = ""; + var e2 = document.getElementById(UPDATED_ID); + assert_equals(e2, null, "should return null when the passed id is none in document."); + }, "update `id` attribute via element.id"); + + + test(function() { + var TEST_ID = "test13"; + + var create_same_id_element = function (order) { + var element = document.createElement("div"); + element.setAttribute("id", TEST_ID); + element.setAttribute("data-order", order);// for debug + return element; + }; + + // create fixture + var container = document.createElement("div"); + container.setAttribute("id", TEST_ID + "-fixture"); + gBody.appendChild(container); + + var element1 = create_same_id_element("1"); + var element2 = create_same_id_element("2"); + var element3 = create_same_id_element("3"); + var element4 = create_same_id_element("4"); + + // append element: 2 -> 4 -> 3 -> 1 + container.appendChild(element2); + container.appendChild(element4); + container.insertBefore(element3, element4); + container.insertBefore(element1, element2); + + + var test = document.getElementById(TEST_ID); + assert_equals(test, element1, "should return 1st element"); + container.removeChild(element1); + + test = document.getElementById(TEST_ID); + assert_equals(test, element2, "should return 2nd element"); + container.removeChild(element2); + + test = document.getElementById(TEST_ID); + assert_equals(test, element3, "should return 3rd element"); + container.removeChild(element3); + + test = document.getElementById(TEST_ID); + assert_equals(test, element4, "should return 4th element"); + container.removeChild(element4); + + + }, "where insertion order and tree order don't match"); + + test(function() { + var TEST_ID = "test14"; + var a = document.createElement("a"); + var b = document.createElement("b"); + a.appendChild(b); + b.id = TEST_ID; + assert_equals(document.getElementById(TEST_ID), null); + + gBody.appendChild(a); + assert_equals(document.getElementById(TEST_ID), b); + }, "Inserting an id by inserting its parent node"); + + test(function () { + var TEST_ID = "test15" + var outer = document.getElementById("outer"); + var middle = document.getElementById("middle"); + var inner = document.getElementById("inner"); + outer.removeChild(middle); + + var new_el = document.createElement("h1"); + new_el.id = "heading"; + inner.appendChild(new_el); + // the new element is not part of the document since + // "middle" element was removed previously + assert_equals(document.getElementById("heading"), null); + }, "Document.getElementById must not return nodes not present in document"); + + // TODO: + // id attribute in a namespace + + + // TODO: + // SVG + MathML elements with id attributes + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Document-getElementsByTagName-xhtml.xhtml b/testing/web-platform/tests/dom/nodes/Document-getElementsByTagName-xhtml.xhtml new file mode 100644 index 000000000..309a29ae7 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-getElementsByTagName-xhtml.xhtml @@ -0,0 +1,104 @@ +<!DOCTYPE html> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>Document.getElementsByTagName</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="log"></div> +<pre id="x"></pre> +<script> +test(function() { + var t = document.body.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "I")) + this.add_cleanup(function() {document.body.removeChild(t)}) + assert_equals(t.localName, "I") + assert_equals(t.tagName, "I") + assert_array_equals(document.getElementsByTagName("I"), [t]) + assert_array_equals(document.getElementsByTagName("i"), []) + assert_array_equals(document.body.getElementsByTagName("I"), [t]) + assert_array_equals(document.body.getElementsByTagName("i"), []) +}, "HTML element with uppercase tag name matches in XHTML documents") + +test(function() { + var t = document.body.appendChild(document.createElementNS("test", "st")) + this.add_cleanup(function() {document.body.removeChild(t)}) + assert_array_equals(document.getElementsByTagName("st"), [t]) + assert_array_equals(document.getElementsByTagName("ST"), []) +}, "Element in non-HTML namespace, no prefix, lowercase name") + +test(function() { + var t = document.body.appendChild(document.createElementNS("test", "ST")) + this.add_cleanup(function() {document.body.removeChild(t)}) + assert_array_equals(document.getElementsByTagName("ST"), [t]) + assert_array_equals(document.getElementsByTagName("st"), []) +}, "Element in non-HTML namespace, no prefix, uppercase name") + +test(function() { + var t = document.body.appendChild(document.createElementNS("test", "te:st")) + this.add_cleanup(function() {document.body.removeChild(t)}) + assert_array_equals(document.getElementsByTagName("st"), []) + assert_array_equals(document.getElementsByTagName("ST"), []) + assert_array_equals(document.getElementsByTagName("te:st"), [t]) + assert_array_equals(document.getElementsByTagName("te:ST"), []) +}, "Element in non-HTML namespace, prefix, lowercase name") + +test(function() { + var t = document.body.appendChild(document.createElementNS("test", "te:ST")) + this.add_cleanup(function() {document.body.removeChild(t)}) + assert_array_equals(document.getElementsByTagName("ST"), []) + assert_array_equals(document.getElementsByTagName("st"), []) + assert_array_equals(document.getElementsByTagName("te:st"), []) + assert_array_equals(document.getElementsByTagName("te:ST"), [t]) +}, "Element in non-HTML namespace, prefix, uppercase name") + +test(function() { + var t = document.body.appendChild(document.createElement("AÇ")) + this.add_cleanup(function() {document.body.removeChild(t)}) + assert_array_equals(document.getElementsByTagName("AÇ"), [t], "All uppercase input") + assert_array_equals(document.getElementsByTagName("aÇ"), [], "Ascii lowercase input") + assert_array_equals(document.getElementsByTagName("aç"), [], "All lowercase input") +}, "Element in HTML namespace, no prefix, non-ascii characters in name") + +test(function() { + var t = document.body.appendChild(document.createElementNS("test", "AÇ")) + this.add_cleanup(function() {document.body.removeChild(t)}) + assert_array_equals(document.getElementsByTagName("AÇ"), [t], "All uppercase input") + assert_array_equals(document.getElementsByTagName("aÇ"), [], "Ascii lowercase input") + assert_array_equals(document.getElementsByTagName("aç"), [], "All lowercase input") +}, "Element in non-HTML namespace, non-ascii characters in name") + +test(function() { + var t = document.body.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "test:aÇ")) + this.add_cleanup(function() {document.body.removeChild(t)}) + assert_array_equals(document.getElementsByTagName("TEST:AÇ"), [], "All uppercase input") + assert_array_equals(document.getElementsByTagName("test:aÇ"), [t], "Ascii lowercase input") + assert_array_equals(document.getElementsByTagName("test:aç"), [], "All lowercase input") +}, "Element in HTML namespace, prefix, non-ascii characters in name") + +test(function() { + var t = document.body.appendChild(document.createElementNS("test", "TEST:AÇ")) + this.add_cleanup(function() {document.body.removeChild(t)}) + assert_array_equals(document.getElementsByTagName("TEST:AÇ"), [t], "All uppercase input") + assert_array_equals(document.getElementsByTagName("test:aÇ"), [], "Ascii lowercase input") + assert_array_equals(document.getElementsByTagName("test:aç"), [], "All lowercase input") +}, "Element in non-HTML namespace, prefix, non-ascii characters in name") + +test(function() { + var actual = document.getElementsByTagName("*"); + var expected = []; + var get_elements = function(node) { + for (var i = 0; i < node.childNodes.length; i++) { + var child = node.childNodes[i]; + if (child.nodeType === child.ELEMENT_NODE) { + expected.push(child); + get_elements(child); + } + } + } + get_elements(document); + assert_array_equals(actual, expected); +}, "getElementsByTagName('*')") +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Document-getElementsByTagName.html b/testing/web-platform/tests/dom/nodes/Document-getElementsByTagName.html new file mode 100644 index 000000000..00e3435c4 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-getElementsByTagName.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Document.getElementsByTagName</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-getelementsbytagname"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="Document-Element-getElementsByTagName.js"></script> +<div id="log"></div> +<script> +test_getElementsByTagName(document, document.body); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-getElementsByTagNameNS.html b/testing/web-platform/tests/dom/nodes/Document-getElementsByTagNameNS.html new file mode 100644 index 000000000..063dc9821 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-getElementsByTagNameNS.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Document.getElementsByTagNameNS</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-getelementsbytagnamens"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="Document-Element-getElementsByTagNameNS.js"></script> +<div id="log"></div> +<script> +test_getElementsByTagNameNS(document, document.body); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-implementation.html b/testing/web-platform/tests/dom/nodes/Document-implementation.html new file mode 100644 index 000000000..aed525965 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-implementation.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Document.implementation</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-implementation"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + var implementation = document.implementation; + assert_true(implementation instanceof DOMImplementation, + "implementation should implement DOMImplementation"); + assert_equals(document.implementation, implementation); +}, "Getting implementation off the same document"); + +test(function() { + var doc = document.implementation.createHTMLDocument(); + assert_not_equals(document.implementation, doc.implementation); +}, "Getting implementation off different documents"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Document-importNode.html b/testing/web-platform/tests/dom/nodes/Document-importNode.html new file mode 100644 index 000000000..32e2f3169 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Document-importNode.html @@ -0,0 +1,57 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Document.importNode</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-importnode"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + var doc = document.implementation.createHTMLDocument("Title"); + var div = doc.body.appendChild(doc.createElement("div")); + div.appendChild(doc.createElement("span")); + assert_equals(div.ownerDocument, doc); + assert_equals(div.firstChild.ownerDocument, doc); + var newDiv = document.importNode(div); + assert_equals(div.ownerDocument, doc); + assert_equals(div.firstChild.ownerDocument, doc); + assert_equals(newDiv.ownerDocument, document); + assert_equals(newDiv.firstChild, null); +}, "No 'deep' argument.") +test(function() { + var doc = document.implementation.createHTMLDocument("Title"); + var div = doc.body.appendChild(doc.createElement("div")); + div.appendChild(doc.createElement("span")); + assert_equals(div.ownerDocument, doc); + assert_equals(div.firstChild.ownerDocument, doc); + var newDiv = document.importNode(div, undefined); + assert_equals(div.ownerDocument, doc); + assert_equals(div.firstChild.ownerDocument, doc); + assert_equals(newDiv.ownerDocument, document); + assert_equals(newDiv.firstChild, null); +}, "Undefined 'deep' argument.") +test(function() { + var doc = document.implementation.createHTMLDocument("Title"); + var div = doc.body.appendChild(doc.createElement("div")); + div.appendChild(doc.createElement("span")); + assert_equals(div.ownerDocument, doc); + assert_equals(div.firstChild.ownerDocument, doc); + var newDiv = document.importNode(div, true); + assert_equals(div.ownerDocument, doc); + assert_equals(div.firstChild.ownerDocument, doc); + assert_equals(newDiv.ownerDocument, document); + assert_equals(newDiv.firstChild.ownerDocument, document); +}, "True 'deep' argument.") +test(function() { + var doc = document.implementation.createHTMLDocument("Title"); + var div = doc.body.appendChild(doc.createElement("div")); + div.appendChild(doc.createElement("span")); + assert_equals(div.ownerDocument, doc); + assert_equals(div.firstChild.ownerDocument, doc); + var newDiv = document.importNode(div, false); + assert_equals(div.ownerDocument, doc); + assert_equals(div.firstChild.ownerDocument, doc); + assert_equals(newDiv.ownerDocument, document); + assert_equals(newDiv.firstChild, null); +}, "False 'deep' argument.") +</script> diff --git a/testing/web-platform/tests/dom/nodes/DocumentType-literal-xhtml.xhtml b/testing/web-platform/tests/dom/nodes/DocumentType-literal-xhtml.xhtml new file mode 100644 index 000000000..2b6965c14 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/DocumentType-literal-xhtml.xhtml @@ -0,0 +1,23 @@ +<!DOCTYPE html PUBLIC "STAFF" "staffNS.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>DocumentType literals</title> +<link rel="help" href="https://dom.spec.whatwg.org/#dom-documenttype-name"/> +<link rel="help" href="https://dom.spec.whatwg.org/#dom-documenttype-publicid"/> +<link rel="help" href="https://dom.spec.whatwg.org/#dom-documenttype-systemid"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="log"/> +<script> +test(function() { + var doctype = document.firstChild; + assert_true(doctype instanceof DocumentType) + assert_equals(doctype.name, "html") + assert_equals(doctype.publicId, 'STAFF') + assert_equals(doctype.systemId, 'staffNS.dtd') +}) +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/DocumentType-literal.html b/testing/web-platform/tests/dom/nodes/DocumentType-literal.html new file mode 100644 index 000000000..a755c397b --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/DocumentType-literal.html @@ -0,0 +1,17 @@ +<!DOCTYPE html PUBLIC "STAFF" "staffNS.dtd"> +<title>DocumentType literals</title> +<link rel="help" href="https://dom.spec.whatwg.org/#dom-documenttype-name"> +<link rel="help" href="https://dom.spec.whatwg.org/#dom-documenttype-publicid"> +<link rel="help" href="https://dom.spec.whatwg.org/#dom-documenttype-systemid"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + var doctype = document.firstChild; + assert_true(doctype instanceof DocumentType) + assert_equals(doctype.name, "html") + assert_equals(doctype.publicId, 'STAFF') + assert_equals(doctype.systemId, 'staffNS.dtd') +}) +</script> diff --git a/testing/web-platform/tests/dom/nodes/DocumentType-remove.html b/testing/web-platform/tests/dom/nodes/DocumentType-remove.html new file mode 100644 index 000000000..9e18d3511 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/DocumentType-remove.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>DocumentType.remove</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-childnode-remove"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="ChildNode-remove.js"></script> +<div id=log></div> +<script> +var node, parentNode; +setup(function() { + node = document.implementation.createDocumentType("html", "", ""); + parentNode = document.implementation.createDocument(null, "", null); +}); +testRemove(node, parentNode, "doctype"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-childElement-null-svg.svg b/testing/web-platform/tests/dom/nodes/Element-childElement-null-svg.svg new file mode 100644 index 000000000..388482874 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-childElement-null-svg.svg @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:h="http://www.w3.org/1999/xhtml" + version="1.1" + width="100%" height="100%" viewBox="0 0 400 400"> +<title>Null test</title> +<h:script src="/resources/testharness.js"/> +<h:script src="/resources/testharnessreport.js"/> + +<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of firstElementChild and lastChildElement returning null</text> +<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle" font-weight="bold">Test</text> + +<h:script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl") + assert_equals(parentEl.firstElementChild, null) + assert_equals(parentEl.lastElementChild, null) +}) +]]></h:script> +</svg> diff --git a/testing/web-platform/tests/dom/nodes/Element-childElement-null-xhtml.xhtml b/testing/web-platform/tests/dom/nodes/Element-childElement-null-xhtml.xhtml new file mode 100644 index 000000000..daedab6d9 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-childElement-null-xhtml.xhtml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>Null Test</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<h1>Test of firstElementChild and lastChildElement returning null</h1> +<div id="log"></div> +<p id="parentEl" style="font-weight:bold;">Test.</p> +<script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl") + assert_equals(parentEl.firstElementChild, null) + assert_equals(parentEl.lastElementChild, null) +}) +]]></script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Element-childElement-null.html b/testing/web-platform/tests/dom/nodes/Element-childElement-null.html new file mode 100644 index 000000000..1863a41da --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-childElement-null.html @@ -0,0 +1,15 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>Null test</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<h1>Test of firstElementChild and lastChildElement returning null</h1> +<div id="log"></div> +<p id="parentEl" style="font-weight:bold;">Test.</p> +<script> +test(function() { + var parentEl = document.getElementById("parentEl") + assert_equals(parentEl.firstElementChild, null) + assert_equals(parentEl.lastElementChild, null) +}) +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-childElementCount-dynamic-add-svg.svg b/testing/web-platform/tests/dom/nodes/Element-childElementCount-dynamic-add-svg.svg new file mode 100644 index 000000000..d149f1ea3 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-childElementCount-dynamic-add-svg.svg @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:h="http://www.w3.org/1999/xhtml" + version="1.1" + width="100%" height="100%" viewBox="0 0 400 400"> +<title>Dynamic Adding of Elements</title> +<h:script src="/resources/testharness.js"/> +<h:script src="/resources/testharnessreport.js"/> + +<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of Dynamic Adding of Elements</text> +<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle">The result of this test is +<tspan id="first_element_child" font-weight="bold">unknown.</tspan></text> + +<h:script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl"); + var newChild = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + parentEl.appendChild(newChild); + assert_equals(parentEl.childElementCount, 2) +}) +]]></h:script> +</svg> diff --git a/testing/web-platform/tests/dom/nodes/Element-childElementCount-dynamic-add-xhtml.xhtml b/testing/web-platform/tests/dom/nodes/Element-childElementCount-dynamic-add-xhtml.xhtml new file mode 100644 index 000000000..c97ed1965 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-childElementCount-dynamic-add-xhtml.xhtml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>Dynamic Adding of Elements</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<h1>Test of Dynamic Adding of Elements</h1> +<div id="log"></div> +<p id="parentEl">The result of this test is +<span id="first_element_child" style="font-weight:bold;">logged above.</span></p> +<script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl"); + var newChild = document.createElement("span"); + parentEl.appendChild(newChild); + assert_equals(parentEl.childElementCount, 2) +}) +]]></script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Element-childElementCount-dynamic-add.html b/testing/web-platform/tests/dom/nodes/Element-childElementCount-dynamic-add.html new file mode 100644 index 000000000..3e7490b21 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-childElementCount-dynamic-add.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>Dynamic Adding of Elements</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<h1>Test of Dynamic Adding of Elements</h1> +<div id="log"></div> +<p id="parentEl">The result of this test is +<span id="first_element_child" style="font-weight:bold;">logged above.</span></p> +<script> +test(function() { + var parentEl = document.getElementById("parentEl"); + var newChild = document.createElement("span"); + parentEl.appendChild(newChild); + assert_equals(parentEl.childElementCount, 2) +}) +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-childElementCount-dynamic-remove-svg.svg b/testing/web-platform/tests/dom/nodes/Element-childElementCount-dynamic-remove-svg.svg new file mode 100644 index 000000000..bf99de65a --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-childElementCount-dynamic-remove-svg.svg @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:h="http://www.w3.org/1999/xhtml" + version="1.1" + width="100%" height="100%" viewBox="0 0 400 400"> +<title>Dynamic Removal of Elements</title> +<h:script src="/resources/testharness.js"/> +<h:script src="/resources/testharnessreport.js"/> + +<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of Dynamic Removal of Elements</text> +<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle">The result of this test is +<tspan id="first_element_child" font-weight="bold">unknown.</tspan><tspan id="last_element_child"> </tspan></text> + +<h:script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl"); + var lec = parentEl.lastElementChild; + parentEl.removeChild(lec); + assert_equals(parentEl.childElementCount, 1) +}) +]]></h:script> +</svg> diff --git a/testing/web-platform/tests/dom/nodes/Element-childElementCount-dynamic-remove-xhtml.xhtml b/testing/web-platform/tests/dom/nodes/Element-childElementCount-dynamic-remove-xhtml.xhtml new file mode 100644 index 000000000..f0009b0a7 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-childElementCount-dynamic-remove-xhtml.xhtml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>Dynamic Removal of Elements</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<h1>Test of Removal Adding of Elements</h1> +<div id="log"></div> +<p id="parentEl">The result of this test is +<span id="first_element_child" style="font-weight:bold;">logged above.</span><span id="last_element_child"> </span></p> +<script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl"); + var lec = parentEl.lastElementChild; + parentEl.removeChild(lec); + assert_equals(parentEl.childElementCount, 1) +}) +]]></script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Element-childElementCount-dynamic-remove.html b/testing/web-platform/tests/dom/nodes/Element-childElementCount-dynamic-remove.html new file mode 100644 index 000000000..3f7e7c7ea --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-childElementCount-dynamic-remove.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>Dynamic Removal of Elements</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<h1>Test of Dynamic Removal of Elements</h1> +<div id="log"></div> +<p id="parentEl">The result of this test is +<span id="first_element_child" style="font-weight:bold;">unknown.</span><span id="last_element_child"> </span></p> +<script> +test(function() { + var parentEl = document.getElementById("parentEl"); + var lec = parentEl.lastElementChild; + parentEl.removeChild(lec); + assert_equals(parentEl.childElementCount, 1) +}) +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-childElementCount-nochild-svg.svg b/testing/web-platform/tests/dom/nodes/Element-childElementCount-nochild-svg.svg new file mode 100644 index 000000000..8ba574360 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-childElementCount-nochild-svg.svg @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:h="http://www.w3.org/1999/xhtml" + version="1.1" + width="100%" height="100%" viewBox="0 0 400 400"> +<title>childElementCount</title> +<h:script src="/resources/testharness.js"/> +<h:script src="/resources/testharnessreport.js"/> + +<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of childElementCount with No Child Element Nodes</text> +<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle" font-weight="bold">Test</text> + +<h:script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl") + assert_equals(parentEl.childElementCount, 0) +}) +]]></h:script> +</svg> diff --git a/testing/web-platform/tests/dom/nodes/Element-childElementCount-nochild-xhtml.xhtml b/testing/web-platform/tests/dom/nodes/Element-childElementCount-nochild-xhtml.xhtml new file mode 100644 index 000000000..f567a20c2 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-childElementCount-nochild-xhtml.xhtml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>childElementCount without Child Element Nodes</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<h1>Test of childElementCount with No Child Element Nodes</h1> +<div id="log"></div> +<p id="parentEl" style="font-weight:bold;">Test.</p> +<script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl") + assert_equals(parentEl.childElementCount, 0) +}) +]]></script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Element-childElementCount-nochild.html b/testing/web-platform/tests/dom/nodes/Element-childElementCount-nochild.html new file mode 100644 index 000000000..fb52fb205 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-childElementCount-nochild.html @@ -0,0 +1,14 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>childElementCount without Child Element Nodes</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<h1>Test of childElementCount with No Child Element Nodes</h1> +<div id="log"></div> +<p id="parentEl" style="font-weight:bold;">Test.</p> +<script> +test(function() { + var parentEl = document.getElementById("parentEl") + assert_equals(parentEl.childElementCount, 0) +}) +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-childElementCount-svg.svg b/testing/web-platform/tests/dom/nodes/Element-childElementCount-svg.svg new file mode 100644 index 000000000..ff93eff62 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-childElementCount-svg.svg @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:h="http://www.w3.org/1999/xhtml" + version="1.1" + width="100%" height="100%" viewBox="0 0 400 400"> +<title>childElementCount</title> +<h:script src="/resources/testharness.js"/> +<h:script src="/resources/testharnessreport.js"/> + +<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of childElementCount</text> +<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle">The result of <tspan id="first_element_child"><tspan>this</tspan> <tspan>test</tspan></tspan> is +<tspan id="middle_element_child" font-weight="bold">unknown.</tspan> + + + +<tspan id="last_element_child" style="display:none;">fnord</tspan> </text> + +<h:script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl") + assert_true("childElementCount" in parentEl) + assert_equals(parentEl.childElementCount, 3) +}) +]]></h:script> +</svg> diff --git a/testing/web-platform/tests/dom/nodes/Element-childElementCount-xhtml.xhtml b/testing/web-platform/tests/dom/nodes/Element-childElementCount-xhtml.xhtml new file mode 100644 index 000000000..6b719ff7a --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-childElementCount-xhtml.xhtml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>childElementCount</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<h1>Test of childElementCount</h1> +<div id="log"></div> +<p id="parentEl">The result of <span id="first_element_child"><span>this</span> <span>test</span></span> is +<span id="middle_element_child" style="font-weight:bold;">unknown.</span> + + + +<span id="last_element_child" style="display:none;">fnord</span> </p> +<script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl") + assert_true("childElementCount" in parentEl) + assert_equals(parentEl.childElementCount, 3) +}) +]]></script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Element-childElementCount.html b/testing/web-platform/tests/dom/nodes/Element-childElementCount.html new file mode 100644 index 000000000..8cfe567f9 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-childElementCount.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>childElementCount</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<h1>Test of childElementCount</h1> +<div id="log"></div> +<p id="parentEl">The result of <span id="first_element_child"><span>this</span> <span>test</span></span> is +<span id="middle_element_child" style="font-weight:bold;">given above.</span> + + + +<span id="last_element_child" style="display:none;">fnord</span> </p> +<script> +test(function() { + var parentEl = document.getElementById("parentEl") + assert_true("childElementCount" in parentEl) + assert_equals(parentEl.childElementCount, 3) +}) +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-children.html b/testing/web-platform/tests/dom/nodes/Element-children.html new file mode 100644 index 000000000..c0210f966 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-children.html @@ -0,0 +1,58 @@ +<!DOCTYPE html> +<title>HTMLCollection edge cases</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<div id="test"><img><img id=foo><img id=foo><img name="bar"></div> +<script> +setup(function() { + // Add some non-HTML elements in there to test what happens with those. + var container = document.getElementById("test"); + var child = document.createElementNS("", "img"); + child.setAttribute("id", "baz"); + container.appendChild(child); + + child = document.createElementNS("", "img"); + child.setAttribute("name", "qux"); + container.appendChild(child); +}); + +test(function() { + var container = document.getElementById("test"); + var result = container.children.item("foo"); + assert_true(result instanceof Element, "Expected an Element."); + assert_false(result.hasAttribute("id"), "Expected the IDless Element.") +}) + +test(function() { + var container = document.getElementById("test"); + var list = container.children; + var result = []; + for (var p in list) { + if (list.hasOwnProperty(p)) { + result.push(p); + } + } + assert_array_equals(result, ['0', '1', '2', '3', '4', '5']); + result = Object.getOwnPropertyNames(list); + assert_array_equals(result, ['0', '1', '2', '3', '4', '5', 'foo', 'bar', 'baz']); + + // Mapping of exposed names to their indices in the list. + var exposedNames = { 'foo': 1, 'bar': 3, 'baz': 4 }; + for (var exposedName in exposedNames) { + assert_true(exposedName in list); + assert_true(list.hasOwnProperty(exposedName)); + assert_equals(list[exposedName], list.namedItem(exposedName)); + assert_equals(list[exposedName], list.item(exposedNames[exposedName])); + assert_true(list[exposedName] instanceof Element); + } + + var unexposedNames = ['qux']; + for (var unexposedName of unexposedNames) { + assert_false(unexposedName in list); + assert_false(list.hasOwnProperty(unexposedName)); + assert_equals(list[unexposedName], undefined); + assert_equals(list.namedItem(unexposedName), null); + } +}); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-classlist.html b/testing/web-platform/tests/dom/nodes/Element-classlist.html new file mode 100644 index 000000000..22b499e93 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-classlist.html @@ -0,0 +1,407 @@ +<!doctype html> +<html> + <head class="test test"> + <title class=" ">Element.classList in case-sensitive documents</title> + <link rel="help" href="https://dom.spec.whatwg.org/#concept-class"> + <script type="text/javascript" src="/resources/testharness.js"></script> + <script type="text/javascript" src="/resources/testharnessreport.js"></script> + <style type="text/css"> +.foo { font-style: italic; } + </style> + <script type="text/javascript"> +var elem = document.getElementsByTagName('title')[0], secondelem = document.getElementsByTagName('head')[0]; +test(function () { + assert_equals( typeof elem.classList, 'object', 'critical test; ignore any results after this' ); +}, 'Element.classList must exist as an object'); +test(function () { + assert_equals( typeof document.documentElement.classList, 'object' ); +}, 'Element.classList must exist as an object even if the element has no class attribute'); +test(function () { + assert_true( !!window.DOMTokenList ); +}, 'DOMTokenList should be exposed for prototyping'); +test(function () { + DOMTokenList.prototype.customProperty = true; + assert_true( elem.classList.customProperty ); +}, 'prototyping DOMTokenList should work'); +test(function () { + assert_true( elem.classList instanceof window.DOMTokenList ); + assert_equals( elem.classList.constructor, window.DOMTokenList ); +}, 'Element.classList must implement DOMTokenList'); +test(function () { + assert_not_equals( getComputedStyle(elem,null).fontStyle, 'italic', 'critical test; required by the testsuite' ); +}, 'CSS .foo selectors must not match elements without any class'); +test(function () { + assert_equals( secondelem.classList.length, 1, 'duplicates in initial string should be removed per https://dom.spec.whatwg.org/#concept-class' ); + assert_equals( secondelem.classList.item(0), 'test' ); + assert_true( secondelem.classList.contains('test') ); +}, 'classList must be correct for an element that has classes'); +test(function () { + assert_equals( elem.classList.length, 0 ); +}, 'classList.length must be 0 for an element that has no classes'); +test(function () { + assert_false( elem.classList.contains('foo') ); +}, 'classList must not contain an undefined class'); +test(function () { + assert_equals( elem.classList.item(0), null ); +}, 'classList.item() must return null for out-of-range index'); +test(function () { + assert_equals( elem.classList.item(-1), null ); +}, 'classList.item() must return null for negative index'); +test(function () { + /* the normative part of the spec states that: + "unless tokens is empty, in which case there are no supported property indices" + ... + "The term[...] supported property indices [is] used as defined in the WebIDL specification." + WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */ + assert_equals( elem.classList[0], undefined ); +}, 'classList[index] must be undefined for out-of-range index'); +test(function () { + assert_equals( elem.classList[-1], undefined ); +}, 'classList[index] must be undefined for negative index'); +test(function () { + assert_equals( elem.className, ' ' ); +}, 'className should contain initial markup whitespace'); +test(function () { + assert_equals( elem.classList + '', ' ', 'implicit' ); + assert_equals( elem.classList.toString(), ' ', 'explicit' ); +}, 'classList should contain initial markup whitespace'); +test(function () { + assert_false( elem.classList.contains('') ); +}, '.contains(empty_string) must return false'); +test(function () { + assert_throws( 'SYNTAX_ERR', function () { elem.classList.add(''); } ); +}, '.add(empty_string) must throw a SYNTAX_ERR'); +test(function () { + assert_throws( 'SYNTAX_ERR', function () { elem.classList.remove(''); } ); +}, '.remove(empty_string) must throw a SYNTAX_ERR'); +test(function () { + assert_throws( 'SYNTAX_ERR', function () { elem.classList.toggle(''); } ); +}, '.toggle(empty_string) must throw a SYNTAX_ERR'); +test(function () { + assert_throws( 'SYNTAX_ERR', function () { elem.classList.replace('', 'foo'); } ); + assert_throws( 'SYNTAX_ERR', function () { elem.classList.replace('foo', ''); } ); + assert_throws( 'SYNTAX_ERR', function () { elem.classList.replace('', 'foo bar'); } ); + assert_throws( 'SYNTAX_ERR', function () { elem.classList.replace('foo bar', ''); } ); + assert_throws( 'SYNTAX_ERR', function () { elem.classList.replace('', ''); } ); +}, '.replace with empty_string must throw a SYNTAX_ERR'); +test(function () { + assert_false( elem.classList.contains('a b') ); +}, '.contains(string_with_spaces) must return false'); +test(function () { + assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.add('a b'); } ); +}, '.add(string_with_spaces) must throw an INVALID_CHARACTER_ERR'); +test(function () { + assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.remove('a b'); } ); +}, '.remove(string_with_spaces) must throw an INVALID_CHARACTER_ERR'); +test(function () { + assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.toggle('a b'); } ); +}, '.toggle(string_with_spaces) must throw an INVALID_CHARACTER_ERR'); +test(function () { + assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.replace('z', 'a b'); } ); + assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.replace('a b', 'z'); } ); + assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.replace('a b', 'b c'); } ); +}, '.replace with string_with_spaces must throw a INVALID_CHARACTER_ERR'); +test(function () { + var foo = document.createElement('div'); + foo.className = 'token1 token2 token3' + foo.classList.replace('token1', 'token3'); + assert_equals( foo.classList.length, 2 ); + assert_false( foo.classList.contains('token1') ); + assert_true( foo.classList.contains('token2') ); + assert_true( foo.classList.contains('token3') ); +}, '.replace with an already existing token') +elem.className = 'foo'; +test(function () { + assert_equals( getComputedStyle(elem,null).fontStyle, 'italic', 'critical test; required by the testsuite' ); +}, 'computed style must update when setting .className'); +test(function () { + assert_true( elem.classList.contains('foo') ); +}, 'classList.contains must update when .className is changed'); +test(function () { + assert_false( elem.classList.contains('FOO') ); +}, 'classList.contains must be case sensitive'); +test(function () { + assert_false( elem.classList.contains('foo.') ); + assert_false( elem.classList.contains('foo)') ); + assert_false( elem.classList.contains('foo\'') ); + assert_false( elem.classList.contains('foo$') ); + assert_false( elem.classList.contains('foo~') ); + assert_false( elem.classList.contains('foo?') ); + assert_false( elem.classList.contains('foo\\') ); +}, 'classList.contains must not match when punctuation characters are added'); +test(function () { + elem.classList.add('FOO'); + assert_equals( getComputedStyle(elem,null).fontStyle, 'italic' ); +}, 'classList.add must not cause the CSS selector to stop matching'); +test(function () { + assert_true( elem.classList.contains('foo') ); +}, 'classList.add must not remove existing classes'); +test(function () { + assert_true( elem.classList.contains('FOO') ); +}, 'classList.contains case sensitivity must match a case-specific string'); +test(function () { + assert_equals( elem.classList.length, 2 ); +}, 'classList.length must correctly reflect the number of tokens'); +test(function () { + assert_equals( elem.classList.item(0), 'foo' ); +}, 'classList.item(0) must return the first token'); +test(function () { + assert_equals( elem.classList.item(1), 'FOO' ); +}, 'classList.item must return case-sensitive strings and preserve token order'); +test(function () { + assert_equals( elem.classList[0], 'foo' ); +}, 'classList[0] must return the first token'); +test(function () { + assert_equals( elem.classList[1], 'FOO' ); +}, 'classList[index] must return case-sensitive strings and preserve token order'); +test(function () { + /* the normative part of the spec states that: + "The object's supported property indices are the numbers in the range zero to the number of tokens in tokens minus one" + ... + "The term[...] supported property indices [is] used as defined in the WebIDL specification." + WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */ + assert_equals( elem.classList[2], undefined ); +}, 'classList[index] must still be undefined for out-of-range index when earlier indexes exist'); +test(function () { + assert_equals( elem.className, 'foo FOO' ); +}, 'className must update correctly when items have been added through classList'); +test(function () { + assert_equals( elem.classList + '', 'foo FOO', 'implicit' ); + assert_equals( elem.classList.toString(), 'foo FOO', 'explicit' ); +}, 'classList must stringify correctly when items have been added'); +test(function () { + elem.classList.add('foo'); + assert_equals( elem.classList.length, 2 ); + assert_equals( elem.classList + '', 'foo FOO', 'implicit' ); + assert_equals( elem.classList.toString(), 'foo FOO', 'explicit' ); +}, 'classList.add should not add a token if it already exists'); +test(function () { + elem.classList.remove('bar'); + assert_equals( elem.classList.length, 2 ); + assert_equals( elem.classList + '', 'foo FOO', 'implicit' ); + assert_equals( elem.classList.toString(), 'foo FOO', 'explicit' ); +}, 'classList.remove removes arguments passed, if they are present.'); +test(function () { + elem.classList.remove('foo'); + assert_equals( elem.classList.length, 1 ); + assert_equals( elem.classList + '', 'FOO', 'implicit' ); + assert_equals( elem.classList.toString(), 'FOO', 'explicit' ); + assert_false( elem.classList.contains('foo') ); + assert_true( elem.classList.contains('FOO') ); +}, 'classList.remove must remove existing tokens'); +test(function () { + assert_not_equals( getComputedStyle(elem,null).fontStyle, 'italic' ); +}, 'classList.remove must not break case-sensitive CSS selector matching'); +test(function () { + secondelem.classList.remove('test'); + assert_equals( secondelem.classList.length, 0 ); + assert_false( secondelem.classList.contains('test') ); +}, 'classList.remove must remove duplicated tokens'); +test(function () { + secondelem.className = 'token1 token2 token3'; + secondelem.classList.remove('token2'); + assert_equals( secondelem.classList + '', 'token1 token3', 'implicit' ); + assert_equals( secondelem.classList.toString(), 'token1 token3', 'explicit' ); +}, 'classList.remove must collapse whitespace around removed tokens'); +test(function () { + secondelem.className = ' token1 token2 '; + secondelem.classList.remove('token2'); + assert_equals( secondelem.classList + '', 'token1', 'implicit' ); + assert_equals( secondelem.classList.toString(), 'token1', 'explicit' ); +}, 'classList.remove must collapse whitespaces around each token'); +test(function () { + secondelem.className = ' token1 token2 token1 '; + secondelem.classList.remove('token2'); + assert_equals( secondelem.classList + '', 'token1', 'implicit' ); + assert_equals( secondelem.classList.toString(), 'token1', 'explicit' ); +}, 'classList.remove must collapse whitespaces around each token and remove duplicates'); +test(function () { + secondelem.className = ' token1 token2 token1 '; + secondelem.classList.remove('token1'); + assert_equals( secondelem.classList + '', 'token2', 'implicit' ); + assert_equals( secondelem.classList.toString(), 'token2', 'explicit' ); +}, 'classList.remove must collapse whitespace when removing duplicate tokens'); +test(function () { + secondelem.className = ' token1 token1 '; + secondelem.classList.add('token1'); + assert_equals( secondelem.classList + '', 'token1', 'implicit' ); + assert_equals( secondelem.classList.toString(), 'token1', 'explicit' ); +}, 'classList.add must collapse whitespaces and remove duplicates when adding a token that already exists'); +test(function () { + assert_true(elem.classList.toggle('foo')); + assert_equals( elem.classList.length, 2 ); + assert_true( elem.classList.contains('foo') ); + assert_true( elem.classList.contains('FOO') ); +}, 'classList.toggle must toggle tokens case-sensitively when adding'); +test(function () { + assert_equals( getComputedStyle(elem,null).fontStyle, 'italic' ); +}, 'classList.toggle must not break case-sensitive CSS selector matching'); +test(function () { + assert_false(elem.classList.toggle('foo')); +}, 'classList.toggle must be able to remove tokens'); +test(function () { + //will return true if the last test incorrectly removed both + assert_false(elem.classList.toggle('FOO')); + assert_false( elem.classList.contains('foo') ); + assert_false( elem.classList.contains('FOO') ); +}, 'classList.toggle must be case-sensitive when removing tokens'); +test(function () { + secondelem.className = 'foo FOO' + secondelem.classList.replace('bar', 'baz'); + assert_equals( secondelem.classList.length, 2 ); + assert_equals( secondelem.classList + '', 'foo FOO', 'implicit' ); + assert_equals( secondelem.classList.toString(), 'foo FOO', 'explicit' ); +}, 'classList.replace replaces arguments passed, if they are present.'); +test(function () { + secondelem.classList.replace('foo', 'bar'); + assert_equals( secondelem.classList.length, 2 ); + assert_equals( secondelem.classList + '', 'bar FOO', 'implicit' ); + assert_equals( secondelem.classList.toString(), 'bar FOO', 'explicit' ); + assert_false( secondelem.classList.contains('foo') ); + assert_true( secondelem.classList.contains('bar') ); + assert_true( secondelem.classList.contains('FOO') ); +}, 'classList.replace must replace existing tokens'); +test(function () { + assert_not_equals( getComputedStyle(secondelem,null).fontStyle, 'italic' ); +}, 'classList.replace must not break case-sensitive CSS selector matching'); +test(function () { + secondelem.className = 'token1 token2 token1' + secondelem.classList.replace('token1', 'token3'); + assert_equals( secondelem.classList.length, 2 ); + assert_false( secondelem.classList.contains('token1') ); + assert_true( secondelem.classList.contains('token2') ); + assert_true( secondelem.classList.contains('token3') ); +}, 'classList.replace must replace duplicated tokens'); +test(function () { + secondelem.className = 'token1 token2 token3'; + secondelem.classList.replace('token2', 'token4'); + assert_equals( secondelem.classList + '', 'token1 token4 token3', 'implicit' ); + assert_equals( secondelem.classList.toString(), 'token1 token4 token3', 'explicit' ); +}, 'classList.replace must collapse whitespace around replaced tokens'); +test(function () { + secondelem.className = ' token1 token2 '; + secondelem.classList.replace('token2', 'token3'); + assert_equals( secondelem.classList.length, 2 ); + assert_equals( secondelem.classList + '', 'token1 token3', 'implicit' ); + assert_equals( secondelem.classList.toString(), 'token1 token3', 'explicit' ); +}, 'classList.replace must collapse whitespaces around each token'); +test(function () { + secondelem.className = ' token1 token2 token1 '; + secondelem.classList.replace('token2', 'token3'); + assert_equals( secondelem.classList + '', 'token1 token3', 'implicit' ); + assert_equals( secondelem.classList.toString(), 'token1 token3', 'explicit' ); +}, 'classList.replace must collapse whitespaces around each token and remove duplicates'); +test(function () { + secondelem.className = ' token1 token2 token1 '; + secondelem.classList.replace('token1', 'token3'); + assert_equals( secondelem.classList + '', 'token3 token2', 'implicit' ); + assert_equals( secondelem.classList.toString(), 'token3 token2', 'explicit' ); +}, 'classList.replace must collapse whitespace when replacing duplicate tokens'); +test(function () { + assert_not_equals( getComputedStyle(elem,null).fontStyle, 'italic' ); +}, 'CSS class selectors must stop matching when all classes have been removed'); +test(function () { + assert_equals( elem.className, '' ); +}, 'className must be empty when all classes have been removed'); +test(function () { + assert_equals( elem.classList + '', '', 'implicit' ); + assert_equals( elem.classList.toString(), '', 'explicit' ); +}, 'classList must stringify to an empty string when all classes have been removed'); +test(function () { + assert_equals( elem.classList.item(0), null ); +}, 'classList.item(0) must return null when all classes have been removed'); +test(function () { + /* the normative part of the spec states that: + "unless the length is zero, in which case there are no supported property indices" + ... + "The term[...] supported property indices [is] used as defined in the WebIDL specification." + WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */ + assert_equals( elem.classList[0], undefined ); +}, 'classList[0] must be undefined when all classes have been removed'); +test(function () { + var foo = document.createElement('div'); + foo.classList.add(); + assert_true( foo.hasAttribute('class') ); + assert_equals( foo.classList + '', '', 'implicit' ); + assert_equals( foo.classList.toString(), '', 'explicit' ); +}, 'Invoking add or remove should set the class attribute'); +// The ordered set parser must skip ASCII whitespace (U+0009, U+000A, U+000C, U+000D, and U+0020.) +test(function () { + var foo = document.createElement('div'); + foo.className = 'a '; + foo.classList.add('b'); + assert_equals(foo.className,'a b'); +}, 'classList.add should treat " " as a space'); +test(function () { + var foo = document.createElement('div'); + foo.className = 'a\t'; + foo.classList.add('b'); + assert_equals(foo.className,'a b'); +}, 'classList.add should treat \\t as a space'); +test(function () { + var foo = document.createElement('div'); + foo.className = 'a\r'; + foo.classList.add('b'); + assert_equals(foo.className,'a b'); +}, 'classList.add should treat \\r as a space'); +test(function () { + var foo = document.createElement('div'); + foo.className = 'a\n'; + foo.classList.add('b'); + assert_equals(foo.className,'a b'); +}, 'classList.add should treat \\n as a space'); +test(function () { + var foo = document.createElement('div'); + foo.className = 'a\f'; + foo.classList.add('b'); + assert_equals(foo.className,'a b'); +}, 'classList.add should treat \\f as a space'); +test(function () { + //WebIDL and ECMAScript 5 - a readonly property has a getter but not a setter + //ES5 makes [[Put]] fail but not throw + var failed = false; + secondelem.className = 'token1'; + try { + secondelem.classList.length = 0; + } catch(e) { + failed = e; + } + assert_equals(secondelem.classList.length,1); + assert_false(failed,'an error was thrown'); +}, 'classList.length must be read-only'); +test(function () { + var realList = secondelem.classList; + secondelem.classList = 'foo bar'; + assert_equals(secondelem.classList,realList); + assert_equals(secondelem.classList.length,2); + assert_equals(secondelem.classList[0],'foo'); + assert_equals(secondelem.classList[1],'bar'); +}, 'classList must have [PutForwards=value]'); +test(function () { + var foo = document.createElement('div'); + foo.className = 'a'; + foo.classList.replace('token1', 'token2'); + + assert_equals(foo.className, 'a'); + + foo.classList.replace('a', 'b'); + assert_equals(foo.className, 'b'); + + assert_throws('SYNTAX_ERR', function () { foo.classList.replace('t with space', '') }); + assert_throws('INVALID_CHARACTER_ERR', function () { foo.classList.replace('t with space', 'foo') }); + assert_throws('SYNTAX_ERR', function () { foo.classList.replace('', 'foo') }); +}, 'classList.replace should work'); + +test(function() { + var foo = document.createElement('div'); + assert_throws(new TypeError(), + function() { foo.classList.supports('hello') }); +}, 'classList.supports should throw'); + </script> + </head> + <body> + + <div id="log"></div> + + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Element-closest.html b/testing/web-platform/tests/dom/nodes/Element-closest.html new file mode 100644 index 000000000..386e3bd25 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-closest.html @@ -0,0 +1,73 @@ +<!DOCTYPE HTML> +<meta charset=utf8> +<title>Test for Element.closest</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body id="body"> + <div id="test8" class="div3" style="display:none"> + <div id="test7" class="div2"> + <div id="test6" class="div1"> + <form id="test10" class="form2"></form> + <form id="test5" class="form1" name="form-a"> + <input id="test1" class="input1" required> + <fieldset class="fieldset2" id="test2"> + <select id="test3" class="select1" required> + <option default id="test4" value="">Test4</option> + <option selected id="test11">Test11</option> + <option id="test12">Test12</option> + <option id="test13">Test13</option> + </select> + <input id="test9" type="text" required> + </fieldset> + </form> + </div> + </div> + </div> + <div id=log></div> +<script> + do_test("select" , "test12", "test3"); + do_test("fieldset" , "test13", "test2"); + do_test("div" , "test13", "test6"); + do_test("body" , "test3" , "body"); + + do_test("[default]" , "test4" , "test4"); + do_test("[selected]" , "test4" , ""); + do_test("[selected]" , "test11", "test11"); + do_test('[name="form-a"]' , "test12", "test5"); + do_test('form[name="form-a"]' , "test13", "test5"); + do_test("input[required]" , "test9" , "test9"); + do_test("select[required]" , "test9" , ""); + + do_test("div:not(.div1)" , "test13", "test7"); + do_test("div.div3" , "test6" , "test8"); + do_test("div#test7" , "test1" , "test7"); + + do_test(".div3 > .div2" , "test12", "test7"); + do_test(".div3 > .div1" , "test12", ""); + do_test("form > input[required]" , "test9" , ""); + do_test("fieldset > select[required]", "test12", "test3"); + + do_test("input + fieldset" , "test6" , ""); + do_test("form + form" , "test3" , "test5"); + do_test("form + form" , "test5" , "test5"); + + do_test(":empty" , "test10", "test10"); + do_test(":last-child" , "test11", "test2"); + do_test(":first-child" , "test12", "test3"); + do_test(":invalid" , "test11", "test2"); + + do_test(":scope" , "test4", "test4"); + do_test("select > :scope" , "test4", "test4"); + do_test("div > :scope" , "test4", ""); + do_test(":has(> :scope)" , "test4", "test3"); +function do_test(aSelector, aElementId, aTargetId) { + test(function() { + var el = document.getElementById(aElementId).closest(aSelector); + if (el === null) { + assert_equals("", aTargetId, aSelector); + } else { + assert_equals(el.id, aTargetId, aSelector); + } + }, "Element.closest with context node '" + aElementId + "' and selector '" + aSelector + "'"); +} +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-firstElementChild-entity-xhtml.xhtml b/testing/web-platform/tests/dom/nodes/Element-firstElementChild-entity-xhtml.xhtml new file mode 100644 index 000000000..f28005e9c --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-firstElementChild-entity-xhtml.xhtml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" +[ +<!ENTITY tree "<span id='first_element_child' style='font-weight:bold;'>unknown.</span>"> +]> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head> +<title>Entity References</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<h1>Test of Entity References</h1> +<div id="log"></div> +<p id="parentEl">The result of this test is &tree;</p> +<script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl") + var fec = parentEl.firstElementChild; + assert_true(!!fec) + assert_equals(fec.nodeType, 1) + assert_equals(fec.getAttribute("id"), "first_element_child") +}) +]]></script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Element-firstElementChild-entity.svg b/testing/web-platform/tests/dom/nodes/Element-firstElementChild-entity.svg new file mode 100644 index 000000000..3a20ea79a --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-firstElementChild-entity.svg @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" +[ +<!ENTITY tree "<tspan id='first_element_child' font-weight='bold'>unknown.</tspan>"> +]> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:h="http://www.w3.org/1999/xhtml" + version="1.1" + width="100%" height="100%" viewBox="0 0 400 400"> +<title>Entity References</title> +<h:script src="/resources/testharness.js"/> +<h:script src="/resources/testharnessreport.js"/> + +<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of Entity References</text> +<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle">The result of this test is &tree;</text> + +<h:script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl") + var fec = parentEl.firstElementChild; + assert_true(!!fec) + assert_equals(fec.nodeType, 1) + assert_equals(fec.getAttribute("id"), "first_element_child") +}) +]]></h:script> +</svg> diff --git a/testing/web-platform/tests/dom/nodes/Element-firstElementChild-namespace-svg.svg b/testing/web-platform/tests/dom/nodes/Element-firstElementChild-namespace-svg.svg new file mode 100644 index 000000000..d42c08777 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-firstElementChild-namespace-svg.svg @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:h="http://www.w3.org/1999/xhtml" + xmlns:pickle="http://ns.example.org/pickle" + version="1.1" + width="100%" height="100%" viewBox="0 0 400 400"> +<title>firstElementChild with namespaces</title> +<h:script src="/resources/testharness.js"/> +<h:script src="/resources/testharnessreport.js"/> + +<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of firstElementChild with namespaces</text> +<g id="parentEl"> + <pickle:dill id="first_element_child"/> +</g> + +<h:script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl"); + var fec = parentEl.firstElementChild; + assert_true(!!fec) + assert_equals(fec.nodeType, 1) + assert_equals(fec.getAttribute("id"), "first_element_child") + assert_equals(fec.localName, "dill") +}) +]]></h:script> +</svg> diff --git a/testing/web-platform/tests/dom/nodes/Element-firstElementChild-namespace-xhtml.xhtml b/testing/web-platform/tests/dom/nodes/Element-firstElementChild-namespace-xhtml.xhtml new file mode 100644 index 000000000..29441d278 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-firstElementChild-namespace-xhtml.xhtml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<html xmlns="http://www.w3.org/1999/xhtml" + xmlns:pickle="http://ns.example.org/pickle"> +<head> +<title>firstElementChild with namespaces</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<h1>Test of firstElementChild with namespaces</h1> +<div id="parentEl"> + <pickle:dill id="first_element_child"/> +</div> +<div id="log"></div> +<p id="parentEl">The result of this test is +<span id="first_element_child" style="font-weight:bold;">logged above.</span></p> +<script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl"); + var fec = parentEl.firstElementChild; + assert_true(!!fec) + assert_equals(fec.nodeType, 1) + assert_equals(fec.getAttribute("id"), "first_element_child") + assert_equals(fec.localName, "dill") +}) +]]></script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Element-firstElementChild-namespace.html b/testing/web-platform/tests/dom/nodes/Element-firstElementChild-namespace.html new file mode 100644 index 000000000..629deab3a --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-firstElementChild-namespace.html @@ -0,0 +1,21 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>firstElementChild with namespaces</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<h1>Test of firstElementChild with namespaces</h1> +<div id="log"></div> +<p id="parentEl">The result of this test is a unknown.</p> +<script> +test(function() { + var parentEl = document.getElementById("parentEl") + var el = document.createElementNS("http://ns.example.org/pickle", "pickle:dill") + el.setAttribute("id", "first_element_child") + parentEl.appendChild(el) + var fec = parentEl.firstElementChild + assert_true(!!fec) + assert_equals(fec.nodeType, 1) + assert_equals(fec.getAttribute("id"), "first_element_child") + assert_equals(fec.localName, "dill") +}) +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-firstElementChild-svg.svg b/testing/web-platform/tests/dom/nodes/Element-firstElementChild-svg.svg new file mode 100644 index 000000000..359c5b82c --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-firstElementChild-svg.svg @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:h="http://www.w3.org/1999/xhtml" + version="1.1" + width="100%" height="100%" viewBox="0 0 400 400"> +<title>firstElementChild</title> +<h:script src="/resources/testharness.js"/> +<h:script src="/resources/testharnessreport.js"/> + +<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of firstElementChild</text> +<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle">The result of this test is +<tspan id="first_element_child" font-weight="bold">unknown.</tspan></text> + +<h:script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl"); + var fec = parentEl.firstElementChild; + assert_true(!!fec) + assert_equals(fec.nodeType, 1) + assert_equals(fec.getAttribute("id"), "first_element_child") +}) +]]></h:script> +</svg> diff --git a/testing/web-platform/tests/dom/nodes/Element-firstElementChild-xhtml.xhtml b/testing/web-platform/tests/dom/nodes/Element-firstElementChild-xhtml.xhtml new file mode 100644 index 000000000..302052b0f --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-firstElementChild-xhtml.xhtml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>firstElementChild</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<h1>Test of firstElementChild</h1> +<div id="log"></div> +<p id="parentEl">The result of this test is +<span id="first_element_child" style="font-weight:bold;">logged above.</span></p> +<script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl"); + var fec = parentEl.firstElementChild; + assert_true(!!fec) + assert_equals(fec.nodeType, 1) + assert_equals(fec.getAttribute("id"), "first_element_child") +}) +]]></script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Element-firstElementChild.html b/testing/web-platform/tests/dom/nodes/Element-firstElementChild.html new file mode 100644 index 000000000..12a0c5946 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-firstElementChild.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>firstElementChild</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<h1>Test of firstElementChild</h1> +<div id="log"></div> +<p id="parentEl">The result of this test is +<span id="first_element_child" style="font-weight:bold;">logged above.</span></p> +<script> +test(function() { + var parentEl = document.getElementById("parentEl"); + var fec = parentEl.firstElementChild; + assert_true(!!fec) + assert_equals(fec.nodeType, 1) + assert_equals(fec.getAttribute("id"), "first_element_child") +}) +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-getElementsByClassName.html b/testing/web-platform/tests/dom/nodes/Element-getElementsByClassName.html new file mode 100644 index 000000000..332c3060f --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-getElementsByClassName.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<title>Element.getElementsByClassName</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + var a = document.createElement("a"), b = document.createElement("b") + b.className = "foo" + a.appendChild(b) + var list = a.getElementsByClassName("foo") + assert_array_equals(list, [b]) + var secondList = a.getElementsByClassName("foo") + assert_true(list === secondList || list !== secondList, "Caching is allowed.") +}, "getElementsByClassName should work on disconnected subtrees.") +test(function() { + var list = document.getElementsByClassName("foo") + assert_false(list instanceof NodeList, "NodeList") + assert_true(list instanceof HTMLCollection, "HTMLCollection") +}, "Interface should be correct.") +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-getElementsByTagName-change-document-HTMLNess-iframe.xml b/testing/web-platform/tests/dom/nodes/Element-getElementsByTagName-change-document-HTMLNess-iframe.xml new file mode 100644 index 000000000..f3f286eaf --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-getElementsByTagName-change-document-HTMLNess-iframe.xml @@ -0,0 +1 @@ +<root/> diff --git a/testing/web-platform/tests/dom/nodes/Element-getElementsByTagName-change-document-HTMLNess.html b/testing/web-platform/tests/dom/nodes/Element-getElementsByTagName-change-document-HTMLNess.html new file mode 100644 index 000000000..cc118d42c --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-getElementsByTagName-change-document-HTMLNess.html @@ -0,0 +1,50 @@ +<!doctype html> +<meta charset=utf-8> +<title></title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<iframe src="Element-getElementsByTagName-change-document-HTMLNess-iframe.xml"></iframe> +<script> + onload = function() { + var parent = document.createElement("div"); + var child1 = document.createElementNS("http://www.w3.org/1999/xhtml", "a"); + child1.textContent = "xhtml:a"; + var child2 = document.createElementNS("http://www.w3.org/1999/xhtml", "A"); + child2.textContent = "xhtml:A"; + var child3 = document.createElementNS("", "a"); + child3.textContent = "a"; + var child4 = document.createElementNS("", "A"); + child4.textContent = "A"; + + parent.appendChild(child1); + parent.appendChild(child2); + parent.appendChild(child3); + parent.appendChild(child4); + + var list = parent.getElementsByTagName("A"); + assert_array_equals(list, [child1, child4], + "In an HTML document, should lowercase the tagname passed in for HTML " + + "elements only"); + + frames[0].document.documentElement.appendChild(parent); + assert_array_equals(list, [child1, child4], + "After changing document, should still be lowercasing for HTML"); + + assert_array_equals(parent.getElementsByTagName("A"), + [child2, child4], + "New list with same root and argument should not be lowercasing now"); + + // Now reinsert all those nodes into the parent, to blow away caches. + parent.appendChild(child1); + parent.appendChild(child2); + parent.appendChild(child3); + parent.appendChild(child4); + assert_array_equals(list, [child1, child4], + "After blowing away caches, should still have the same list"); + + assert_array_equals(parent.getElementsByTagName("A"), + [child2, child4], + "New list with same root and argument should still not be lowercasing"); + done(); + } +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-getElementsByTagName.html b/testing/web-platform/tests/dom/nodes/Element-getElementsByTagName.html new file mode 100644 index 000000000..87c4fe934 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-getElementsByTagName.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Element.getElementsByTagName</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-element-getelementsbytagname"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="Document-Element-getElementsByTagName.js"></script> +<div id="log"></div> +<script> +var element; +setup(function() { + element = document.createElement("div"); + element.appendChild(document.createTextNode("text")); + var p = element.appendChild(document.createElement("p")); + p.appendChild(document.createElement("a")) + .appendChild(document.createTextNode("link")); + p.appendChild(document.createElement("b")) + .appendChild(document.createTextNode("bold")); + p.appendChild(document.createElement("em")) + .appendChild(document.createElement("u")) + .appendChild(document.createTextNode("emphasized")); + element.appendChild(document.createComment("comment")); +}); + +test_getElementsByTagName(element, element); + +test(function() { + assert_array_equals(element.getElementsByTagName(element.localName), []); +}, "Matching the context object"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-getElementsByTagNameNS.html b/testing/web-platform/tests/dom/nodes/Element-getElementsByTagNameNS.html new file mode 100644 index 000000000..f826afc39 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-getElementsByTagNameNS.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Element.getElementsByTagNameNS</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-element-getelementsbytagnamens"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="Document-Element-getElementsByTagNameNS.js"></script> +<div id="log"></div> +<script> +var element; +setup(function() { + element = document.createElement("div"); + element.appendChild(document.createTextNode("text")); + var p = element.appendChild(document.createElement("p")); + p.appendChild(document.createElement("a")) + .appendChild(document.createTextNode("link")); + p.appendChild(document.createElement("b")) + .appendChild(document.createTextNode("bold")); + p.appendChild(document.createElement("em")) + .appendChild(document.createElement("u")) + .appendChild(document.createTextNode("emphasized")); + element.appendChild(document.createComment("comment")); +}); + +test_getElementsByTagNameNS(element, element); + +test(function() { + assert_array_equals(element.getElementsByTagNameNS("*", element.localName), []); +}, "Matching the context object (wildcard namespace)"); + +test(function() { + assert_array_equals( + element.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", + element.localName), + []); +}, "Matching the context object (specific namespace)"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-hasAttributes.html b/testing/web-platform/tests/dom/nodes/Element-hasAttributes.html new file mode 100644 index 000000000..fbb9c233b --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-hasAttributes.html @@ -0,0 +1,40 @@ +<!doctype html> +<meta charset="utf-8"> +<title></title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> + +<button></button> +<div id="foo"></div> +<p data-foo=""></p> + +<script> +test(function() { + var buttonElement = document.getElementsByTagName('button')[0]; + assert_equals(buttonElement.hasAttributes(), false, 'hasAttributes() on empty element must return false.'); + + var emptyDiv = document.createElement('div'); + assert_equals(emptyDiv.hasAttributes(), false, 'hasAttributes() on dynamically created empty element must return false.'); + +}, 'element.hasAttributes() must return false when the element does not have attribute.'); + +test(function() { + var divWithId = document.getElementById('foo'); + assert_equals(divWithId.hasAttributes(), true, 'hasAttributes() on element with id attribute must return true.'); + + var divWithClass = document.createElement('div'); + divWithClass.setAttribute('class', 'foo'); + assert_equals(divWithClass.hasAttributes(), true, 'hasAttributes() on dynamically created element with class attribute must return true.'); + + var pWithCustomAttr = document.getElementsByTagName('p')[0]; + assert_equals(pWithCustomAttr.hasAttributes(), true, 'hasAttributes() on element with custom attribute must return true.'); + + var divWithCustomAttr = document.createElement('div'); + divWithCustomAttr.setAttribute('data-custom', 'foo'); + assert_equals(divWithCustomAttr.hasAttributes(), true, 'hasAttributes() on dynamically created element with custom attribute must return true.'); + +}, 'element.hasAttributes() must return true when the element has attribute.'); + +</script> +</body> diff --git a/testing/web-platform/tests/dom/nodes/Element-insertAdjacentElement.html b/testing/web-platform/tests/dom/nodes/Element-insertAdjacentElement.html new file mode 100644 index 000000000..d03e56680 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-insertAdjacentElement.html @@ -0,0 +1,91 @@ +<!doctype html> +<meta charset=utf-8> +<title></title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> + +<div id="target"></div> +<div id="parent"><span id=target2></span></div> +<div id="log" style="visibility:visible"></div> +<span id="test1"></span> +<span id="test2"></span> +<span id="test3"></span> +<span id="test4"></span> +<script> +var target = document.getElementById("target"); +var target2 = document.getElementById("target2"); + +test(function() { + assert_throws("SyntaxError", function() { + target.insertAdjacentElement("test", document.getElementById("test1")) + }); + + assert_throws("SyntaxError", function() { + target2.insertAdjacentElement("test", document.getElementById("test1")) + }); +}, "Inserting to an invalid location should cause a Syntax Error exception") + +test(function() { + var el = target.insertAdjacentElement("beforebegin", document.getElementById("test1")); + assert_equals(target.previousSibling.id, "test1"); + assert_equals(el.id, "test1"); + + el = target2.insertAdjacentElement("beforebegin", document.getElementById("test1")); + assert_equals(target2.previousSibling.id, "test1"); + assert_equals(el.id, "test1"); +}, "Inserted element should be target element's previous sibling for 'beforebegin' case") + +test(function() { + var el = target.insertAdjacentElement("afterbegin", document.getElementById("test2")); + assert_equals(target.firstChild.id, "test2"); + assert_equals(el.id, "test2"); + + el = target2.insertAdjacentElement("afterbegin", document.getElementById("test2")); + assert_equals(target2.firstChild.id, "test2"); + assert_equals(el.id, "test2"); +}, "Inserted element should be target element's first child for 'afterbegin' case") + +test(function() { + var el = target.insertAdjacentElement("beforeend", document.getElementById("test3")); + assert_equals(target.lastChild.id, "test3"); + assert_equals(el.id, "test3"); + + el = target2.insertAdjacentElement("beforeend", document.getElementById("test3")); + assert_equals(target2.lastChild.id, "test3"); + assert_equals(el.id, "test3"); +}, "Inserted element should be target element's last child for 'beforeend' case") + +test(function() { + var el = target.insertAdjacentElement("afterend", document.getElementById("test4")); + assert_equals(target.nextSibling.id, "test4"); + assert_equals(el.id, "test4"); + + el = target2.insertAdjacentElement("afterend", document.getElementById("test4")); + assert_equals(target2.nextSibling.id, "test4"); + assert_equals(el.id, "test4"); +}, "Inserted element should be target element's next sibling for 'afterend' case") + +test(function() { + var docElement = document.documentElement; + docElement.style.visibility="hidden"; + + assert_throws("HierarchyRequestError", function() { + var el = docElement.insertAdjacentElement("beforebegin", document.getElementById("test1")); + assert_equals(el, null); + }); + + var el = docElement.insertAdjacentElement("afterbegin", document.getElementById("test2")); + assert_equals(docElement.firstChild.id, "test2"); + assert_equals(el.id, "test2"); + + el = docElement.insertAdjacentElement("beforeend", document.getElementById("test3")); + assert_equals(docElement.lastChild.id, "test3"); + assert_equals(el.id, "test3"); + + assert_throws("HierarchyRequestError", function() { + var el = docElement.insertAdjacentElement("afterend", document.getElementById("test4")); + assert_equals(el, null); + }); +}, "Adding more than one child to document should cause a HierarchyRequestError exception") + +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-insertAdjacentText.html b/testing/web-platform/tests/dom/nodes/Element-insertAdjacentText.html new file mode 100644 index 000000000..0fafabb51 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-insertAdjacentText.html @@ -0,0 +1,76 @@ +<!doctype html> +<meta charset=utf-8> +<title></title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<body style="visibility:hidden"> +<div id="target"></div> +<div id="parent"><span id=target2></span></div> +<div id="log" style="visibility:visible"></div> +</body> +<script> +var target = document.getElementById("target"); +var target2 = document.getElementById("target2"); + +test(function() { + assert_throws("SyntaxError", function() { + target.insertAdjacentText("test", "text") + }); + + assert_throws("SyntaxError", function() { + target2.insertAdjacentText("test", "test") + }); +}, "Inserting to an invalid location should cause a Syntax Error exception") + +test(function() { + target.insertAdjacentText("beforebegin", "test1"); + assert_equals(target.previousSibling.nodeValue, "test1"); + + target2.insertAdjacentText("beforebegin", "test1"); + assert_equals(target2.previousSibling.nodeValue, "test1"); +}, "Inserted text node should be target element's previous sibling for 'beforebegin' case") + +test(function() { + target.insertAdjacentText("afterbegin", "test2"); + assert_equals(target.firstChild.nodeValue, "test2"); + + target2.insertAdjacentText("afterbegin", "test2"); + assert_equals(target2.firstChild.nodeValue, "test2"); +}, "Inserted text node should be target element's first child for 'afterbegin' case") + +test(function() { + target.insertAdjacentText("beforeend", "test3"); + assert_equals(target.lastChild.nodeValue, "test3"); + + target2.insertAdjacentText("beforeend", "test3"); + assert_equals(target2.lastChild.nodeValue, "test3"); +}, "Inserted text node should be target element's last child for 'beforeend' case") + +test(function() { + target.insertAdjacentText("afterend", "test4"); + assert_equals(target.nextSibling.nodeValue, "test4"); + + target2.insertAdjacentText("afterend", "test4"); + assert_equals(target.nextSibling.nodeValue, "test4"); +}, "Inserted text node should be target element's next sibling for 'afterend' case") + +test(function() { + var docElement = document.documentElement; + docElement.style.visibility="hidden"; + + assert_throws("HierarchyRequestError", function() { + docElement.insertAdjacentText("beforebegin", "text1") + }); + + docElement.insertAdjacentText("afterbegin", "test2"); + assert_equals(docElement.firstChild.nodeValue, "test2"); + + docElement.insertAdjacentText("beforeend", "test3"); + assert_equals(docElement.lastChild.nodeValue, "test3"); + + assert_throws("HierarchyRequestError", function() { + docElement.insertAdjacentText("afterend", "test4") + }); +}, "Adding more than one child to document should cause a HierarchyRequestError exception") + +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-lastElementChild-svg.svg b/testing/web-platform/tests/dom/nodes/Element-lastElementChild-svg.svg new file mode 100644 index 000000000..1cec4a130 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-lastElementChild-svg.svg @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:h="http://www.w3.org/1999/xhtml" + version="1.1" + width="100%" height="100%" viewBox="0 0 400 400"> +<title>lastElementChild</title> +<h:script src="/resources/testharness.js"/> +<h:script src="/resources/testharnessreport.js"/> + +<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of lastElementChild</text> +<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle">The result of <tspan id="first_element_child">this test</tspan> is <tspan id="last_element_child" font-weight="bold">not</tspan> known.</text> + +<h:script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl"); + var lec = parentEl.lastElementChild; + assert_true(!!lec) + assert_equals(lec.nodeType, 1) + assert_equals(lec.getAttribute("id"), "last_element_child") +}) +]]></h:script> +</svg> diff --git a/testing/web-platform/tests/dom/nodes/Element-lastElementChild-xhtml.xhtml b/testing/web-platform/tests/dom/nodes/Element-lastElementChild-xhtml.xhtml new file mode 100644 index 000000000..3150b92a4 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-lastElementChild-xhtml.xhtml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>firstElementChild</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<h1>Test of firstElementChild</h1> +<div id="log"></div> +<p id="parentEl">The result of <span id="first_element_child">this test</span> is <span id="last_element_child" style="font-weight:bold;">logged</span> above.</p> +<script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl"); + var lec = parentEl.lastElementChild; + assert_true(!!lec) + assert_equals(lec.nodeType, 1) + assert_equals(lec.getAttribute("id"), "last_element_child") +}) +]]></script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Element-lastElementChild.html b/testing/web-platform/tests/dom/nodes/Element-lastElementChild.html new file mode 100644 index 000000000..de7aebdf2 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-lastElementChild.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>lastElementChild</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<h1>Test of lastElementChild</h1> +<div id="log"></div> +<p id="parentEl">The result of <span id="first_element_child">this test</span> is <span id="last_element_child" style="font-weight:bold;">logged</span> above.</p> +<script> +test(function() { + var parentEl = document.getElementById("parentEl"); + var lec = parentEl.lastElementChild; + assert_true(!!lec) + assert_equals(lec.nodeType, 1) + assert_equals(lec.getAttribute("id"), "last_element_child") +}) +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-matches.html b/testing/web-platform/tests/dom/nodes/Element-matches.html new file mode 100644 index 000000000..e04c0f9d1 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-matches.html @@ -0,0 +1,87 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>Selectors-API Level 2 Test Suite: HTML with Selectors Level 3</title> +<!-- Selectors API Test Suite Version 3 --> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/dom/nodes/selectors.js"></script> +<script src="/dom/nodes/ParentNode-querySelector-All.js"></script> +<script src="Element-matches.js"></script> +<style>iframe { visibility: hidden; position: absolute; }</style> + +<div id="log">This test requires JavaScript.</div> + +<script> +async_test(function() { + var frame = document.createElement("iframe"); + frame.onload = this.step_func_done(init); + frame.src = "/dom/nodes/ParentNode-querySelector-All-content.html#target"; + document.body.appendChild(frame); +}); + +function init(e) { + /* + * This test suite tests Selectors API methods in 4 different contexts: + * 1. Document node + * 2. In-document Element node + * 3. Detached Element node (an element with no parent, not in the document) + * 4. Document Fragment node + * + * For each context, the following tests are run: + * + * The interface check tests ensure that each type of node exposes the Selectors API methods. + * + * The matches() tests are run + * All the selectors tested for both the valid and invalid selector tests are found in selectors.js. + * See comments in that file for documentation of the format used. + * + * The level2-lib.js file contains all the common test functions for running each of the aforementioned tests + */ + + var docType = "html"; // Only run tests suitable for HTML + + // Prepare the nodes for testing + var doc = e.target.contentDocument; // Document Node tests + + var element = doc.getElementById("root"); // In-document Element Node tests + + //Setup the namespace tests + setupSpecialElements(doc, element); + + var outOfScope = element.cloneNode(true); // Append this to the body before running the in-document + // Element tests, but after running the Document tests. This + // tests that no elements that are not descendants of element + // are selected. + + traverse(outOfScope, function(elem) { // Annotate each element as being a clone; used for verifying + elem.setAttribute("data-clone", ""); // that none of these elements ever match. + }); + + + var detached = element.cloneNode(true); // Detached Element Node tests + + var fragment = doc.createDocumentFragment(); // Fragment Node tests + fragment.appendChild(element.cloneNode(true)); + + // Setup Tests + interfaceCheckMatches("Document", doc); + interfaceCheckMatches("Detached Element", detached); + interfaceCheckMatches("Fragment", fragment); + interfaceCheckMatches("In-document Element", element); + + runSpecialMatchesTests("DIV Element", element); + runSpecialMatchesTests("NULL Element", document.createElement("null")); + runSpecialMatchesTests("UNDEFINED Element", document.createElement("undefined")); + + runInvalidSelectorTestMatches("Document", doc, invalidSelectors); + runInvalidSelectorTestMatches("Detached Element", detached, invalidSelectors); + runInvalidSelectorTestMatches("Fragment", fragment, invalidSelectors); + runInvalidSelectorTestMatches("In-document Element", element, invalidSelectors); + + runMatchesTest("In-document", doc, validSelectors, "html"); + runMatchesTest("Detached", detached, validSelectors, "html"); + runMatchesTest("Fragment", fragment, validSelectors, "html"); + + runMatchesTest("In-document", doc, scopedSelectors, "html"); +} +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-matches.js b/testing/web-platform/tests/dom/nodes/Element-matches.js new file mode 100644 index 000000000..1bc0f3d08 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-matches.js @@ -0,0 +1,127 @@ +/* + * Check that the matches() method exists on the given Node + */ +function interfaceCheckMatches(type, obj) { + if (obj.nodeType === obj.ELEMENT_NODE) { + test(function() { + assert_idl_attribute(obj, "matches", type + " supports matches"); + }, type + " supports matches") + } +} + +function runSpecialMatchesTests(type, element) { + test(function() { // 1 + if (element.tagName.toLowerCase() === "null") { + assert_true(element.matches(null), "An element with the tag name '" + element.tagName.toLowerCase() + "' should match."); + } else { + assert_false(element.matches(null), "An element with the tag name '" + element.tagName.toLowerCase() + "' should not match."); + } + }, type + ".matches(null)") + + test(function() { // 2 + if (element.tagName.toLowerCase() === "undefined") { + assert_true(element.matches(undefined), "An element with the tag name '" + element.tagName.toLowerCase() + "' should match."); + } else { + assert_false(element.matches(undefined), "An element with the tag name '" + element.tagName.toLowerCase() + "' should not match."); + } + }, type + ".matches(undefined)") + + test(function() { // 3 + assert_throws(TypeError(), function() { + element.matches(); + }, "This should throw a TypeError.") + }, type + ".matches no parameter") +} + +/* + * Execute queries with the specified invalid selectors for matches() + * Only run these tests when errors are expected. Don't run for valid selector tests. + */ +function runInvalidSelectorTestMatches(type, root, selectors) { + if (root.nodeType === root.ELEMENT_NODE) { + for (var i = 0; i < selectors.length; i++) { + var s = selectors[i]; + var n = s["name"]; + var q = s["selector"]; + + test(function() { + assert_throws("SyntaxError", function() { + root.matches(q) + }) + }, type + ".matches: " + n + ": " + q); + } + } +} + +function runMatchesTest(type, root, selectors, docType) { + var nodeType = getNodeType(root); + + for (var i = 0; i < selectors.length; i++) { + var s = selectors[i]; + var n = s["name"]; + var q = s["selector"]; + var e = s["expect"]; + var u = s["unexpected"]; + + var ctx = s["ctx"]; + var ref = s["ref"]; + + if ((!s["exclude"] || (s["exclude"].indexOf(nodeType) === -1 && s["exclude"].indexOf(docType) === -1)) + && (s["testType"] & TEST_MATCH) ) { + + if (ctx && !ref) { + test(function() { + var j, element, refNode; + for (j = 0; j < e.length; j++) { + element = root.querySelector("#" + e[j]); + refNode = root.querySelector(ctx); + assert_true(element.matches(q, refNode), "The element #" + e[j] + " should match the selector.") + } + + if (u) { + for (j = 0; j < u.length; j++) { + element = root.querySelector("#" + u[j]); + refNode = root.querySelector(ctx); + assert_false(element.matches(q, refNode), "The element #" + u[j] + " should not match the selector.") + } + } + }, type + " Element.matches: " + n + " (with refNode Element): " + q); + } + + if (ref) { + test(function() { + var j, element, refNodes; + for (j = 0; j < e.length; j++) { + element = root.querySelector("#" + e[j]); + refNodes = root.querySelectorAll(ref); + assert_true(element.matches(q, refNodes), "The element #" + e[j] + " should match the selector.") + } + + if (u) { + for (j = 0; j < u.length; j++) { + element = root.querySelector("#" + u[j]); + refNodes = root.querySelectorAll(ref); + assert_false(element.matches(q, refNodes), "The element #" + u[j] + " should not match the selector.") + } + } + }, type + " Element.matches: " + n + " (with refNodes NodeList): " + q); + } + + if (!ctx && !ref) { + test(function() { + for (var j = 0; j < e.length; j++) { + var element = root.querySelector("#" + e[j]); + assert_true(element.matches(q), "The element #" + e[j] + " should match the selector.") + } + + if (u) { + for (j = 0; j < u.length; j++) { + element = root.querySelector("#" + u[j]); + assert_false(element.matches(q), "The element #" + u[j] + " should not match the selector.") + } + } + }, type + " Element.matches: " + n + " (with no refNodes): " + q); + } + } + } +} diff --git a/testing/web-platform/tests/dom/nodes/Element-nextElementSibling-svg.svg b/testing/web-platform/tests/dom/nodes/Element-nextElementSibling-svg.svg new file mode 100644 index 000000000..3e17cad20 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-nextElementSibling-svg.svg @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:h="http://www.w3.org/1999/xhtml" + version="1.1" + width="100%" height="100%" viewBox="0 0 400 400"> +<title>nextElementSibling</title> +<h:script src="/resources/testharness.js"/> +<h:script src="/resources/testharnessreport.js"/> + +<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of nextElementSibling</text> +<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle">The result of <tspan id="first_element_child">this test</tspan> is <tspan id="last_element_child" font-weight="bold">unknown.</tspan></text> + +<h:script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl"); + var fec = document.getElementById("first_element_child"); + var nes = fec.nextElementSibling; + assert_true(!!nes) + assert_equals(nes.nodeType, 1) + assert_equals(nes.getAttribute("id"), "last_element_child") +}) +]]></h:script> +</svg> diff --git a/testing/web-platform/tests/dom/nodes/Element-nextElementSibling-xhtml.xhtml b/testing/web-platform/tests/dom/nodes/Element-nextElementSibling-xhtml.xhtml new file mode 100644 index 000000000..915209bda --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-nextElementSibling-xhtml.xhtml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>nextElementSibling</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<h1>Test of nextElementSibling</h1> +<div id="log"></div> +<p id="parentEl">The result of <span id="first_element_child">this test</span> is <span id="last_element_child" style="font-weight:bold;">unknown.</span></p> +<script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl"); + var fec = document.getElementById("first_element_child"); + var nes = fec.nextElementSibling; + assert_true(!!nes) + assert_equals(nes.nodeType, 1) + assert_equals(nes.getAttribute("id"), "last_element_child") +}) +]]></script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Element-nextElementSibling.html b/testing/web-platform/tests/dom/nodes/Element-nextElementSibling.html new file mode 100644 index 000000000..985c602f4 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-nextElementSibling.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>nextElementSibling</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<h1>Test of nextElementSibling</h1> +<div id="log"></div> +<p id="parentEl">The result of <span id="first_element_child">this test</span> is <span id="last_element_child" style="font-weight:bold;">unknown.</span></p> +<script> +test(function() { + var parentEl = document.getElementById("parentEl"); + var fec = document.getElementById("first_element_child"); + var nes = fec.nextElementSibling; + assert_true(!!nes) + assert_equals(nes.nodeType, 1) + assert_equals(nes.getAttribute("id"), "last_element_child") +}) +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-previousElementSibling-svg.svg b/testing/web-platform/tests/dom/nodes/Element-previousElementSibling-svg.svg new file mode 100644 index 000000000..671d2c87f --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-previousElementSibling-svg.svg @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:h="http://www.w3.org/1999/xhtml" + version="1.1" + width="100%" height="100%" viewBox="0 0 400 400"> +<title>previousElementSibling</title> +<h:script src="/resources/testharness.js"/> +<h:script src="/resources/testharnessreport.js"/> + +<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of previousElementSibling</text> +<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle">The result of <tspan id="first_element_child">this test</tspan> is +<tspan id="middle_element_child" font-weight="bold">unknown.</tspan> + + + +<tspan id="last_element_child" display="none">fnord</tspan> </text> + +<h:script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl"); + var lec = document.getElementById("last_element_child"); + var pes = lec.previousElementSibling; + assert_true(!!pes) + assert_equals(pes.nodeType, 1) + assert_equals(pes.getAttribute("id"), "middle_element_child") +}) +]]></h:script> +</svg> diff --git a/testing/web-platform/tests/dom/nodes/Element-previousElementSibling-xhtml.xhtml b/testing/web-platform/tests/dom/nodes/Element-previousElementSibling-xhtml.xhtml new file mode 100644 index 000000000..7fbbc6d38 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-previousElementSibling-xhtml.xhtml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>previousElementSibling</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<h1>Test of previousElementSibling</h1> +<div id="log"></div> +<p id="parentEl">The result of <span id="first_element_child">this test</span> is +<span id="middle_element_child" style="font-weight:bold;">unknown.</span> + + + +<span id="last_element_child" style="display:none;">fnord</span> </p> +<script><![CDATA[ +test(function() { + var parentEl = document.getElementById("parentEl"); + var lec = document.getElementById("last_element_child"); + var pes = lec.previousElementSibling; + assert_true(!!pes) + assert_equals(pes.nodeType, 1) + assert_equals(pes.getAttribute("id"), "middle_element_child") +}) +]]></script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Element-previousElementSibling.html b/testing/web-platform/tests/dom/nodes/Element-previousElementSibling.html new file mode 100644 index 000000000..02c7b16df --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-previousElementSibling.html @@ -0,0 +1,23 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>previousElementSibling</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<h1>Test of previousElementSibling</h1> +<div id="log"></div> +<p id="parentEl">The result of <span id="first_element_child">this test</span> is +<span id="middle_element_child" style="font-weight:bold;">unknown.</span> + + + +<span id="last_element_child" style="display:none;">fnord</span> </p> +<script> +test(function() { + var parentEl = document.getElementById("parentEl"); + var lec = document.getElementById("last_element_child"); + var pes = lec.previousElementSibling; + assert_true(!!pes) + assert_equals(pes.nodeType, 1) + assert_equals(pes.getAttribute("id"), "middle_element_child") +}) +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-remove.html b/testing/web-platform/tests/dom/nodes/Element-remove.html new file mode 100644 index 000000000..ab642d660 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-remove.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Element.remove</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-childnode-remove"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="ChildNode-remove.js"></script> +<div id=log></div> +<script> +var node, parentNode; +setup(function() { + node = document.createElement("div"); + parentNode = document.createElement("div"); +}); +testRemove(node, parentNode, "element"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-removeAttributeNS.html b/testing/web-platform/tests/dom/nodes/Element-removeAttributeNS.html new file mode 100644 index 000000000..a2773e6f1 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-removeAttributeNS.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<title>Element.removeAttributeNS</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="attributes.js"></script> +<div id="log"></div> +<script> +var XML = "http://www.w3.org/XML/1998/namespace" + +test(function() { + var el = document.createElement("foo") + el.setAttributeNS(XML, "a:bb", "pass") + attr_is(el.attributes[0], "pass", "bb", XML, "a", "a:bb") + el.removeAttributeNS(XML, "a:bb") + assert_equals(el.attributes.length, 1) + attr_is(el.attributes[0], "pass", "bb", XML, "a", "a:bb") +}, "removeAttributeNS should take a local name.") +</script> diff --git a/testing/web-platform/tests/dom/nodes/Element-siblingElement-null-svg.svg b/testing/web-platform/tests/dom/nodes/Element-siblingElement-null-svg.svg new file mode 100644 index 000000000..48c981b8c --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-siblingElement-null-svg.svg @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:h="http://www.w3.org/1999/xhtml" + version="1.1" + width="100%" height="100%" viewBox="0 0 400 400"> +<title>Null test</title> +<h:script src="/resources/testharness.js"/> +<h:script src="/resources/testharnessreport.js"/> + +<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of previousElementSibling and nextElementSibling returning null</text> +<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle">The result of this test is <tspan id="first_element_child" font-weight="bold">unknown.</tspan></text> + +<h:script><![CDATA[ +test(function() { + var fec = document.getElementById("first_element_child"); + assert_equals(fec.previousElementSibling, null) + assert_equals(fec.nextElementSibling, null) +}) +]]></h:script> +</svg> diff --git a/testing/web-platform/tests/dom/nodes/Element-siblingElement-null-xhtml.xhtml b/testing/web-platform/tests/dom/nodes/Element-siblingElement-null-xhtml.xhtml new file mode 100644 index 000000000..fcf4d54ff --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-siblingElement-null-xhtml.xhtml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>Null Test</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<h1>Test of previousElementSibling and nextElementSibling returning null</h1> +<div id="log"></div> +<p id="parentEl">The result of this test is <span id="first_element_child" style="font-weight:bold;">unknown.</span></p> +<script><![CDATA[ +test(function() { + var fec = document.getElementById("first_element_child"); + assert_equals(fec.previousElementSibling, null) + assert_equals(fec.nextElementSibling, null) +}) +]]></script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Element-siblingElement-null.html b/testing/web-platform/tests/dom/nodes/Element-siblingElement-null.html new file mode 100644 index 000000000..a7920b4fb --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-siblingElement-null.html @@ -0,0 +1,16 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>Null test</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<h1>Test of previousElementSibling and nextElementSibling returning null</h1> +<div id="log"></div> +<p id="parentEl">The result of this test is <span id="first_element_child" style="font-weight:bold;">unknown.</span></p> +<script> +test(function() { + var fec = document.getElementById("first_element_child"); + assert_equals(fec.previousElementSibling, null) + assert_equals(fec.nextElementSibling, null) +}) +</script> + diff --git a/testing/web-platform/tests/dom/nodes/Element-tagName.html b/testing/web-platform/tests/dom/nodes/Element-tagName.html new file mode 100644 index 000000000..035a23cc5 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Element-tagName.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<title>Element.tagName</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + var HTMLNS = "http://www.w3.org/1999/xhtml" + assert_equals(document.createElementNS(HTMLNS, "I").tagName, "I") + assert_equals(document.createElementNS(HTMLNS, "i").tagName, "I") + assert_equals(document.createElementNS(HTMLNS, "x:b").tagName, "X:B") +}, "tagName should upper-case for HTML elements in HTML documents.") + +test(function() { + var SVGNS = "http://www.w3.org/2000/svg" + assert_equals(document.createElementNS(SVGNS, "svg").tagName, "svg") + assert_equals(document.createElementNS(SVGNS, "SVG").tagName, "SVG") + assert_equals(document.createElementNS(SVGNS, "s:svg").tagName, "s:svg") + assert_equals(document.createElementNS(SVGNS, "s:SVG").tagName, "s:SVG") +}, "tagName should not upper-case for SVG elements in HTML documents.") + +test(function() { + if ("DOMParser" in window) { + var xmlel = new DOMParser() + .parseFromString('<div xmlns="http://www.w3.org/1999/xhtml">Test</div>', 'text/xml') + .documentElement; + assert_equals(xmlel.tagName, "div", "tagName should be lowercase in XML") + var htmlel = document.importNode(xmlel, true) + assert_equals(htmlel.tagName, "DIV", "tagName should be uppercase in HTML") + } +}, "tagName should be updated when changing ownerDocument") + +test(function() { + var xmlel = document.implementation + .createDocument("http://www.w3.org/1999/xhtml", "div", null) + .documentElement; + assert_equals(xmlel.tagName, "div", "tagName should be lowercase in XML") + var htmlel = document.importNode(xmlel, true) + assert_equals(htmlel.tagName, "DIV", "tagName should be uppercase in HTML") +}, "tagName should be updated when changing ownerDocument (createDocument without prefix)") + +test(function() { + var xmlel = document.implementation + .createDocument("http://www.w3.org/1999/xhtml", "foo:div", null) + .documentElement; + assert_equals(xmlel.tagName, "foo:div", "tagName should be lowercase in XML") + var htmlel = document.importNode(xmlel, true) + assert_equals(htmlel.tagName, "FOO:DIV", "tagName should be uppercase in HTML") +}, "tagName should be updated when changing ownerDocument (createDocument with prefix)") +</script> diff --git a/testing/web-platform/tests/dom/nodes/MutationObserver-attributes.html b/testing/web-platform/tests/dom/nodes/MutationObserver-attributes.html new file mode 100644 index 000000000..6721b7eec --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/MutationObserver-attributes.html @@ -0,0 +1,406 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>MutationObservers: attributes mutations</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="mutationobservers.js"></script> +<h1>MutationObservers: attributes mutations</h1> +<div id="log"></div> + +<section style="display: none"> +<p id='n'></p> + +<p id='n00'></p> +<p id='n01'></p> +<p id='n02'></p> +<p id='n03'></p> +<input id="n04" type="text"> + +<p id='n10'></p> +<p id='n11'></p> +<p id='n12' class='c01'></p> +<p id='n13' class='c01 c02'></p> + +<p id='n20'></p> +<p id='n21'></p> +<p id='n22'></p> +<p id='n23'></p> +<p id='n24' class="c01 c02"></p> + +<p id='n30' class="c01 c02"></p> +<p id='n31' class="c01 c02"></p> +<p id='n32' class="c01 c02"></p> + +<p id='n40' class="c01 c02"></p> +<p id='n41' class="c01 c02"></p> +<p id='n42' class="c01 c02"></p> +<p id='n43' class="c01 c02"></p> +<p id='n44' class="c01 c02"></p> +<p id='n45' class="c01 c02"></p> + +<p id='n50' class="c01 c02"></p> +<p id='n51'></p> + +<p id='n60'></p> +<p id='n61' class="c01"></p> +<p id='n62'></p> + +<p id='n70' class="c01"></p> +<p id='n71'></p> +<input id="n72" type="text"> + +<p id='n80'></p> +<p id='n81'></p> + +<p id='n90'></p> +<p id='n91'></p> +<p id='n92'></p> + +<p id='n1000'></p> +<p id='n1001' class='c01'></p> + +<p id='n2000'></p> +<p id='n2001' class='c01'></p> + +<p id='n3000'></p> + +</section> + +<script> + +var n = document.getElementById('n'); + +runMutationTest(n, + {"attributes":true}, + [{type: "attributes", attributeName: "id"}], + function() { n.id = "n000";}, + "attributes Element.id: update, no oldValue, mutation"); + +var n00 = document.getElementById('n00'); +runMutationTest(n00, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "n00", attributeName: "id"}], + function() { n00.id = "n000";}, + "attributes Element.id: update mutation"); + +var n01 = document.getElementById('n01'); +runMutationTest(n01, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "n01", attributeName: "id"}], + function() { n01.id = "";}, + "attributes Element.id: empty string update mutation"); + +var n02 = document.getElementById('n02'); +runMutationTest(n02, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "n02", attributeName: "id"}, {type: "attributes", attributeName: "class"}], + function() { n02.id = "n02"; n02.setAttribute("class", "c01");}, + "attributes Element.id: same value mutation"); + +var n03 = document.getElementById('n03'); +runMutationTest(n03, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "n03", attributeName: "id"}], + function() { n03.unknown = "c02"; n03.id = "n030";}, + "attributes Element.unknown: IDL attribute no mutation"); + +var n04 = document.getElementById('n04'); +runMutationTest(n04, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "text", attributeName: "type"}, {type: "attributes", oldValue: "n04", attributeName: "id"}], + function() { n04.type = "unknown"; n04.id = "n040";}, + "attributes HTMLInputElement.type: type update mutation"); + + var n10 = document.getElementById('n10'); +runMutationTest(n10, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", attributeName: "class"}], + function() { n10.className = "c01";}, + "attributes Element.className: new value mutation"); + + var n11 = document.getElementById('n11'); +runMutationTest(n11, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", attributeName: "class"}], + function() { n11.className = "";}, + "attributes Element.className: empty string update mutation"); + + var n12 = document.getElementById('n12'); +runMutationTest(n12, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "c01", attributeName: "class"}], + function() { n12.className = "c01";}, + "attributes Element.className: same value mutation"); + + var n13 = document.getElementById('n13'); +runMutationTest(n13, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}], + function() { n13.className = "c01 c02";}, + "attributes Element.className: same multiple values mutation"); + + var n20 = document.getElementById('n20'); +runMutationTest(n20, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", attributeName: "class"}], + function() { n20.classList.add("c01");}, + "attributes Element.classList.add: single token addition mutation"); + + var n21 = document.getElementById('n21'); +runMutationTest(n21, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", attributeName: "class"}], + function() { n21.classList.add("c01", "c02", "c03");}, + "attributes Element.classList.add: multiple tokens addition mutation"); + + var n22 = document.getElementById('n22'); +runMutationTest(n22, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "n22", attributeName: "id"}], + function() { try { n22.classList.add("c01", "", "c03"); } catch (e) { }; + n22.id = "n220"; }, + "attributes Element.classList.add: syntax err/no mutation"); + + var n23 = document.getElementById('n23'); +runMutationTest(n23, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "n23", attributeName: "id"}], + function() { try { n23.classList.add("c01", "c 02", "c03"); } catch (e) { }; + n23.id = "n230"; }, + "attributes Element.classList.add: invalid character/no mutation"); + + var n24 = document.getElementById('n24'); +runMutationTest(n24, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}, {type: "attributes", oldValue: "n24", attributeName: "id"}], + function() { n24.classList.add("c02"); n24.id = "n240";}, + "attributes Element.classList.add: same value mutation"); + + var n30 = document.getElementById('n30'); +runMutationTest(n30, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}], + function() { n30.classList.remove("c01");}, + "attributes Element.classList.remove: single token removal mutation"); + + var n31 = document.getElementById('n31'); +runMutationTest(n31, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}], + function() { n31.classList.remove("c01", "c02");}, + "attributes Element.classList.remove: multiple tokens removal mutation"); + + var n32 = document.getElementById('n32'); +runMutationTest(n32, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}, {type: "attributes", oldValue: "n32", attributeName: "id"}], + function() { n32.classList.remove("c03"); n32.id = "n320";}, + "attributes Element.classList.remove: missing token removal mutation"); + + var n40 = document.getElementById('n40'); +runMutationTest(n40, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}], + function() { n40.classList.toggle("c01");}, + "attributes Element.classList.toggle: token removal mutation"); + + var n41 = document.getElementById('n41'); +runMutationTest(n41, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}], + function() { n41.classList.toggle("c03");}, + "attributes Element.classList.toggle: token addition mutation"); + + var n42 = document.getElementById('n42'); +runMutationTest(n42, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}], + function() { n42.classList.toggle("c01", false);}, + "attributes Element.classList.toggle: forced token removal mutation"); + + var n43 = document.getElementById('n43'); +runMutationTest(n43, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "n43", attributeName: "id"}], + function() { n43.classList.toggle("c03", false); n43.id = "n430"; }, + "attributes Element.classList.toggle: forced missing token removal no mutation"); + + var n44 = document.getElementById('n44'); +runMutationTest(n44, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "n44", attributeName: "id"}], + function() { n44.classList.toggle("c01", true); n44.id = "n440"; }, + "attributes Element.classList.toggle: forced existing token addition no mutation"); + + var n45 = document.getElementById('n45'); +runMutationTest(n45, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}], + function() { n45.classList.toggle("c03", true);}, + "attributes Element.classList.toggle: forced token addition mutation"); + + var n50 = document.getElementById('n50'); +runMutationTest(n50, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}], + function() { + for (var i = 0; i < n50.attributes.length; i++) { + var attr = n50.attributes[i]; + if (attr.localName === "class") { + attr.value = "c03"; + } + }; + }, + "attributes Element.attributes.value: update mutation"); + + var n51 = document.getElementById('n51'); +runMutationTest(n51, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "n51", attributeName: "id"}], + function() { + n51.attributes[0].value = "n51"; + }, + "attributes Element.attributes.value: same id mutation"); + + var n60 = document.getElementById('n60'); +runMutationTest(n60, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "n60", attributeName: "id"}], + function() { + n60.setAttribute("id", "n601"); + }, + "attributes Element.setAttribute: id mutation"); + + var n61 = document.getElementById('n61'); +runMutationTest(n61, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "c01", attributeName: "class"}], + function() { + n61.setAttribute("class", "c01"); + }, + "attributes Element.setAttribute: same class mutation"); + + var n62 = document.getElementById('n62'); +runMutationTest(n62, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", attributeName: "classname"}], + function() { + n62.setAttribute("classname", "c01"); + }, + "attributes Element.setAttribute: classname mutation"); + + var n70 = document.getElementById('n70'); +runMutationTest(n70, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "c01", attributeName: "class"}], + function() { + n70.removeAttribute("class"); + }, + "attributes Element.removeAttribute: removal mutation"); + + var n71 = document.getElementById('n71'); +runMutationTest(n71, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "n71", attributeName: "id"}], + function() { + n71.removeAttribute("class"); + n71.id = "n710"; + }, + "attributes Element.removeAttribute: removal no mutation"); + + var n72 = document.getElementById('n72'); +runMutationTest(n72, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "text", attributeName: "type"}, {type: "attributes", oldValue: "n72", attributeName: "id"}], + function() { + n72.removeAttribute("type"); + n72.id = "n720"; + }, + "childList HTMLInputElement.removeAttribute: type removal mutation"); + + var n80 = document.getElementById('n80'); +runMutationTest(n80, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", attributeName: "private", attributeNamespace: "http://example.org/"}], + function() { + n80.setAttributeNS("http://example.org/", "private", "42"); + }, + "attributes Element.setAttributeNS: creation mutation"); + + var n81 = document.getElementById('n81'); +runMutationTest(n81, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", attributeName: "lang", attributeNamespace: "http://www.w3.org/XML/1998/namespace"}], + function() { + n81.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:lang", "42"); + }, + "attributes Element.setAttributeNS: prefixed attribute creation mutation"); + + var n90 = document.getElementById('n90'); + n90.setAttributeNS("http://example.org/", "private", "42"); +runMutationTest(n90, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "42", attributeName: "private", attributeNamespace: "http://example.org/"}], + function() { + n90.removeAttributeNS("http://example.org/", "private"); + }, + "attributes Element.removeAttributeNS: removal mutation"); + + var n91 = document.getElementById('n91'); +runMutationTest(n91, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "n91", attributeName: "id"}], + function() { + n91.removeAttributeNS("http://example.org/", "private"); + n91.id = "n910"; + }, + "attributes Element.removeAttributeNS: removal no mutation"); + + var n92 = document.getElementById('n92'); +runMutationTest(n92, + {"attributes":true, "attributeOldValue": true}, + [{type: "attributes", oldValue: "n92", attributeName: "id"}], + function() { + n92.removeAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:lang"); + n92.id = "n920"; + }, + "attributes Element.removeAttributeNS: prefixed attribute removal no mutation"); + + var n1000 = document.getElementById('n1000'); +runMutationTest(n1000, + {"attributes":true, "attributeOldValue": true,"attributeFilter": ["id"]}, + [{type: "attributes", oldValue: "n1000", attributeName: "id"}], + function() { n1000.id = "abc"; n1000.className = "c01"}, + "attributes/attributeFilter Element.id/Element.className: update mutation"); + + var n1001 = document.getElementById('n1001'); +runMutationTest(n1001, + {"attributes":true, "attributeOldValue": true,"attributeFilter": ["id", "class"]}, + [{type: "attributes", oldValue: "n1001", attributeName: "id"}, + {type: "attributes", oldValue: "c01", attributeName: "class"}], + function() { n1001.id = "abc"; n1001.className = "c02"; n1001.setAttribute("lang", "fr");}, + "attributes/attributeFilter Element.id/Element.className: multiple filter update mutation"); + + var n2000 = document.getElementById('n2000'); +runMutationTest(n2000, + {"attributeOldValue": true}, + [{type: "attributes", oldValue: "n2000", attributeName: "id"}], + function() { n2000.id = "abc";}, + "attributeOldValue alone Element.id: update mutation"); + + var n2001 = document.getElementById('n2001'); +runMutationTest(n2001, + {"attributeFilter": ["id", "class"]}, + [{type: "attributes", attributeName: "id"}, + {type: "attributes", attributeName: "class"}], + function() { n2001.id = "abcd"; n2001.className = "c02"; n2001.setAttribute("lang", "fr");}, + "attributeFilter alone Element.id/Element.className: multiple filter update mutation"); + + var n3000 = document.getElementById('n3000'); +runMutationTest(n3000, + {"subtree": true, "childList":false, "attributes" : true}, + [{type: "attributes", attributeName: "id" }], + function() { n3000.textContent = "CHANGED"; n3000.id = "abc";}, + "childList false: no childList mutation"); + +</script> diff --git a/testing/web-platform/tests/dom/nodes/MutationObserver-characterData.html b/testing/web-platform/tests/dom/nodes/MutationObserver-characterData.html new file mode 100644 index 000000000..addaef03d --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/MutationObserver-characterData.html @@ -0,0 +1,215 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>MutationObservers: characterData mutations</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="mutationobservers.js"></script> +<h1>MutationObservers: characterData mutations</h1> +<div id="log"></div> + +<section style="display: none"> + +<p id='n'>text content</p> + +<p id='n00'>text content</p> + +<p id='n10'>CHAN</p> +<p id='n11'>CHANGED</p> +<p id='n12'>CHANGED</p> + +<p id='n20'>CHGED</p> +<p id='n21'>CHANGED</p> +<p id='n22'>CHANGED</p> + +<p id='n30'>CCCHANGED</p> +<p id='n31'>CHANGED</p> + +<p id='n40'>CCCHANGED</p> +<p id='n41'>CHANGED</p> + +<p id="n50"><?processing data?></p> + +<p id="n60"><!-- data --></p> + +<p id='n70'>CHANN</p> +<p id='n71'>CHANN</p> + +<p id='n80'>CHANN</p> +<p id='n81'>CHANN</p> + +<p id='n90'>CHANN</p> + +</section> + +<script> + var n = document.getElementById('n').firstChild; +runMutationTest(n, + {"characterData":true}, + [{type: "characterData"}], + function() { n.data = "NEW VALUE"; }, + "characterData Text.data: simple mutation without oldValue"); + + var n00 = document.getElementById('n00').firstChild; +runMutationTest(n00, + {"characterData":true,"characterDataOldValue":true}, + [{type: "characterData", oldValue: "text content" }], + function() { n00.data = "CHANGED"; }, + "characterData Text.data: simple mutation"); + + var n10 = document.getElementById('n10').firstChild; +runMutationTest(n10, + {"characterData":true,"characterDataOldValue":true}, + [{type: "characterData", oldValue: "CHAN" }], + function() { n10.appendData("GED"); }, + "characterData Text.appendData: simple mutation"); + + var n11 = document.getElementById('n11').firstChild; +runMutationTest(n11, + {"characterData":true,"characterDataOldValue":true}, + [{type: "characterData", oldValue: "CHANGED" }], + function() { n11.appendData(""); }, + "characterData Text.appendData: empty string mutation"); + + var n12 = document.getElementById('n12').firstChild; +runMutationTest(n12, + {"characterData":true,"characterDataOldValue":true}, + [{type: "characterData", oldValue: "CHANGED" }], + function() { n12.appendData(null); }, + "characterData Text.appendData: null string mutation"); + + var n20 = document.getElementById('n20').firstChild; +runMutationTest(n20, + {"characterData":true,"characterDataOldValue":true}, + [{type: "characterData", oldValue: "CHGED" }], + function() { n20.insertData(2, "AN"); }, + "characterData Text.insertData: simple mutation"); + + var n21 = document.getElementById('n21').firstChild; +runMutationTest(n21, + {"characterData":true,"characterDataOldValue":true}, + [{type: "characterData", oldValue: "CHANGED" }], + function() { n21.insertData(2, ""); }, + "characterData Text.insertData: empty string mutation"); + + var n22 = document.getElementById('n22').firstChild; +runMutationTest(n22, + {"characterData":true,"characterDataOldValue":true}, + [{type: "characterData", oldValue: "CHANGED" }], + function() { n22.insertData(2, null); }, + "characterData Text.insertData: null string mutation"); + + var n30 = document.getElementById('n30').firstChild; +runMutationTest(n30, + {"characterData":true,"characterDataOldValue":true}, + [{type: "characterData", oldValue: "CCCHANGED" }], + function() { n30.deleteData(0, 2); }, + "characterData Text.deleteData: simple mutation"); + + var n31 = document.getElementById('n31').firstChild; +runMutationTest(n31, + {"characterData":true,"characterDataOldValue":true}, + [{type: "characterData", oldValue: "CHANGED" }, {type: "characterData", oldValue: "CHANGED" }], + function() { n31.deleteData(0, 0); n31.data = "n31"; }, + "characterData Text.deleteData: empty mutation"); + + var n40 = document.getElementById('n40').firstChild; +runMutationTest(n40, + {"characterData":true,"characterDataOldValue":true}, + [{type: "characterData", oldValue: "CCCHANGED" }], + function() { n40.replaceData(0, 2, "CH"); }, + "characterData Text.replaceData: simple mutation"); + + var n41 = document.getElementById('n41').firstChild; +runMutationTest(n41, + {"characterData":true,"characterDataOldValue":true}, + [{type: "characterData", oldValue: "CHANGED" }], + function() { n41.replaceData(0, 0, "CH"); }, + "characterData Text.replaceData: empty mutation"); + + var n50 = document.getElementById('n50').firstChild; +runMutationTest(n50, + {"characterData":true,"characterDataOldValue":true}, + [{type: "characterData", oldValue: "?processing data?" },{type: "characterData", oldValue: "CHANGED" },{type: "characterData", oldValue: "CHANGED" }], + function() { + n50.data = "CHANGED"; + n50.deleteData(0, 0); + n50.replaceData(0, 2, "CH"); }, + "characterData ProcessingInstruction: data mutations"); + + var n60 = document.getElementById('n60').firstChild; +runMutationTest(n60, + {"characterData":true,"characterDataOldValue":true}, + [{type: "characterData", oldValue: " data " },{type: "characterData", oldValue: "CHANGED" },{type: "characterData", oldValue: "CHANGED" }], + function() { + n60.data = "CHANGED"; + n60.deleteData(0, 0); + n60.replaceData(0, 2, "CH"); }, + "characterData Comment: data mutations"); + + var n70 = document.getElementById('n70'); + var r70 = null; + test(function () { + n70.appendChild(document.createTextNode("NNN")); + n70.appendChild(document.createTextNode("NGED")); + r70 = document.createRange(); + r70.setStart(n70.firstChild, 4); + r70.setEnd(n70.lastChild, 1); + }, "Range (r70) is created"); +runMutationTest(n70.firstChild, + {"characterData":true,"characterDataOldValue":true}, + [{type: "characterData", oldValue: "CHANN" }], + function() { r70.deleteContents(); }, + "characterData Range.deleteContents: child and data removal mutation"); + + var n71 = document.getElementById('n71'); + var r71 = null; + test(function () { + n71.appendChild(document.createTextNode("NNN")); + n71.appendChild(document.createTextNode("NGED")); + r71 = document.createRange(); + r71.setStart(n71.firstChild, 4); + r71.setEnd(n71.lastChild, 1); + }, "Range (r71) is created"); +runMutationTest(n71.lastChild, + {"characterData":true,"characterDataOldValue":true}, + [{type: "characterData", oldValue: "NGED"}], + function() { r71.deleteContents(); }, + "characterData Range.deleteContents: child and data removal mutation (2)"); + + var n80 = document.getElementById('n80'); + var r80 = null; + test(function () { + n80.appendChild(document.createTextNode("NNN")); + n80.appendChild(document.createTextNode("NGED")); + r80 = document.createRange(); + r80.setStart(n80.firstChild, 4); + r80.setEnd(n80.lastChild, 1); + }, "Range (r80) is created"); +runMutationTest(n80.firstChild, + {"characterData":true,"characterDataOldValue":true}, + [{type: "characterData", oldValue: "CHANN" }], + function() { r80.extractContents(); }, + "characterData Range.extractContents: child and data removal mutation"); + + var n81 = document.getElementById('n81'); + var r81 = null; + test(function () { + n81.appendChild(document.createTextNode("NNN")); + n81.appendChild(document.createTextNode("NGED")); + r81 = document.createRange(); + r81.setStart(n81.firstChild, 4); + r81.setEnd(n81.lastChild, 1); + }, "Range (r81) is created"); +runMutationTest(n81.lastChild, + {"characterData":true,"characterDataOldValue":true}, + [{type: "characterData", oldValue: "NGED" }], + function() { r81.extractContents(); }, + "characterData Range.extractContents: child and data removal mutation (2)"); + + var n90 = document.getElementById('n90').firstChild; +runMutationTest(n90, + {"characterDataOldValue":true}, + [{type: "characterData", oldValue: "CHANN" }], + function() { n90.data = "CHANGED"; }, + "characterData/characterDataOldValue alone Text.data: simple mutation"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/MutationObserver-childList.html b/testing/web-platform/tests/dom/nodes/MutationObserver-childList.html new file mode 100644 index 000000000..e4c674e02 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/MutationObserver-childList.html @@ -0,0 +1,434 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>MutationObservers: childList mutations</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="mutationobservers.js"></script> +<h1>MutationObservers: childList mutations</h1> +<div id="log"></div> + +<section style="display: none"> +<p id='dummies'> +<span id='d30'>text content</span> +<span id='d35'>text content</span> +<span id='d40'>text content</span> +<span id='d45'>text content</span> +<span id='d50'>text content</span> +<span id='d51'>text content</span> +</p> + +</section> +<section style="display: none"> +<p id='n00'><span>text content</span></p> + +<p id='n10'><span>text content</span></p> +<p id='n11'></p> +<p id='n12'></p> +<p id='n13'><span>text content</span></p> + +<p id='n20'>PAS</p> +<p id='n21'>CH</p> + +<p id='n30'><span>text content</span></p> +<p id='n31'><span>text content</span></p> +<p id='n32'><span>AN</span><span>CH</span><span>GED</span></p> +<p id='n33'><span>text content</span></p> +<p id='n34'><span>text content</span></p> +<p id='n35'><span>text content</span></p> + +<p id='n40'><span>text content</span></p> +<p id='n41'><span>text content</span></p> +<p id='n42'><span>CH</span><span>GED</span><span>AN</span></p> +<p id='n43'><span>text content</span></p> +<p id='n44'><span>text content</span></p> +<p id='n45'><span>text content</span></p> + + +<p id='n50'><span>text content</span></p> +<p id='n51'><span>text content</span></p> +<p id='n52'><span>NO </span><span>CHANGED</span></p> +<p id='n53'><span>text content</span></p> + +<p id='n60'><span>text content</span></p> + +<p id='n70'><span>NO </span><span>CHANGED</span></p> +<p id='n71'>CHANN</p> + +<p id='n80'><span>NO </span><span>CHANGED</span></p> +<p id='n81'>CHANN</p> + +<p id='n90'><span>CHA</span><span>ED</span></p> +<p id='n91'>CHAE</p> + +<p id='n100'><span id="s1">CHAN</span><span id="s2">GED</span></p> + +</section> + +<script> + var dummies = document.getElementById('dummies'); + + function createFragment() { + var fragment = document.createDocumentFragment(); + fragment.appendChild(document.createTextNode("11")); + fragment.appendChild(document.createTextNode("22")); + return fragment; + } + + var n00 = document.getElementById('n00'); + + runMutationTest(n00, + {"childList":true, "attributes":true}, + [{type: "attributes", attributeName: "class"}], + function() { n00.nodeValue = ""; n00.setAttribute("class", "dummy");}, + "childList Node.nodeValue: no mutation"); + + var n10 = document.getElementById('n10'); + runMutationTest(n10, + {"childList":true}, + [{type: "childList", + removedNodes: [n10.firstChild], + addedNodes: function() {return [n10.firstChild]}}], + function() { n10.textContent = "new data"; }, + "childList Node.textContent: replace content mutation"); + + var n11 = document.getElementById('n11'); + runMutationTest(n11, + {"childList":true}, + [{type: "childList", + addedNodes: function() {return [n11.firstChild]}}], + function() { n11.textContent = "new data"; }, + "childList Node.textContent: no previous content mutation"); + + var n12 = document.getElementById('n12'); + runMutationTest(n12, + {"childList":true, "attributes":true}, + [{type: "attributes", attributeName: "class"}], + function() { n12.textContent = ""; n12.setAttribute("class", "dummy");}, + "childList Node.textContent: textContent no mutation"); + + var n13 = document.getElementById('n13'); + runMutationTest(n13, + {"childList":true}, + [{type: "childList", removedNodes: [n13.firstChild]}], + function() { n13.textContent = ""; }, + "childList Node.textContent: empty string mutation"); + + var n20 = document.getElementById('n20'); + n20.appendChild(document.createTextNode("S")); + runMutationTest(n20, + {"childList":true}, + [{type: "childList", + removedNodes: [n20.lastChild], + previousSibling: n20.firstChild}], + function() { n20.normalize(); }, + "childList Node.normalize mutation"); + + var n21 = document.getElementById('n21'); + n21.appendChild(document.createTextNode("AN")); + n21.appendChild(document.createTextNode("GED")); + runMutationTest(n21, + {"childList":true}, + [{type: "childList", + removedNodes: [n21.lastChild.previousSibling], + previousSibling: n21.firstChild, + nextSibling: n21.lastChild}, + {type: "childList", + removedNodes: [n21.lastChild], + previousSibling: n21.firstChild}], + function() { n21.normalize(); }, + "childList Node.normalize mutations"); + + var n30 = document.getElementById('n30'); + var d30 = document.getElementById('d30'); + runMutationTest(n30, + {"childList":true}, + [{type: "childList", + addedNodes: [d30], + nextSibling: n30.firstChild}], + function() { n30.insertBefore(d30, n30.firstChild); }, + "childList Node.insertBefore: addition mutation"); + + var n31 = document.getElementById('n31'); + runMutationTest(n31, + {"childList":true}, + [{type: "childList", + removedNodes: [n31.firstChild]}], + function() { dummies.insertBefore(n31.firstChild, dummies.firstChild); }, + "childList Node.insertBefore: removal mutation"); + + var n32 = document.getElementById('n32'); + runMutationTest(n32, + {"childList":true}, + [{type: "childList", + removedNodes: [n32.firstChild.nextSibling], + previousSibling: n32.firstChild, nextSibling: n32.lastChild}, + {type: "childList", + addedNodes: [n32.firstChild.nextSibling], + nextSibling: n32.firstChild}], + function() { n32.insertBefore(n32.firstChild.nextSibling, n32.firstChild); }, + "childList Node.insertBefore: removal and addition mutations"); + + var n33 = document.getElementById('n33'); + var f33 = createFragment(); + runMutationTest(n33, + {"childList":true}, + [{type: "childList", + addedNodes: [f33.firstChild, f33.lastChild], + nextSibling: n33.firstChild}], + function() { n33.insertBefore(f33, n33.firstChild); }, + "childList Node.insertBefore: fragment addition mutations"); + + var n34 = document.getElementById('n34'); + var f34 = createFragment(); + runMutationTest(f34, + {"childList":true}, + [{type: "childList", + removedNodes: [f34.firstChild, f34.lastChild]}], + function() { n34.insertBefore(f34, n34.firstChild); }, + "childList Node.insertBefore: fragment removal mutations"); + + var n35 = document.getElementById('n35'); + var d35 = document.getElementById('d35'); + runMutationTest(n35, + {"childList":true}, + [{type: "childList", + addedNodes: [d35], + previousSibling: n35.firstChild}], + function() { n35.insertBefore(d35, null); }, + "childList Node.insertBefore: last child addition mutation"); + + var n40 = document.getElementById('n40'); + var d40 = document.getElementById('d40'); + runMutationTest(n40, + {"childList":true}, + [{type: "childList", + addedNodes: [d40], + previousSibling: n40.firstChild}], + function() { n40.appendChild(d40); }, + "childList Node.appendChild: addition mutation"); + + var n41 = document.getElementById('n41'); + runMutationTest(n41, + {"childList":true}, + [{type: "childList", + removedNodes: [n41.firstChild]}], + function() { dummies.appendChild(n41.firstChild); }, + "childList Node.appendChild: removal mutation"); + + var n42 = document.getElementById('n42'); + runMutationTest(n42, + {"childList":true}, + [{type: "childList", + removedNodes: [n42.firstChild.nextSibling], + previousSibling: n42.firstChild, nextSibling: n42.lastChild}, + {type: "childList", + addedNodes: [n42.firstChild.nextSibling], + previousSibling: n42.lastChild}], + function() { n42.appendChild(n42.firstChild.nextSibling); }, + "childList Node.appendChild: removal and addition mutations"); + + var n43 = document.getElementById('n43'); + var f43 = createFragment(); + runMutationTest(n43, + {"childList":true}, + [{type: "childList", + addedNodes: [f43.firstChild, f43.lastChild], + previousSibling: n43.firstChild}], + function() { n43.appendChild(f43); }, + "childList Node.appendChild: fragment addition mutations"); + + var n44 = document.getElementById('n44'); + var f44 = createFragment(); + runMutationTest(f44, + {"childList":true}, + [{type: "childList", + removedNodes: [f44.firstChild, f44.lastChild]}], + function() { n44.appendChild(f44); }, + "childList Node.appendChild: fragment removal mutations"); + + var n45 = document.createElement('p'); + var d45 = document.createElement('span'); + runMutationTest(n45, + {"childList":true}, + [{type: "childList", + addedNodes: [d45]}], + function() { n45.appendChild(d45); }, + "childList Node.appendChild: addition outside document tree mutation"); + + var n50 = document.getElementById('n50'); + var d50 = document.getElementById('d50'); + runMutationTest(n50, + {"childList":true}, + [{type: "childList", + removedNodes: [n50.firstChild], + addedNodes: [d50]}], + function() { n50.replaceChild(d50, n50.firstChild); }, + "childList Node.replaceChild: replacement mutation"); + + var n51 = document.getElementById('n51'); + var d51 = document.getElementById('d51'); + runMutationTest(n51, + {"childList":true}, + [{type: "childList", + removedNodes: [n51.firstChild]}], + function() { d51.parentNode.replaceChild(n51.firstChild, d51); }, + "childList Node.replaceChild: removal mutation"); + + var n52 = document.getElementById('n52'); + runMutationTest(n52, + {"childList":true}, + [{type: "childList", + removedNodes: [n52.lastChild], + previousSibling: n52.firstChild}, + {type: "childList", + removedNodes: [n52.firstChild], + addedNodes: [n52.lastChild]}], + function() { n52.replaceChild(n52.lastChild, n52.firstChild); }, + "childList Node.replaceChild: internal replacement mutation"); + + var n53 = document.getElementById('n53'); + runMutationTest(n53, + {"childList":true}, + [{type: "childList", + removedNodes: [n53.firstChild]}, + {type: "childList", + addedNodes: [n53.firstChild]}], + function() { n53.replaceChild(n53.firstChild, n53.firstChild); }, + "childList Node.replaceChild: self internal replacement mutation"); + + var n60 = document.getElementById('n60'); + runMutationTest(n60, + {"childList":true}, + [{type: "childList", + removedNodes: [n60.firstChild]}], + function() { n60.removeChild(n60.firstChild); }, + "childList Node.removeChild: removal mutation"); + + var n70 = document.getElementById('n70'); + var r70 = null; + test(function () { + r70 = document.createRange(); + r70.setStartBefore(n70.firstChild); + r70.setEndAfter(n70.firstChild); + }, "Range (r70) is created"); + runMutationTest(n70, + {"childList":true}, + [{type: "childList", + removedNodes: [n70.firstChild], + nextSibling: n70.lastChild}], + function() { r70.deleteContents(); }, + "childList Range.deleteContents: child removal mutation"); + + var n71 = document.getElementById('n71'); + var r71 = null; + test(function () { + n71.appendChild(document.createTextNode("NNN")); + n71.appendChild(document.createTextNode("NGED")); + r71 = document.createRange(); + r71.setStart(n71.firstChild, 4); + r71.setEnd(n71.lastChild, 1); + }, "Range (r71) is created"); + runMutationTest(n71, + {"childList":true}, + [{type: "childList", + removedNodes: [n71.firstChild.nextSibling], + previousSibling: n71.firstChild, + nextSibling: n71.lastChild}], + function() { r71.deleteContents(); }, + "childList Range.deleteContents: child and data removal mutation"); + + var n80 = document.getElementById('n80'); + var r80 = null; + test(function () { + r80 = document.createRange(); + r80.setStartBefore(n80.firstChild); + r80.setEndAfter(n80.firstChild); + }, "Range (r80) is created"); + runMutationTest(n80, + {"childList":true}, + [{type: "childList", + removedNodes: [n80.firstChild], + nextSibling: n80.lastChild}], + function() { r80.extractContents(); }, + "childList Range.extractContents: child removal mutation"); + + var n81 = document.getElementById('n81'); + var r81 = null; + test(function () { + n81.appendChild(document.createTextNode("NNN")); + n81.appendChild(document.createTextNode("NGED")); + r81 = document.createRange(); + r81.setStart(n81.firstChild, 4); + r81.setEnd(n81.lastChild, 1); + }, "Range (r81) is created"); + runMutationTest(n81, + {"childList":true}, + [{type: "childList", + removedNodes: [n81.firstChild.nextSibling], + previousSibling: n81.firstChild, + nextSibling: n81.lastChild}], + function() { r81.extractContents(); }, + "childList Range.extractContents: child and data removal mutation"); + + var n90 = document.getElementById('n90'); + var f90 = document.createTextNode("NG"); + var r90 = null; + test(function () { + r90 = document.createRange(); + r90.setStartAfter(n90.firstChild); + r90.setEndBefore(n90.lastChild); + }, "Range (r90) is created"); + runMutationTest(n90, + {"childList":true}, + [{type: "childList", + addedNodes: [f90], + previousSibling: n90.firstChild, + nextSibling: n90.lastChild}], + function() { r90.insertNode(f90); }, + "childList Range.insertNode: child insertion mutation"); + + var n91 = document.getElementById('n91'); + var f91 = document.createTextNode("NG"); + var r91 = null; + test(function () { + n91.appendChild(document.createTextNode("D")); + r91 = document.createRange(); + r91.setStart(n91.firstChild, 3); + r91.setEnd(n91.lastChild, 0); + }, "Range (r91) is created"); + runMutationTest(n91, + {"childList":true}, + [{type: "childList", + addedNodes: function() { return [n91.lastChild.previousSibling]; }, + previousSibling: n91.firstChild, + nextSibling: n91.lastChild}, + {type: "childList", + addedNodes: [f91], + previousSibling: n91.firstChild, + nextSibling: function () { return n91.lastChild.previousSibling; } }], + function() { r91.insertNode(f91); }, + "childList Range.insertNode: children insertion mutation"); + + var n100 = document.getElementById('n100'); + var f100 = document.createElement("span"); + var r100 = null; + test(function () { + r100 = document.createRange(); + r100.setStartBefore(n100.firstChild); + r100.setEndAfter(n100.lastChild); + }, "Range (r100) is created"); + runMutationTest(n100, + {"childList":true}, + [{type: "childList", + removedNodes: [n100.firstChild], + nextSibling: n100.lastChild}, + {type: "childList", + removedNodes: [n100.lastChild]}, + {type: "childList", + addedNodes: [f100] }], + function() { r100.surroundContents(f100); }, + "childList Range.surroundContents: children removal and addition mutation"); + +</script> + + diff --git a/testing/web-platform/tests/dom/nodes/MutationObserver-disconnect.html b/testing/web-platform/tests/dom/nodes/MutationObserver-disconnect.html new file mode 100644 index 000000000..883edecf7 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/MutationObserver-disconnect.html @@ -0,0 +1,48 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>MutationObservers: disconnect</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<h1>MutationObservers: disconnect</h1> +<div id="log"></div> +<section style="display: none"> +<p id='n00'></p> +</section> +<script> +var n00 = document.getElementById('n00'); +var parentTest = async_test("subtree mutations"); +function masterMO(sequence, obs) { + parentTest.step(function() { + assert_equals(sequence.length, 4, "mutation records must match"); + }); + parentTest.done(); +} +parentTest.step(function() { + (new MutationObserver(masterMO)).observe(n00.parentNode, {"subtree": true, "attributes": true}); +}); + +var disconnectTest = async_test("disconnect discarded some mutations"); +function observerCallback(sequence, obs) { + disconnectTest.step(function() { + assert_equals(sequence.length, 1); + assert_equals(sequence[0].type, "attributes"); + assert_equals(sequence[0].attributeName, "id"); + assert_equals(sequence[0].oldValue, "latest"); + disconnectTest.done(); + }); +} + +var observer; +disconnectTest.step(function() { + observer = new MutationObserver(observerCallback); + observer.observe(n00, {"attributes": true}); + n00.id = "foo"; + n00.id = "bar"; + observer.disconnect(); + observer.observe(n00, {"attributes": true, "attributeOldValue": true}); + n00.id = "latest"; + observer.disconnect(); + observer.observe(n00, {"attributes": true, "attributeOldValue": true}); + n00.id = "n0000"; +}); +</script> diff --git a/testing/web-platform/tests/dom/nodes/MutationObserver-document.html b/testing/web-platform/tests/dom/nodes/MutationObserver-document.html new file mode 100644 index 000000000..4662b2345 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/MutationObserver-document.html @@ -0,0 +1,167 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>MutationObservers: takeRecords</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="mutationobservers.js"></script> +<h1>MutationObservers: document mutations</h1> +<div id="log"></div> + +<script id='s001'> + var setupTest = async_test("setup test"); + var insertionTest = async_test("parser insertion mutations"); + var insertionTest2 = async_test("parser script insertion mutation"); + var testCounter = 0; + + function masterMO(sequence, obs) { + testCounter++; + if (testCounter == 1) { + insertionTest.step( + function () { + checkRecords(document, sequence, + [{type: "childList", + addedNodes: function () { + return [ document.getElementById("n00") ]; + }, + previousSibling: function () { + return document.getElementById("s001"); + }, + target: document.body}, + {type: "childList", + addedNodes: function () { + return [ document.getElementById("s002") ]; + }, + previousSibling: function () { + return document.getElementById("n00"); + }, + target: document.body}, + {type: "childList", + addedNodes: function () { + return [ document.getElementById("s002").firstChild ]; + }, + target: function () { + return document.getElementById("s002"); + }}]); + }); + } else if (testCounter == 2) { + insertionTest2.step( + function () { + checkRecords(document, sequence, + [{type: "childList", + addedNodes: function () { + return [ document.getElementById("inserted_script") ]; + }, + target: function () { + return document.getElementById("n00"); + }}, + {type: "childList", + addedNodes: function () { + return [ document.getElementById("inserted_element") ]; + }, + previousSibling: function () { + return document.getElementById("s002"); + }, + target: document.body} + ]); + }); + } + } + var document_observer; + var newElement; + setupTest.step(function() { + document_observer = new MutationObserver(masterMO); + newElement = document.createElement("span"); + document_observer.observe(document, {subtree:true,childList:true}); + newElement.id = "inserted_element"; + newElement.setAttribute("style", "display: none"); + newElement.textContent = "my new span for n00"; + }); +</script><p id='n00'></p><script id='s002'> + var newScript = document.createElement("script"); + setupTest.step(function() { + newScript.textContent = "document.body.appendChild(newElement);"; + newScript.id = "inserted_script"; + document.getElementById("n00").appendChild(newScript); + }); + if (testCounter < 1) { + insertionTest.step( + function () { + assert_unreached("document observer did not trigger"); + }); + } +</script><script id='s003'> + setupTest.step(function() { + document_observer.disconnect(); + }); + if (testCounter < 2) { + insertionTest2.step( + function () { + assert_unreached("document observer did not trigger"); + }); + } + insertionTest.done(); + insertionTest2.done(); +</script> + +<p id='n012'></p><div id='d01'> +<script id='s011'> + var removalTest = async_test("removal of parent during parsing"); + var d01 = document.getElementById("d01"); + testCounter = 0; + + function removalMO(sequence, obs) { + testCounter++; + if (testCounter == 1) { + removalTest.step( + function () { + checkRecords(document, sequence, + [{type: "childList", + removedNodes: function () { + return [ d01 ]; + }, + previousSibling: function () { + return document.getElementById("n012"); + }, + target: document.body}]); + }); + } else if (testCounter == 2) { + removalTest.step( + function () { + checkRecords(document, sequence, + [{type: "childList", + addedNodes: function () { + return [ document.getElementById("s012") ]; + }, + previousSibling: function () { + return document.getElementById("n012"); + }, + target: document.body}, + {type: "childList", + addedNodes: function () { + return [ document.getElementById("s012").firstChild ]; + }, + target: function () { + return document.getElementById("s012"); + }}]); + }); + } + } + var document2_observer; + setupTest.step(function() { + document2_observer = new MutationObserver(removalMO); + document2_observer.observe(document, {subtree:true,childList:true}); + d01.parentNode.removeChild(d01); + }); +</script><p id='n01'></p></div><script id='s012'> + setupTest.step(function() { + document2_observer.disconnect(); + }); + if (testCounter < 2) { + removalTest.step( + function () { + assert_unreached("document observer did not trigger"); + }); + } + removalTest.done(); + setupTest.done(); +</script> diff --git a/testing/web-platform/tests/dom/nodes/MutationObserver-inner-outer.html b/testing/web-platform/tests/dom/nodes/MutationObserver-inner-outer.html new file mode 100644 index 000000000..9f6d87141 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/MutationObserver-inner-outer.html @@ -0,0 +1,65 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>MutationObservers: innerHTML, outerHTML mutations</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="mutationobservers.js"></script> +<h1>MutationObservers: innerHTML, outerHTML mutations</h1> +<div id="log"></div> + +<section style="display: none"> + +<p id='n00'>old text</p> + +<p id='n01'>old text</p> + +<div id='n02'><p>old text</p></div> +</section> + +<script> + var n00; + var n00oldText; + var n01; + var n01oldText; + var n02; + + setup(function() { + n00 = document.getElementById('n00'); + n00oldText = n00.firstChild; + n01 = document.getElementById('n01'); + n01oldText = n01.firstChild; + n02 = document.getElementById('n02'); + }) + + runMutationTest(n00, + {childList:true,attributes:true}, + [{type: "childList", + removedNodes: [n00oldText], + addedNodes: function() { + return [document.getElementById("n00").firstChild]; + }}, + {type: "attributes", attributeName: "class"}], + function() { n00.innerHTML = "new text"; n00.className = "c01"}, + "innerHTML mutation"); + + runMutationTest(n01, + {childList:true}, + [{type: "childList", + removedNodes: [n01oldText], + addedNodes: function() { + return [document.getElementById("n01").firstChild, + document.getElementById("n01").lastChild]; + }}], + function() { n01.innerHTML = "<span>new</span><span>text</span>"; }, + "innerHTML with 2 children mutation"); + + runMutationTest(n02, + {childList:true}, + [{type: "childList", + removedNodes: [n02.firstChild], + addedNodes: function() { + return [n02.firstChild]; + }}], + function() { n02.firstChild.outerHTML = "<p>next text</p>"; }, + "outerHTML mutation"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/MutationObserver-takeRecords.html b/testing/web-platform/tests/dom/nodes/MutationObserver-takeRecords.html new file mode 100644 index 000000000..6a27ef77e --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/MutationObserver-takeRecords.html @@ -0,0 +1,53 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>MutationObservers: takeRecords</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="mutationobservers.js"></script> +<h1>MutationObservers: takeRecords</h1> +<div id="log"></div> + +<section style="display: none"> + +<p id='n00'></p> + +</section> + +<script> + + var n00 = document.getElementById('n00'); + + var unused = async_test("unreachabled test"); + + var observer; + unused.step(function () { + observer = new MutationObserver(unused.unreached_func("the observer callback should not fire")); + observer.observe(n00, { "subtree": true, + "childList": true, + "attributes": true, + "characterData": true, + "attributeOldValue": true, + "characterDataOldValue": true}); + n00.id = "foo"; + n00.id = "bar"; + n00.className = "bar"; + n00.textContent = "old data"; + n00.firstChild.data = "new data"; + }); + + test(function() { + checkRecords(n00, observer.takeRecords(), [{type: "attributes", attributeName: "id", oldValue: "n00"}, + {type: "attributes", attributeName: "id", oldValue: "foo"}, + {type: "attributes", attributeName: "class"}, + {type: "childList", addedNodes: [n00.firstChild]}, + {type: "characterData", oldValue: "old data", target: n00.firstChild}]); + }, "All records present"); + + test(function() { + checkRecords(n00, observer.takeRecords(), []); + }, "No more records present"); +</script> +<script> + unused.done(); + +</script> diff --git a/testing/web-platform/tests/dom/nodes/Node-appendChild.html b/testing/web-platform/tests/dom/nodes/Node-appendChild.html new file mode 100644 index 000000000..684607961 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-appendChild.html @@ -0,0 +1,59 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Node.appendChild</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-appendchild"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<iframe src=about:blank></iframe> +<script> +// TODO: Exhaustive tests +function testLeaf(node, desc) { + // WebIDL. + test(function() { + assert_throws(new TypeError(), function() { node.appendChild(null) }) + }, "Appending null to a " + desc) + + // Pre-insert step 1. + test(function() { + assert_throws("HIERARCHY_REQUEST_ERR", function() { node.appendChild(document.createTextNode("fail")) }) + }, "Appending to a " + desc) +} + +// WebIDL. +test(function() { + assert_throws(new TypeError(), function() { document.body.appendChild(null) }) + assert_throws(new TypeError(), function() { document.body.appendChild({'a':'b'}) }) +}, "WebIDL tests") + +// WebIDL and pre-insert step 1. +test(function() { + testLeaf(document.createTextNode("Foo"), "text node") + testLeaf(document.createComment("Foo"), "comment") + testLeaf(document.doctype, "doctype") +}, "Appending to a leaf node.") + +// Pre-insert step 5. +test(function() { + var frameDoc = frames[0].document + assert_throws("HIERARCHY_REQUEST_ERR", function() { document.body.appendChild(frameDoc) }) +}, "Appending a document") + +// Pre-insert step 8. +test(function() { + var frameDoc = frames[0].document + var s = frameDoc.createElement("a") + assert_equals(s.ownerDocument, frameDoc) + document.body.appendChild(s) + assert_equals(s.ownerDocument, document) +}, "Adopting an orphan") +test(function() { + var frameDoc = frames[0].document + var s = frameDoc.createElement("b") + assert_equals(s.ownerDocument, frameDoc) + frameDoc.body.appendChild(s) + assert_equals(s.ownerDocument, frameDoc) + document.body.appendChild(s) + assert_equals(s.ownerDocument, document) +}, "Adopting a non-orphan") +</script> diff --git a/testing/web-platform/tests/dom/nodes/Node-baseURI.html b/testing/web-platform/tests/dom/nodes/Node-baseURI.html new file mode 100644 index 000000000..1672b6ecd --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-baseURI.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<title>Node.baseURI</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + var element = document.createElement("div"); + document.body.appendChild(element); + assert_equals(element.baseURI, document.URL); +}, "For elements belonging to document, baseURI should be document url") + +test(function() { + var element = document.createElement("div"); + assert_equals(element.baseURI, document.URL); +}, "For elements unassigned to document, baseURI should be document url") + +test(function() { + var fragment = document.createDocumentFragment(); + var element = document.createElement("div"); + fragment.appendChild(element); + assert_equals(element.baseURI, document.URL) +}, "For elements belonging to document fragments, baseURI should be document url") + +test(function() { + var fragment = document.createDocumentFragment(); + var element = document.createElement("div"); + fragment.appendChild(element); + document.body.appendChild(fragment); + assert_equals(element.baseURI, document.URL) +}, "After inserting fragment into document, element baseURI should be document url") +</script> diff --git a/testing/web-platform/tests/dom/nodes/Node-childNodes.html b/testing/web-platform/tests/dom/nodes/Node-childNodes.html new file mode 100644 index 000000000..f7586fa74 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-childNodes.html @@ -0,0 +1,99 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Node.childNodes</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-childnodes"> +<link rel=author title="Tim Taubert" href="mailto:ttaubert@mozilla.com"> +<link rel=author title="Ms2ger" href="mailto:Ms2ger@gmail.com"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + var element = document.createElement("p"); + assert_equals(element.childNodes, element.childNodes); +}, "Caching of Node.childNodes"); + +var check_parent_node = function(node) { + assert_array_equals(node.childNodes, []); + + var children = node.childNodes; + var child = document.createElement("p"); + node.appendChild(child); + assert_equals(node.childNodes, children); + assert_array_equals(children, [child]); + assert_equals(children.item(0), child); + + var child2 = document.createComment("comment"); + node.appendChild(child2); + assert_array_equals(children, [child, child2]); + assert_equals(children.item(0), child); + assert_equals(children.item(1), child2); + + assert_false(2 in children); + assert_equals(children[2], undefined); + assert_equals(children.item(2), null); +}; + +test(function() { + check_parent_node(document.createElement("p")); +}, "Node.childNodes on an Element."); + +test(function() { + check_parent_node(document.createDocumentFragment()); +}, "Node.childNodes on a DocumentFragment."); + +test(function() { + check_parent_node(new Document()); +}, "Node.childNodes on a Document."); + +test(function() { + var node = document.createElement("div"); + var kid1 = document.createElement("p"); + var kid2 = document.createTextNode("hey"); + var kid3 = document.createElement("span"); + node.appendChild(kid1); + node.appendChild(kid2); + node.appendChild(kid3); + + var list = node.childNodes; + assert_array_equals([...list], [kid1, kid2, kid3]); + + var keys = list.keys(); + assert_false(keys instanceof Array); + keys = [...keys]; + assert_array_equals(keys, [0, 1, 2]); + + var values = list.values(); + assert_false(values instanceof Array); + values = [...values]; + assert_array_equals(values, [kid1, kid2, kid3]); + + var entries = list.entries(); + assert_false(entries instanceof Array); + entries = [...entries]; + assert_equals(entries.length, keys.length); + assert_equals(entries.length, values.length); + for (var i = 0; i < entries.length; ++i) { + assert_array_equals(entries[i], [keys[i], values[i]]); + } + + var cur = 0; + var thisObj = {}; + list.forEach(function(value, key, listObj) { + assert_equals(listObj, list); + assert_equals(this, thisObj); + assert_equals(value, values[cur]); + assert_equals(key, keys[cur]); + cur++; + }, thisObj); + assert_equals(cur, entries.length); + + assert_equals(list[Symbol.iterator], Array.prototype[Symbol.iterator]); + assert_equals(list.keys, Array.prototype.keys); + if (Array.prototype.values) { + assert_equals(list.values, Array.prototype.values); + } + assert_equals(list.entries, Array.prototype.entries); + assert_equals(list.forEach, Array.prototype.forEach); +}, "Iterator behavior of Node.childNodes"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Node-cloneNode.html b/testing/web-platform/tests/dom/nodes/Node-cloneNode.html new file mode 100644 index 000000000..9fb939f7e --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-cloneNode.html @@ -0,0 +1,272 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Node.cloneNode</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-clonenode"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +function assert_equal_node(nodeA, nodeB) { + assert_equals(nodeB.nodeType, nodeA.nodeType, "nodeType"); + assert_equals(nodeB.nodeName, nodeA.nodeName, "nodeName"); + + if (nodeA.nodeType === Node.ELEMENT_NODE) { + assert_equals(nodeB.prefix, nodeA.prefix); + assert_equals(nodeB.namespaceURI, nodeA.namespaceURI); + assert_equals(nodeB.localName, nodeA.localName); + assert_equals(nodeB.tagName, nodeA.tagName); + assert_not_equals(nodeB.attributes != nodeA.attributes); + assert_equals(nodeB.attributes.length, nodeA.attributes.length); + for (var i = 0, il = nodeA.attributes.length; i < il; ++i) { + assert_not_equals(nodeB.attributes[i], nodeA.attributes[i]); + assert_equals(nodeB.attributes[i].name, nodeA.attributes[i].name); + assert_equals(nodeB.attributes[i].prefix, nodeA.attributes[i].prefix); + assert_equals(nodeB.attributes[i].namespaceURI, nodeA.attributes[i].namespaceURI); + assert_equals(nodeB.attributes[i].value, nodeA.attributes[i].value); + } + } +} + +function check_copy(orig, copy, type) { + assert_not_equals(orig, copy); + assert_equal_node(orig, copy); + assert_true(orig instanceof type, "Should be type"); + assert_true(copy instanceof type, "Should be type"); +} + +function create_element_and_check(localName, type) { + test(function() { + var element = document.createElement(localName); + var copy = element.cloneNode(); + check_copy(element, copy, type); + }, "createElement(" + localName + ")"); +} + +// test1: createElement +test(function() { + create_element_and_check("a", HTMLAnchorElement); + create_element_and_check("abbr", HTMLElement); + create_element_and_check("acronym", HTMLElement); + create_element_and_check("address", HTMLElement); + create_element_and_check("applet", HTMLAppletElement); + create_element_and_check("area", HTMLAreaElement); + create_element_and_check("article", HTMLElement); + create_element_and_check("aside", HTMLElement); + create_element_and_check("audio", HTMLAudioElement); + create_element_and_check("b", HTMLElement); + create_element_and_check("base", HTMLBaseElement); + create_element_and_check("bdi", HTMLElement); + create_element_and_check("bdo", HTMLElement); + create_element_and_check("bgsound", HTMLElement); + create_element_and_check("big", HTMLElement); + create_element_and_check("blockquote",HTMLElement); + create_element_and_check("body", HTMLBodyElement); + create_element_and_check("br", HTMLBRElement); + create_element_and_check("button", HTMLButtonElement); + create_element_and_check("canvas", HTMLCanvasElement); + create_element_and_check("caption", HTMLTableCaptionElement); + create_element_and_check("center", HTMLElement); + create_element_and_check("cite", HTMLElement); + create_element_and_check("code", HTMLElement); + create_element_and_check("col", HTMLTableColElement); + create_element_and_check("colgroup", HTMLTableColElement); + create_element_and_check("data", HTMLDataElement); + create_element_and_check("datalist", HTMLDataListElement); + create_element_and_check("dialog", HTMLDialogElement); + create_element_and_check("dd", HTMLElement); + create_element_and_check("del", HTMLModElement); + create_element_and_check("details", HTMLElement); + create_element_and_check("dfn", HTMLElement); + create_element_and_check("dir", HTMLDirectoryElement); + create_element_and_check("div", HTMLDivElement); + create_element_and_check("dl", HTMLDListElement); + create_element_and_check("dt", HTMLElement); + create_element_and_check("embed", HTMLEmbedElement); + create_element_and_check("fieldset", HTMLFieldSetElement); + create_element_and_check("figcaption",HTMLElement); + create_element_and_check("figure", HTMLElement); + create_element_and_check("font", HTMLFontElement); + create_element_and_check("footer", HTMLElement); + create_element_and_check("form", HTMLFormElement); + create_element_and_check("frame", HTMLFrameElement); + create_element_and_check("frameset", HTMLFrameSetElement); + create_element_and_check("h1", HTMLHeadingElement); + create_element_and_check("h2", HTMLHeadingElement); + create_element_and_check("h3", HTMLHeadingElement); + create_element_and_check("h4", HTMLHeadingElement); + create_element_and_check("h5", HTMLHeadingElement); + create_element_and_check("h6", HTMLHeadingElement); + create_element_and_check("head", HTMLHeadElement); + create_element_and_check("header", HTMLElement); + create_element_and_check("hgroup", HTMLElement); + create_element_and_check("hr", HTMLHRElement); + create_element_and_check("html", HTMLHtmlElement); + create_element_and_check("i", HTMLElement); + create_element_and_check("iframe", HTMLIFrameElement); + create_element_and_check("img", HTMLImageElement); + create_element_and_check("input", HTMLInputElement); + create_element_and_check("ins", HTMLModElement); + create_element_and_check("isindex", HTMLElement); + create_element_and_check("kbd", HTMLElement); + create_element_and_check("label", HTMLLabelElement); + create_element_and_check("legend", HTMLLegendElement); + create_element_and_check("li", HTMLLIElement); + create_element_and_check("link", HTMLLinkElement); + create_element_and_check("main", HTMLElement); + create_element_and_check("map", HTMLMapElement); + create_element_and_check("mark", HTMLElement); + create_element_and_check("marquee", HTMLElement); + create_element_and_check("meta", HTMLMetaElement); + create_element_and_check("meter", HTMLMeterElement); + create_element_and_check("nav", HTMLElement); + create_element_and_check("nobr", HTMLElement); + create_element_and_check("noframes", HTMLElement); + create_element_and_check("noscript", HTMLElement); + create_element_and_check("object", HTMLObjectElement); + create_element_and_check("ol", HTMLOListElement); + create_element_and_check("optgroup", HTMLOptGroupElement); + create_element_and_check("option", HTMLOptionElement); + create_element_and_check("output", HTMLOutputElement); + create_element_and_check("p", HTMLParagraphElement); + create_element_and_check("param", HTMLParamElement); + create_element_and_check("pre", HTMLPreElement); + create_element_and_check("progress", HTMLProgressElement); + create_element_and_check("q", HTMLQuoteElement); + create_element_and_check("rp", HTMLElement); + create_element_and_check("rt", HTMLElement); + create_element_and_check("ruby", HTMLElement); + create_element_and_check("s", HTMLElement); + create_element_and_check("samp", HTMLElement); + create_element_and_check("script", HTMLScriptElement); + create_element_and_check("section", HTMLElement); + create_element_and_check("select", HTMLSelectElement); + create_element_and_check("small", HTMLElement); + create_element_and_check("source", HTMLSourceElement); + create_element_and_check("spacer", HTMLElement); + create_element_and_check("span", HTMLSpanElement); + create_element_and_check("strike", HTMLElement); + create_element_and_check("style", HTMLStyleElement); + create_element_and_check("sub", HTMLElement); + create_element_and_check("summary", HTMLElement); + create_element_and_check("sup", HTMLElement); + create_element_and_check("table", HTMLTableElement); + create_element_and_check("tbody", HTMLTableSectionElement); + create_element_and_check("td", HTMLTableCellElement); + create_element_and_check("template", HTMLTemplateElement); + create_element_and_check("textarea", HTMLTextAreaElement); + create_element_and_check("th", HTMLTableCellElement); + create_element_and_check("time", HTMLTimeElement); + create_element_and_check("title", HTMLTitleElement); + create_element_and_check("tr", HTMLTableRowElement); + create_element_and_check("tt", HTMLElement); + create_element_and_check("track", HTMLTrackElement); + create_element_and_check("u", HTMLElement); + create_element_and_check("ul", HTMLUListElement); + create_element_and_check("var", HTMLElement); + create_element_and_check("video", HTMLVideoElement); + create_element_and_check("unknown", HTMLUnknownElement); + create_element_and_check("wbr", HTMLElement); +}, ""); + +test(function() { + var fragment = document.createDocumentFragment(); + var copy = fragment.cloneNode(); + check_copy(fragment, copy, DocumentFragment); +}, "createDocumentFragment"); + +test(function() { + var text = document.createTextNode("hello world"); + var copy = text.cloneNode(); + check_copy(text, copy, Text); + assert_equals(text.data, copy.data); + assert_equals(text.wholeText, copy.wholeText); +}, "createTextNode"); + +test(function() { + var comment = document.createComment("a comment"); + var copy = comment.cloneNode(); + check_copy(comment, copy, Comment); + assert_equals(comment.data, copy.data); +}, "createComment"); + +test(function() { + var el = document.createElement("foo"); + el.setAttribute("a", "b"); + el.setAttribute("c", "d"); + var c = el.cloneNode(); + check_copy(el, c, Element); +}, "createElement with attributes") + +test(function() { + var el = document.createElementNS("http://www.w3.org/1999/xhtml", "foo:div"); + var c = el.cloneNode(); + check_copy(el, c, HTMLDivElement); +}, "createElementNS HTML") + +test(function() { + var el = document.createElementNS("http://www.example.com/", "foo:div"); + var c = el.cloneNode(); + check_copy(el, c, Element); +}, "createElementNS non-HTML") + +test(function() { + var pi = document.createProcessingInstruction("target", "data"); + var copy = pi.cloneNode(); + check_copy(pi, copy, ProcessingInstruction); + assert_equals(pi.data, copy.data); + assert_equals(pi.target, pi.target); +}, "createProcessingInstruction"); + +test(function() { + var doctype = document.implementation.createDocumentType("html", "public", "system"); + var copy = doctype.cloneNode(); + check_copy(doctype, copy, DocumentType); + assert_equals(doctype.name, copy.name); + assert_equals(doctype.publicId, copy.publicId); + assert_equals(doctype.systemId, copy.systemId); +}, "implementation.createDocumentType"); + +test(function() { + var doc = document.implementation.createDocument(null, null); + var copy = doc.cloneNode(); + check_copy(doc, copy, Document); + assert_equals(doc.contentType, copy.contentType); +}, "implementation.createDocument"); + +test(function() { + var html = document.implementation.createHTMLDocument("title"); + var copy = html.cloneNode(); + check_copy(html, copy, Document); + assert_equals(copy.title, ""); +}, "implementation.createHTMLDocument"); + +test(function() { + var parent = document.createElement("div"); + var child1 = document.createElement("div"); + var child2 = document.createElement("div"); + var grandChild = document.createElement("div"); + + child2.appendChild(grandChild); + parent.appendChild(child1); + parent.appendChild(child2); + + var deep = true; + var copy = parent.cloneNode(deep); + + check_copy(parent, copy, HTMLDivElement); + assert_equals(copy.childNodes.length, 2); + + check_copy(child1, copy.childNodes[0], HTMLDivElement); + assert_equals(copy.childNodes[0].childNodes.length, 0); + + check_copy(child2, copy.childNodes[1], HTMLDivElement); + assert_equals(copy.childNodes[1].childNodes.length, 1); + check_copy(grandChild, copy.childNodes[1].childNodes[0], HTMLDivElement); + + deep = false; + copy = parent.cloneNode(deep); + + check_copy(parent, copy, HTMLDivElement); + assert_equals(copy.childNodes.length, 0); +}, "node with children"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Node-compareDocumentPosition.html b/testing/web-platform/tests/dom/nodes/Node-compareDocumentPosition.html new file mode 100644 index 000000000..afae60aad --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-compareDocumentPosition.html @@ -0,0 +1,87 @@ +<!doctype html> +<title>Node.compareDocumentPosition() tests</title> +<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name> +<div id=log></div> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=../common.js></script> +<script> +"use strict"; + +testNodes.forEach(function(referenceName) { + var reference = eval(referenceName); + testNodes.forEach(function(otherName) { + var other = eval(otherName); + test(function() { + var result = reference.compareDocumentPosition(other); + + // "If other and reference are the same object, return zero and + // terminate these steps." + if (other === reference) { + assert_equals(result, 0); + return; + } + + // "If other and reference are not in the same tree, return the result of + // adding DOCUMENT_POSITION_DISCONNECTED, + // DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC, and either + // DOCUMENT_POSITION_PRECEDING or DOCUMENT_POSITION_FOLLOWING, with the + // constraint that this is to be consistent, together and terminate these + // steps." + if (furthestAncestor(reference) !== furthestAncestor(other)) { + // TODO: Test that it's consistent. + assert_in_array(result, [Node.DOCUMENT_POSITION_DISCONNECTED + + Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC + + Node.DOCUMENT_POSITION_PRECEDING, + Node.DOCUMENT_POSITION_DISCONNECTED + + Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC + + Node.DOCUMENT_POSITION_FOLLOWING]); + return; + } + + // "If other is an ancestor of reference, return the result of + // adding DOCUMENT_POSITION_CONTAINS to DOCUMENT_POSITION_PRECEDING + // and terminate these steps." + var ancestor = reference.parentNode; + while (ancestor && ancestor !== other) { + ancestor = ancestor.parentNode; + } + if (ancestor === other) { + assert_equals(result, Node.DOCUMENT_POSITION_CONTAINS + + Node.DOCUMENT_POSITION_PRECEDING); + return; + } + + // "If other is a descendant of reference, return the result of adding + // DOCUMENT_POSITION_CONTAINED_BY to DOCUMENT_POSITION_FOLLOWING and + // terminate these steps." + ancestor = other.parentNode; + while (ancestor && ancestor !== reference) { + ancestor = ancestor.parentNode; + } + if (ancestor === reference) { + assert_equals(result, Node.DOCUMENT_POSITION_CONTAINED_BY + + Node.DOCUMENT_POSITION_FOLLOWING); + return; + } + + // "If other is preceding reference return DOCUMENT_POSITION_PRECEDING + // and terminate these steps." + var prev = previousNode(reference); + while (prev && prev !== other) { + prev = previousNode(prev); + } + if (prev === other) { + assert_equals(result, Node.DOCUMENT_POSITION_PRECEDING); + return; + } + + // "Return DOCUMENT_POSITION_FOLLOWING." + assert_equals(result, Node.DOCUMENT_POSITION_FOLLOWING); + }, referenceName + ".compareDocumentPosition(" + otherName + ")"); + }); +}); + +testDiv.parentNode.removeChild(testDiv); +</script> +<!-- vim: set expandtab tabstop=2 shiftwidth=2: --> diff --git a/testing/web-platform/tests/dom/nodes/Node-constants.html b/testing/web-platform/tests/dom/nodes/Node-constants.html new file mode 100644 index 000000000..33e7c10e7 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-constants.html @@ -0,0 +1,39 @@ +<!doctype html> +<title>Node constants</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../constants.js"></script> +<div id="log"></div> +<script> +var objects; +setup(function() { + objects = [ + [Node, "Node interface object"], + [Node.prototype, "Node prototype object"], + [document.createElement("foo"), "Element object"], + [document.createTextNode("bar"), "Text object"] + ] +}) +testConstants(objects, [ + ["ELEMENT_NODE", 1], + ["ATTRIBUTE_NODE", 2], + ["TEXT_NODE", 3], + ["CDATA_SECTION_NODE", 4], + ["ENTITY_REFERENCE_NODE", 5], + ["ENTITY_NODE", 6], + ["PROCESSING_INSTRUCTION_NODE", 7], + ["COMMENT_NODE", 8], + ["DOCUMENT_NODE", 9], + ["DOCUMENT_TYPE_NODE", 10], + ["DOCUMENT_FRAGMENT_NODE", 11], + ["NOTATION_NODE", 12] +], "nodeType") +testConstants(objects, [ + ["DOCUMENT_POSITION_DISCONNECTED", 0x01], + ["DOCUMENT_POSITION_PRECEDING", 0x02], + ["DOCUMENT_POSITION_FOLLOWING", 0x04], + ["DOCUMENT_POSITION_CONTAINS", 0x08], + ["DOCUMENT_POSITION_CONTAINED_BY", 0x10], + ["DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC", 0x20] +], "createDocumentPosition") +</script> diff --git a/testing/web-platform/tests/dom/nodes/Node-contains-xml.xml b/testing/web-platform/tests/dom/nodes/Node-contains-xml.xml new file mode 100644 index 000000000..b95b7ffd1 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-contains-xml.xml @@ -0,0 +1,83 @@ +<!DOCTYPE html> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>Node.nodeName</title> +<link rel="author" title="Olli Pettay" href="mailto:Olli@Pettay.fi"/> +<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="log"/> +<div id="test"> + <input type="button" id="testbutton"/> + <a id="link">Link text</a> +</div> +<script> +<![CDATA[ +test(function() { + assert_throws(new TypeError(), function() { + document.contains(); + }); + assert_throws(new TypeError(), function() { + document.contains(9); + }); +}, "Should throw TypeError if the arguments are wrong."); + +test(function() { + assert_equals(document.contains(null), false, "Document shouldn't contain null."); +}, "contains(null) should be false"); + +test(function() { + assert_equals(document.contains(document), true, "Document should contain itself!"); + assert_equals(document.contains(document.createElement("foo")), false, "Document shouldn't contain element which is't in the document"); + assert_equals(document.contains(document.createTextNode("foo")), false, "Document shouldn't contain text node which is't in the document"); +}, "document.contains"); + +test(function() { + var tb = document.getElementById("testbutton"); + assert_equals(tb.contains(tb), true, "Element should contain itself.") + assert_equals(document.contains(tb), true, "Document should contain element in it!"); + assert_equals(document.documentElement.contains(tb), true, "Element should contain element in it!"); +}, "contains with a button"); + +test(function() { + var link = document.getElementById("link"); + var text = link.firstChild; + assert_equals(document.contains(text), true, "Document should contain a text node in it."); + assert_equals(link.contains(text), true, "Element should contain a text node in it."); + assert_equals(text.contains(text), true, "Text node should contain itself."); + assert_equals(text.contains(link), false, "text node shouldn't contain its parent."); +}, "contains with a text node"); + +test(function() { + var pi = document.createProcessingInstruction("adf", "asd"); + assert_equals(pi.contains(document), false, "Processing instruction shouldn't contain document"); + assert_equals(document.contains(pi), false, "Document shouldn't contain newly created processing instruction"); + document.documentElement.appendChild(pi); + document.contains(pi, true, "Document should contain processing instruction"); +}, "contains with a processing instruction"); + +test(function() { + if ("createContextualFragment" in document.createRange()) { + var df = document.createRange().createContextualFragment("<div>foo</div>"); + assert_equals(df.contains(df.firstChild), true, "Document fragment should contain its child"); + assert_equals(df.contains(df.firstChild.firstChild), true, + "Document fragment should contain its descendant"); + assert_equals(df.contains(df), true, "Document fragment should contain itself."); + } +}, "contains with a document fragment"); + +test(function() { + var d = document.implementation.createHTMLDocument(""); + assert_equals(document.contains(d), false, + "Document shouldn't contain another document."); + assert_equals(document.contains(d.createElement("div")), false, + "Document shouldn't contain an element from another document."); + assert_equals(document.contains(d.documentElement), false, + "Document shouldn't contain an element from another document."); +}, "contaibs with another document"); +]]> +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Node-contains.html b/testing/web-platform/tests/dom/nodes/Node-contains.html new file mode 100644 index 000000000..a3d644866 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-contains.html @@ -0,0 +1,36 @@ +<!doctype html> +<title>Node.contains() tests</title> +<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name> +<div id=log></div> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=../common.js></script> +<script> +"use strict"; + +testNodes.forEach(function(referenceName) { + var reference = eval(referenceName); + + test(function() { + assert_false(reference.contains(null)); + }, referenceName + ".contains(null)"); + + testNodes.forEach(function(otherName) { + var other = eval(otherName); + test(function() { + var ancestor = other; + while (ancestor && ancestor !== reference) { + ancestor = ancestor.parentNode; + } + if (ancestor === reference) { + assert_true(reference.contains(other)); + } else { + assert_false(reference.contains(other)); + } + }, referenceName + ".compareDocumentPosition(" + otherName + ")"); + }); +}); + +testDiv.parentNode.removeChild(testDiv); +</script> +<!-- vim: set expandtab tabstop=2 shiftwidth=2: --> diff --git a/testing/web-platform/tests/dom/nodes/Node-insertBefore.html b/testing/web-platform/tests/dom/nodes/Node-insertBefore.html new file mode 100644 index 000000000..a9fc83b50 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-insertBefore.html @@ -0,0 +1,306 @@ +<!DOCTYPE html> +<title>Node.insertBefore</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +function testLeafNode(nodeName, createNodeFunction) { + test(function() { + var node = createNodeFunction(); + assert_throws(new TypeError(), function() { node.insertBefore(null, null) }) + }, "Calling insertBefore with a non-Node first argument on a leaf node " + nodeName + " must throw TypeError.") + test(function() { + var node = createNodeFunction(); + assert_throws("HIERARCHY_REQUEST_ERR", function() { node.insertBefore(document.createTextNode("fail"), null) }) + // Would be step 2. + assert_throws("HIERARCHY_REQUEST_ERR", function() { node.insertBefore(node, null) }) + // Would be step 3. + assert_throws("HIERARCHY_REQUEST_ERR", function() { node.insertBefore(node, document.createTextNode("child")) }) + }, "Calling insertBefore an a leaf node " + nodeName + " must throw HIERARCHY_REQUEST_ERR.") +} + +test(function() { + // WebIDL. + assert_throws(new TypeError(), function() { document.body.insertBefore(null, null) }) + assert_throws(new TypeError(), function() { document.body.insertBefore(null, document.body.firstChild) }) + assert_throws(new TypeError(), function() { document.body.insertBefore({'a':'b'}, document.body.firstChild) }) +}, "Calling insertBefore with a non-Node first argument must throw TypeError.") + +testLeafNode("DocumentType", function () { return document.doctype; } ) +testLeafNode("Text", function () { return document.createTextNode("Foo") }) +testLeafNode("Comment", function () { return document.createComment("Foo") }) +testLeafNode("ProcessingInstruction", function () { return document.createProcessingInstruction("foo", "bar") }) + +test(function() { + // Step 2. + assert_throws("HIERARCHY_REQUEST_ERR", function() { document.body.insertBefore(document.body, document.getElementById("log")) }) + assert_throws("HIERARCHY_REQUEST_ERR", function() { document.body.insertBefore(document.documentElement, document.getElementById("log")) }) +}, "Calling insertBefore with an inclusive ancestor of the context object must throw HIERARCHY_REQUEST_ERR.") + +// Step 3. +test(function() { + var a = document.createElement("div"); + var b = document.createElement("div"); + var c = document.createElement("div"); + assert_throws("NotFoundError", function() { + a.insertBefore(b, c); + }); +}, "Calling insertBefore with a reference child whose parent is not the context node must throw a NotFoundError.") + +// Step 4.1. +test(function() { + var doc = document.implementation.createHTMLDocument("title"); + var doc2 = document.implementation.createHTMLDocument("title2"); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(doc2, doc.documentElement); + }); + + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(doc.createTextNode("text"), doc.documentElement); + }); +}, "If the context node is a document, inserting a document or text node should throw a HierarchyRequestError.") + +// Step 4.2.1. +test(function() { + var doc = document.implementation.createHTMLDocument("title"); + doc.removeChild(doc.documentElement); + + var df = doc.createDocumentFragment(); + df.appendChild(doc.createElement("a")); + df.appendChild(doc.createElement("b")); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(df, null); + }); + + df = doc.createDocumentFragment(); + df.appendChild(doc.createTextNode("text")); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(df, null); + }); + + df = doc.createDocumentFragment(); + df.appendChild(doc.createComment("comment")); + df.appendChild(doc.createTextNode("text")); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(df, null); + }); +}, "If the context node is a document, appending a DocumentFragment that contains a text node or too many elements should throw a HierarchyRequestError.") +test(function() { + var doc = document.implementation.createHTMLDocument("title"); + doc.removeChild(doc.documentElement); + + var df = doc.createDocumentFragment(); + df.appendChild(doc.createElement("a")); + df.appendChild(doc.createElement("b")); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(df, doc.firstChild); + }); + + df = doc.createDocumentFragment(); + df.appendChild(doc.createTextNode("text")); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(df, doc.firstChild); + }); + + df = doc.createDocumentFragment(); + df.appendChild(doc.createComment("comment")); + df.appendChild(doc.createTextNode("text")); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(df, doc.firstChild); + }); +}, "If the context node is a document, inserting a DocumentFragment that contains a text node or too many elements should throw a HierarchyRequestError.") + +// Step 4.2.2. +test(function() { + // The context node has an element child. + var doc = document.implementation.createHTMLDocument("title"); + var comment = doc.appendChild(doc.createComment("foo")); + assert_array_equals(doc.childNodes, [doc.doctype, doc.documentElement, comment]); + + var df = doc.createDocumentFragment(); + df.appendChild(doc.createElement("a")); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(df, doc.doctype); + }); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(df, doc.documentElement); + }); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(df, comment); + }); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(df, null); + }); +}, "If the context node is a document, inserting a DocumentFragment with an element if there already is an element child should throw a HierarchyRequestError.") +test(function() { + // /child/ is a doctype. + var doc = document.implementation.createHTMLDocument("title"); + var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild); + doc.removeChild(doc.documentElement); + assert_array_equals(doc.childNodes, [comment, doc.doctype]); + + var df = doc.createDocumentFragment(); + df.appendChild(doc.createElement("a")); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(df, doc.doctype); + }); +}, "If the context node is a document and a doctype is following the reference child, inserting a DocumentFragment with an element should throw a HierarchyRequestError.") +test(function() { + // /child/ is not null and a doctype is following /child/. + var doc = document.implementation.createHTMLDocument("title"); + var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild); + doc.removeChild(doc.documentElement); + assert_array_equals(doc.childNodes, [comment, doc.doctype]); + + var df = doc.createDocumentFragment(); + df.appendChild(doc.createElement("a")); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(df, comment); + }); +}, "If the context node is a document, inserting a DocumentFragment with an element before the doctype should throw a HierarchyRequestError.") + +// Step 4.3. +test(function() { + // The context node has an element child. + var doc = document.implementation.createHTMLDocument("title"); + var comment = doc.appendChild(doc.createComment("foo")); + assert_array_equals(doc.childNodes, [doc.doctype, doc.documentElement, comment]); + + var a = doc.createElement("a"); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(a, doc.doctype); + }); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(a, doc.documentElement); + }); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(a, comment); + }); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(a, null); + }); +}, "If the context node is a document, inserting an element if there already is an element child should throw a HierarchyRequestError.") +test(function() { + // /child/ is a doctype. + var doc = document.implementation.createHTMLDocument("title"); + var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild); + doc.removeChild(doc.documentElement); + assert_array_equals(doc.childNodes, [comment, doc.doctype]); + + var a = doc.createElement("a"); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(a, doc.doctype); + }); +}, "If the context node is a document, inserting an element before the doctype should throw a HierarchyRequestError.") +test(function() { + // /child/ is not null and a doctype is following /child/. + var doc = document.implementation.createHTMLDocument("title"); + var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild); + doc.removeChild(doc.documentElement); + assert_array_equals(doc.childNodes, [comment, doc.doctype]); + + var a = doc.createElement("a"); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(a, comment); + }); +}, "If the context node is a document and a doctype is following the reference child, inserting an element should throw a HierarchyRequestError.") + +// Step 4.4. +test(function() { + var doc = document.implementation.createHTMLDocument("title"); + var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild); + assert_array_equals(doc.childNodes, [comment, doc.doctype, doc.documentElement]); + + var doctype = document.implementation.createDocumentType("html", "", ""); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(doctype, comment); + }); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(doctype, doc.doctype); + }); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(doctype, doc.documentElement); + }); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(doctype, null); + }); +}, "If the context node is a document, inserting a doctype if there already is a doctype child should throw a HierarchyRequestError.") +test(function() { + var doc = document.implementation.createHTMLDocument("title"); + var comment = doc.appendChild(doc.createComment("foo")); + doc.removeChild(doc.doctype); + assert_array_equals(doc.childNodes, [doc.documentElement, comment]); + + var doctype = document.implementation.createDocumentType("html", "", ""); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(doctype, comment); + }); +}, "If the context node is a document, inserting a doctype after the document element should throw a HierarchyRequestError.") +test(function() { + var doc = document.implementation.createHTMLDocument("title"); + var comment = doc.appendChild(doc.createComment("foo")); + doc.removeChild(doc.doctype); + assert_array_equals(doc.childNodes, [doc.documentElement, comment]); + + var doctype = document.implementation.createDocumentType("html", "", ""); + assert_throws("HierarchyRequestError", function() { + doc.insertBefore(doctype, null); + }); +}, "If the context node is a document with and element child, appending a doctype should throw a HierarchyRequestError.") + +// Step 5. +test(function() { + var df = document.createDocumentFragment(); + var a = df.appendChild(document.createElement("a")); + + var doc = document.implementation.createHTMLDocument("title"); + assert_throws("HierarchyRequestError", function() { + df.insertBefore(doc, a); + }); + assert_throws("HierarchyRequestError", function() { + df.insertBefore(doc, null); + }); + + var doctype = document.implementation.createDocumentType("html", "", ""); + assert_throws("HierarchyRequestError", function() { + df.insertBefore(doctype, a); + }); + assert_throws("HierarchyRequestError", function() { + df.insertBefore(doctype, null); + }); +}, "If the context node is a DocumentFragment, inserting a document or a doctype should throw a HierarchyRequestError.") +test(function() { + var el = document.createElement("div"); + var a = el.appendChild(document.createElement("a")); + + var doc = document.implementation.createHTMLDocument("title"); + assert_throws("HierarchyRequestError", function() { + el.insertBefore(doc, a); + }); + assert_throws("HierarchyRequestError", function() { + el.insertBefore(doc, null); + }); + + var doctype = document.implementation.createDocumentType("html", "", ""); + assert_throws("HierarchyRequestError", function() { + el.insertBefore(doctype, a); + }); + assert_throws("HierarchyRequestError", function() { + el.insertBefore(doctype, null); + }); +}, "If the context node is an element, inserting a document or a doctype should throw a HierarchyRequestError.") + +// Step 7. +test(function() { + var a = document.createElement("div"); + var b = document.createElement("div"); + var c = document.createElement("div"); + a.appendChild(b); + a.appendChild(c); + assert_array_equals(a.childNodes, [b, c]); + assert_equals(a.insertBefore(b, b), b); + assert_array_equals(a.childNodes, [b, c]); + assert_equals(a.insertBefore(c, c), c); + assert_array_equals(a.childNodes, [b, c]); +}, "Inserting a node before itself should not move the node"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Node-isConnected.html b/testing/web-platform/tests/dom/nodes/Node-isConnected.html new file mode 100644 index 000000000..da0b460de --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-isConnected.html @@ -0,0 +1,95 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<head> +<title>Node.prototype.isConnected</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-isconnected"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> + +"use strict"; + +test(function() { + var nodes = [document.createElement("div"), + document.createElement("div"), + document.createElement("div")]; + checkNodes([], nodes); + + // Append nodes[0]. + document.body.appendChild(nodes[0]); + checkNodes([nodes[0]], + [nodes[1], nodes[2]]); + + // Append nodes[1] and nodes[2] together. + nodes[1].appendChild(nodes[2]); + checkNodes([nodes[0]], + [nodes[1], nodes[2]]); + + nodes[0].appendChild(nodes[1]); + checkNodes(nodes, []); + + // Remove nodes[2]. + nodes[2].remove(); + checkNodes([nodes[0], nodes[1]], + [nodes[2]]); + + // Remove nodes[0] and nodes[1] together. + nodes[0].remove(); + checkNodes([], nodes); +}, "Test with ordinary child nodes"); + +test(function() { + var nodes = [document.createElement("iframe"), + document.createElement("iframe"), + document.createElement("iframe"), + document.createElement("iframe"), + document.createElement("div")]; + var frames = [nodes[0], + nodes[1], + nodes[2], + nodes[3]]; + checkNodes([], nodes); + + // Since we cannot append anything to the contentWindow of an iframe before it + // is appended to the main DOM tree, we append the iframes one after another. + document.body.appendChild(nodes[0]); + checkNodes([nodes[0]], + [nodes[1], nodes[2], nodes[3], nodes[4]]); + + frames[0].contentDocument.body.appendChild(nodes[1]); + checkNodes([nodes[0], nodes[1]], + [nodes[2], nodes[3], nodes[4]]); + + frames[1].contentDocument.body.appendChild(nodes[2]); + checkNodes([nodes[0], nodes[1], nodes[2]], + [nodes[3], nodes[4]]); + + frames[2].contentDocument.body.appendChild(nodes[3]); + checkNodes([nodes[0], nodes[1], nodes[2], nodes[3]], + [nodes[4]]); + + frames[3].contentDocument.body.appendChild(nodes[4]); + checkNodes(nodes, []); + + frames[3].remove(); + // Since node[4] is still under the doument of frame[3], it's still connected. + checkNodes([nodes[0], nodes[1], nodes[2], nodes[4]], + [nodes[3]]); + + frames[0].remove(); + // Since node[1] and node[2] are still under the doument of frame[0], they are + // still connected. + checkNodes([nodes[1], nodes[2], nodes[4]], + [nodes[0], nodes[3]]); +}, "Test with iframes"); + +// This helper function is used to check whether nodes should be connected. +function checkNodes(aConnectedNodes, aDisconnectedNodes) { + aConnectedNodes.forEach(node => assert_true(node.isConnected)); + aDisconnectedNodes.forEach(node => assert_false(node.isConnected)); +} + +</script> +</body> diff --git a/testing/web-platform/tests/dom/nodes/Node-isEqualNode-iframe1.xml b/testing/web-platform/tests/dom/nodes/Node-isEqualNode-iframe1.xml new file mode 100644 index 000000000..8077e73c2 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-isEqualNode-iframe1.xml @@ -0,0 +1 @@ +<!DOCTYPE foo [ <!ELEMENT foo (#PCDATA)> ]><foo/> diff --git a/testing/web-platform/tests/dom/nodes/Node-isEqualNode-iframe2.xml b/testing/web-platform/tests/dom/nodes/Node-isEqualNode-iframe2.xml new file mode 100644 index 000000000..eacc9d17a --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-isEqualNode-iframe2.xml @@ -0,0 +1 @@ +<!DOCTYPE foo [ <!ELEMENT foo EMPTY> ]><foo/> diff --git a/testing/web-platform/tests/dom/nodes/Node-isEqualNode-xhtml.xhtml b/testing/web-platform/tests/dom/nodes/Node-isEqualNode-xhtml.xhtml new file mode 100644 index 000000000..3170643d2 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-isEqualNode-xhtml.xhtml @@ -0,0 +1,84 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>Node.isEqualNode</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="log"/> +<script> +function testNullHandling(node) { + test(function() { + assert_false(node.isEqualNode(null)) + assert_false(node.isEqualNode(undefined)) + }) +} +[ + document.createElement("foo"), + document.createTextNode("foo"), + document.createProcessingInstruction("foo", "bar"), + document.createComment("foo"), + document, + document.implementation.createDocumentType("html", "", ""), + document.createDocumentFragment() +].forEach(testNullHandling) + +test(function() { + var a = document.createElement("foo") + a.setAttribute("a", "bar") + a.setAttribute("b", "baz") + var b = document.createElement("foo") + b.setAttribute("b", "baz") + b.setAttribute("a", "bar") + assert_true(a.isEqualNode(b)) +}, "isEqualNode should return true when the attributes are in a different order") + +test(function() { + var a = document.createElementNS("ns", "prefix:foo") + var b = document.createElementNS("ns", "prefix:foo") + assert_true(a.isEqualNode(b)) +}, "isEqualNode should return true if elements have same namespace, prefix, and local name") + +test(function() { + var a = document.createElementNS("ns1", "prefix:foo") + var b = document.createElementNS("ns2", "prefix:foo") + assert_false(a.isEqualNode(b)) +}, "isEqualNode should return false if elements have different namespace") + +test(function() { + var a = document.createElementNS("ns", "prefix1:foo") + var b = document.createElementNS("ns", "prefix2:foo") + assert_false(a.isEqualNode(b)) +}, "isEqualNode should return false if elements have different prefix") + +test(function() { + var a = document.createElementNS("ns", "prefix:foo1") + var b = document.createElementNS("ns", "prefix:foo2") + assert_false(a.isEqualNode(b)) +}, "isEqualNode should return false if elements have different local name") + +test(function() { + var a = document.createElement("foo") + a.setAttributeNS("ns", "x:a", "bar") + var b = document.createElement("foo") + b.setAttributeNS("ns", "y:a", "bar") + assert_true(a.isEqualNode(b)) +}, "isEqualNode should return true when the attributes have different prefixes") +var internalSubset = async_test("isEqualNode should return true when only the internal subsets of DocumentTypes differ.") +var wait = 2; +function iframeLoaded() { + if (!--wait) { + internalSubset.step(function() { + var doc1 = document.getElementById("subset1").contentDocument + var doc2 = document.getElementById("subset2").contentDocument + assert_true(doc1.doctype.isEqualNode(doc2.doctype), "doc1.doctype.isEqualNode(doc2.doctype)") + assert_true(doc1.isEqualNode(doc2), "doc1.isEqualNode(doc2)") + }) + internalSubset.done() + } +} +</script> +<iframe id="subset1" onload="iframeLoaded()" src="Node-isEqualNode-iframe1.xml" /> +<iframe id="subset2" onload="iframeLoaded()" src="Node-isEqualNode-iframe2.xml" /> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Node-isEqualNode.html b/testing/web-platform/tests/dom/nodes/Node-isEqualNode.html new file mode 100644 index 000000000..9ff4c5b03 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-isEqualNode.html @@ -0,0 +1,161 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Node.prototype.isEqualNode</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-isequalnode"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +"use strict"; + +test(function() { + + var doctype1 = document.implementation.createDocumentType("qualifiedName", "publicId", "systemId"); + var doctype2 = document.implementation.createDocumentType("qualifiedName", "publicId", "systemId"); + var doctype3 = document.implementation.createDocumentType("qualifiedName2", "publicId", "systemId"); + var doctype4 = document.implementation.createDocumentType("qualifiedName", "publicId2", "systemId"); + var doctype5 = document.implementation.createDocumentType("qualifiedName", "publicId", "systemId3"); + + assert_true(doctype1.isEqualNode(doctype1), "self-comparison"); + assert_true(doctype1.isEqualNode(doctype2), "same properties"); + assert_false(doctype1.isEqualNode(doctype3), "different name"); + assert_false(doctype1.isEqualNode(doctype4), "different public ID"); + assert_false(doctype1.isEqualNode(doctype5), "different system ID"); + +}, "doctypes should be compared on name, public ID, and system ID"); + +test(function() { + + var element1 = document.createElementNS("namespace", "prefix:localName"); + var element2 = document.createElementNS("namespace", "prefix:localName"); + var element3 = document.createElementNS("namespace2", "prefix:localName"); + var element4 = document.createElementNS("namespace", "prefix2:localName"); + var element5 = document.createElementNS("namespace", "prefix:localName2"); + + var element6 = document.createElementNS("namespace", "prefix:localName"); + element6.setAttribute("foo", "bar"); + + assert_true(element1.isEqualNode(element1), "self-comparison"); + assert_true(element1.isEqualNode(element2), "same properties"); + assert_false(element1.isEqualNode(element3), "different namespace"); + assert_false(element1.isEqualNode(element4), "different prefix"); + assert_false(element1.isEqualNode(element5), "different local name"); + assert_false(element1.isEqualNode(element6), "different number of attributes"); + +}, "elements should be compared on namespace, namespace prefix, local name, and number of attributes"); + +test(function() { + + var element1 = document.createElement("element"); + element1.setAttributeNS("namespace", "prefix:localName", "value"); + + var element2 = document.createElement("element"); + element2.setAttributeNS("namespace", "prefix:localName", "value"); + + var element3 = document.createElement("element"); + element3.setAttributeNS("namespace2", "prefix:localName", "value"); + + var element4 = document.createElement("element"); + element4.setAttributeNS("namespace", "prefix2:localName", "value"); + + var element5 = document.createElement("element"); + element5.setAttributeNS("namespace", "prefix:localName2", "value"); + + var element6 = document.createElement("element"); + element6.setAttributeNS("namespace", "prefix:localName", "value2"); + + assert_true(element1.isEqualNode(element1), "self-comparison"); + assert_true(element1.isEqualNode(element2), "attribute with same properties"); + assert_false(element1.isEqualNode(element3), "attribute with different namespace"); + assert_true(element1.isEqualNode(element4), "attribute with different prefix"); + assert_false(element1.isEqualNode(element5), "attribute with different local name"); + assert_false(element1.isEqualNode(element6), "attribute with different value"); + +}, "elements should be compared on attribute namespace, local name, and value"); + +test(function() { + + var pi1 = document.createProcessingInstruction("target", "data"); + var pi2 = document.createProcessingInstruction("target", "data"); + var pi3 = document.createProcessingInstruction("target2", "data"); + var pi4 = document.createProcessingInstruction("target", "data2"); + + assert_true(pi1.isEqualNode(pi1), "self-comparison"); + assert_true(pi1.isEqualNode(pi2), "same properties"); + assert_false(pi1.isEqualNode(pi3), "different target"); + assert_false(pi1.isEqualNode(pi4), "different data"); + +}, "processing instructions should be compared on target and data"); + +test(function() { + + var text1 = document.createTextNode("data"); + var text2 = document.createTextNode("data"); + var text3 = document.createTextNode("data2"); + + assert_true(text1.isEqualNode(text1), "self-comparison"); + assert_true(text1.isEqualNode(text2), "same properties"); + assert_false(text1.isEqualNode(text3), "different data"); + +}, "text nodes should be compared on data"); + +test(function() { + + var comment1 = document.createComment("data"); + var comment2 = document.createComment("data"); + var comment3 = document.createComment("data2"); + + assert_true(comment1.isEqualNode(comment1), "self-comparison"); + assert_true(comment1.isEqualNode(comment2), "same properties"); + assert_false(comment1.isEqualNode(comment3), "different data"); + +}, "comments should be compared on data"); + +test(function() { + + var documentFragment1 = document.createDocumentFragment(); + var documentFragment2 = document.createDocumentFragment(); + + assert_true(documentFragment1.isEqualNode(documentFragment1), "self-comparison"); + assert_true(documentFragment1.isEqualNode(documentFragment2), "same properties"); + +}, "document fragments should not be compared based on properties"); + +test(function() { + + var document1 = document.implementation.createDocument("", ""); + var document2 = document.implementation.createDocument("", ""); + + assert_true(document1.isEqualNode(document1), "self-comparison"); + assert_true(document1.isEqualNode(document2), "another empty XML document"); + + var htmlDoctype = document.implementation.createDocumentType("html", "", ""); + var document3 = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", htmlDoctype); + document3.documentElement.appendChild(document3.createElement("head")); + document3.documentElement.appendChild(document3.createElement("body")); + var document4 = document.implementation.createHTMLDocument(); + assert_true(document3.isEqualNode(document4), "default HTML documents, created different ways"); + +}, "documents should not be compared based on properties"); + +test(function() { + + testDeepEquality(function() { return document.createElement("foo") }); + testDeepEquality(function() { return document.createDocumentFragment() }); + testDeepEquality(function() { return document.implementation.createDocument("", "") }); + testDeepEquality(function() { return document.implementation.createHTMLDocument() }); + + function testDeepEquality(parentFactory) { + // Some ad-hoc tests of deep equality + + var parentA = parentFactory(); + var parentB = parentFactory(); + + parentA.appendChild(document.createComment("data")); + assert_false(parentA.isEqualNode(parentB)); + parentB.appendChild(document.createComment("data")); + assert_true(parentA.isEqualNode(parentB)); + } + +}, "node equality testing should test descendant equality too"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Node-isSameNode.html b/testing/web-platform/tests/dom/nodes/Node-isSameNode.html new file mode 100644 index 000000000..884fdd504 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-isSameNode.html @@ -0,0 +1,100 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Node.prototype.isSameNode</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-issamenode"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +"use strict"; + +test(function() { + + var doctype1 = document.implementation.createDocumentType("qualifiedName", "publicId", "systemId"); + var doctype2 = document.implementation.createDocumentType("qualifiedName", "publicId", "systemId"); + + assert_true(doctype1.isSameNode(doctype1), "self-comparison"); + assert_false(doctype1.isSameNode(doctype2), "same properties"); + assert_false(doctype1.isSameNode(null), "with null other node"); +}, "doctypes should be comapred on reference"); + +test(function() { + + var element1 = document.createElementNS("namespace", "prefix:localName"); + var element2 = document.createElementNS("namespace", "prefix:localName"); + + assert_true(element1.isSameNode(element1), "self-comparison"); + assert_false(element1.isSameNode(element2), "same properties"); + assert_false(element1.isSameNode(null), "with null other node"); + +}, "elements should be compared on reference"); + +test(function() { + + var element1 = document.createElement("element"); + element1.setAttributeNS("namespace", "prefix:localName", "value"); + + var element2 = document.createElement("element"); + element2.setAttributeNS("namespace", "prefix:localName", "value"); + + assert_true(element1.isSameNode(element1), "self-comparison"); + assert_false(element1.isSameNode(element2), "same properties"); + assert_false(element1.isSameNode(null), "with null other node"); + +}, "elements should be compared on reference"); + +test(function() { + + var pi1 = document.createProcessingInstruction("target", "data"); + var pi2 = document.createProcessingInstruction("target", "data"); + + assert_true(pi1.isSameNode(pi1), "self-comparison"); + assert_false(pi1.isSameNode(pi2), "different target"); + assert_false(pi1.isSameNode(null), "with null other node"); + +}, "processing instructions should be compared on reference"); + +test(function() { + + var text1 = document.createTextNode("data"); + var text2 = document.createTextNode("data"); + + assert_true(text1.isSameNode(text1), "self-comparison"); + assert_false(text1.isSameNode(text2), "same properties"); + assert_false(text1.isSameNode(null), "with null other node"); + +}, "text nodes should be compared on reference"); + +test(function() { + + var comment1 = document.createComment("data"); + var comment2 = document.createComment("data"); + + assert_true(comment1.isSameNode(comment1), "self-comparison"); + assert_false(comment1.isSameNode(comment2), "same properties"); + assert_false(comment1.isSameNode(null), "with null other node"); + +}, "comments should be compared on reference"); + +test(function() { + + var documentFragment1 = document.createDocumentFragment(); + var documentFragment2 = document.createDocumentFragment(); + + assert_true(documentFragment1.isSameNode(documentFragment1), "self-comparison"); + assert_false(documentFragment1.isSameNode(documentFragment2), "same properties"); + assert_false(documentFragment1.isSameNode(null), "with null other node"); + +}, "document fragments should be compared on reference"); + +test(function() { + + var document1 = document.implementation.createDocument("", ""); + var document2 = document.implementation.createDocument("", ""); + + assert_true(document1.isSameNode(document1), "self-comparison"); + assert_false(document1.isSameNode(document2), "another empty XML document"); + assert_false(document1.isSameNode(null), "with null other node"); + +}, "documents should not be compared on reference"); + +</script> diff --git a/testing/web-platform/tests/dom/nodes/Node-lookupNamespaceURI.html b/testing/web-platform/tests/dom/nodes/Node-lookupNamespaceURI.html new file mode 100644 index 000000000..45b6c0fbb --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-lookupNamespaceURI.html @@ -0,0 +1,116 @@ +<!DOCTYPE html> +<html> +<head> +<title>LookupNamespaceURI and IsDefaultNamespace tests</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +</head> +<body> +<h1>LookupNamespaceURI and IsDefaultNamespace</h1> +<div id="log"/> +<script> +function lookupNamespaceURI(node, prefix, expected, name) { + test(function() { + assert_equals(node.lookupNamespaceURI(prefix), expected); + }, name); +} + +function isDefaultNamespace(node, namespace, expected, name) { + test(function() { + assert_equals(node.isDefaultNamespace(namespace), expected); + }, name); +} + + +var frag = document.createDocumentFragment(); +lookupNamespaceURI(frag, null, null, 'DocumentFragment should have null namespace, prefix null'); +lookupNamespaceURI(frag, '', null, 'DocumentFragment should have null namespace, prefix ""'); +lookupNamespaceURI(frag, 'foo', null, 'DocumentFragment should have null namespace, prefix "foo"'); +lookupNamespaceURI(frag, 'xmlns', null, 'DocumentFragment should have null namespace, prefix "xmlns"'); +isDefaultNamespace(frag, null, true, 'DocumentFragment is in default namespace, prefix null'); +isDefaultNamespace(frag, '', true, 'DocumentFragment is in default namespace, prefix ""'); +isDefaultNamespace(frag, 'foo', false, 'DocumentFragment is in default namespace, prefix "foo"'); +isDefaultNamespace(frag, 'xmlns', false, 'DocumentFragment is in default namespace, prefix "xmlns"'); + + + +var fooElem = document.createElementNS('fooNamespace', 'prefix:elem'); +fooElem.setAttribute('bar', 'value'); + +lookupNamespaceURI(fooElem, null, null, 'Element should have null namespace, prefix null'); +lookupNamespaceURI(fooElem, '', null, 'Element should have null namespace, prefix ""'); +lookupNamespaceURI(fooElem, 'fooNamespace', null, 'Element should not have namespace matching prefix with namespaceURI value'); +lookupNamespaceURI(fooElem, 'xmlns', null, 'Element should not have XMLNS namespace'); +lookupNamespaceURI(fooElem, 'prefix', 'fooNamespace', 'Element has namespace URI matching prefix'); +isDefaultNamespace(fooElem, null, true, 'Empty namespace is not default, prefix null'); +isDefaultNamespace(fooElem, '', true, 'Empty namespace is not default, prefix ""'); +isDefaultNamespace(fooElem, 'fooNamespace', false, 'fooNamespace is not default'); +isDefaultNamespace(fooElem, 'http://www.w3.org/2000/xmlns/', false, 'xmlns namespace is not default'); + +fooElem.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:bar', 'barURI'); +fooElem.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'bazURI'); + +lookupNamespaceURI(fooElem, null, 'bazURI', 'Element should have baz namespace, prefix null'); +lookupNamespaceURI(fooElem, '', 'bazURI', 'Element should have baz namespace, prefix ""'); +lookupNamespaceURI(fooElem, 'xmlns', null, 'Element does not has namespace with xlmns prefix'); +lookupNamespaceURI(fooElem, 'bar', 'barURI', 'Element has bar namespace'); + +isDefaultNamespace(fooElem, null, false, 'Empty namespace is not default on fooElem, prefix null'); +isDefaultNamespace(fooElem, '', false, 'Empty namespace is not default on fooElem, prefix ""'); +isDefaultNamespace(fooElem, 'barURI', false, 'bar namespace is not default'); +isDefaultNamespace(fooElem, 'bazURI', true, 'baz namespace is default'); + +var comment = document.createComment('comment'); +fooElem.appendChild(comment); + +lookupNamespaceURI(comment, null, 'bazURI', 'Comment should inherit baz namespace'); +lookupNamespaceURI(comment, '', 'bazURI', 'Comment should inherit baz namespace'); +lookupNamespaceURI(comment, 'prefix', 'fooNamespace', 'Comment should inherit namespace URI matching prefix'); +lookupNamespaceURI(comment, 'bar', 'barURI', 'Comment should inherit bar namespace'); + +isDefaultNamespace(comment, null, false, 'For comment, empty namespace is not default, prefix null'); +isDefaultNamespace(comment, '', false, 'For comment, empty namespace is not default, prefix ""'); +isDefaultNamespace(comment, 'fooNamespace', false, 'For comment, fooNamespace is not default'); +isDefaultNamespace(comment, 'http://www.w3.org/2000/xmlns/', false, 'For comment, xmlns namespace is not default'); +isDefaultNamespace(comment, 'barURI', false, 'For comment, inherited bar namespace is not default'); +isDefaultNamespace(comment, 'bazURI', true, 'For comment, inherited baz namespace is default'); + +var fooChild = document.createElementNS('childNamespace', 'childElem'); +fooElem.appendChild(fooChild); + +lookupNamespaceURI(fooChild, null, 'childNamespace', 'Child element should inherit baz namespace'); +lookupNamespaceURI(fooChild, '', 'childNamespace', 'Child element should have null namespace'); +lookupNamespaceURI(fooChild, 'xmlns', null, 'Child element should not have XMLNS namespace'); +lookupNamespaceURI(fooChild, 'prefix', 'fooNamespace', 'Child element has namespace URI matching prefix'); + +isDefaultNamespace(fooChild, null, false, 'Empty namespace is not default for child, prefix null'); +isDefaultNamespace(fooChild, '', false, 'Empty namespace is not default for child, prefix ""'); +isDefaultNamespace(fooChild, 'fooNamespace', false, 'fooNamespace is not default for child'); +isDefaultNamespace(fooChild, 'http://www.w3.org/2000/xmlns/', false, 'xmlns namespace is not default for child'); +isDefaultNamespace(fooChild, 'barURI', false, 'bar namespace is not default for child'); +isDefaultNamespace(fooChild, 'bazURI', false, 'baz namespace is default for child'); +isDefaultNamespace(fooChild, 'childNamespace', true, 'childNamespace is default for child'); + +document.documentElement.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:bar', 'barURI'); +document.documentElement.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'bazURI'); + +lookupNamespaceURI(document, null, 'http://www.w3.org/1999/xhtml', 'Document should have xhtml namespace, prefix null'); +lookupNamespaceURI(document, '', 'http://www.w3.org/1999/xhtml', 'Document should have xhtml namespace, prefix ""'); +lookupNamespaceURI(document, 'prefix', null, 'Document has no namespace URI matching prefix'); +lookupNamespaceURI(document, 'bar', 'barURI', 'Document has bar namespace'); + +isDefaultNamespace(document, null, false, 'For document, empty namespace is not default, prefix null'); +isDefaultNamespace(document, '', false, 'For document, empty namespace is not default, prefix ""'); +isDefaultNamespace(document, 'fooNamespace', false, 'For document, fooNamespace is not default'); +isDefaultNamespace(document, 'http://www.w3.org/2000/xmlns/', false, 'For document, xmlns namespace is not default'); +isDefaultNamespace(document, 'barURI', false, 'For document, bar namespace is not default'); +isDefaultNamespace(document, 'bazURI', false, 'For document, baz namespace is not default'); +isDefaultNamespace(document, 'http://www.w3.org/1999/xhtml', true, 'For document, xhtml namespace is default'); + +var comment = document.createComment('comment'); +document.appendChild(comment); +lookupNamespaceURI(comment, 'bar', null, 'Comment does not have bar namespace'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Node-lookupPrefix.xhtml b/testing/web-platform/tests/dom/nodes/Node-lookupPrefix.xhtml new file mode 100644 index 000000000..50a487c58 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-lookupPrefix.xhtml @@ -0,0 +1,31 @@ +<html xmlns="http://www.w3.org/1999/xhtml" xmlns:x="test"> +<head> +<title>Node.lookupPrefix</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body xmlns:s="test"> +<div id="log"/> +<x xmlns:t="test"><!--comment--><?test test?>TEST<x/></x> +<script> +function lookupPrefix(node, ns, prefix) { + test(function() { + assert_equals(node.lookupPrefix(ns), prefix) + }) +} +var x = document.getElementsByTagName("x")[0]; +lookupPrefix(document, "test", "x") // XXX add test for when there is no documentElement +lookupPrefix(document, null, null) +lookupPrefix(x, "http://www.w3.org/1999/xhtml", null) +lookupPrefix(x, "something", null) +lookupPrefix(x, null, null) +lookupPrefix(x, "test", "t") +lookupPrefix(x.parentNode, "test", "s") +lookupPrefix(x.firstChild, "test", "t") +lookupPrefix(x.childNodes[1], "test", "t") +lookupPrefix(x.childNodes[2], "test", "t") +lookupPrefix(x.lastChild, "test", "t") +x.parentNode.removeChild(x) +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Node-nodeName-xhtml.xhtml b/testing/web-platform/tests/dom/nodes/Node-nodeName-xhtml.xhtml new file mode 100644 index 000000000..bc478af8b --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-nodeName-xhtml.xhtml @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>Node.nodeName</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="log"/> +<script> +test(function() { + var HTMLNS = "http://www.w3.org/1999/xhtml", + SVGNS = "http://www.w3.org/2000/svg" + assert_equals(document.createElementNS(HTMLNS, "I").nodeName, "I") + assert_equals(document.createElementNS(HTMLNS, "i").nodeName, "i") + assert_equals(document.createElementNS(SVGNS, "svg").nodeName, "svg") + assert_equals(document.createElementNS(SVGNS, "SVG").nodeName, "SVG") + assert_equals(document.createElementNS(HTMLNS, "x:b").nodeName, "x:b") +}, "For Element nodes, nodeName should return the same as tagName.") +test(function() { + assert_equals(document.createTextNode("foo").nodeName, "#text") +}, "For Text nodes, nodeName should return \"#text\".") +test(function() { + assert_equals(document.createProcessingInstruction("foo", "bar").nodeName, + "foo") +}, "For ProcessingInstruction nodes, nodeName should return the target.") +test(function() { + assert_equals(document.createComment("foo").nodeName, "#comment") +}, "For Comment nodes, nodeName should return \"#comment\".") +test(function() { + assert_equals(document.nodeName, "#document") +}, "For Document nodes, nodeName should return \"#document\".") +test(function() { + assert_equals(document.doctype.nodeName, "html") +}, "For DocumentType nodes, nodeName should return the name.") +test(function() { + assert_equals(document.createDocumentFragment().nodeName, + "#document-fragment") +}, "For DocumentFragment nodes, nodeName should return \"#document-fragment\".") +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Node-nodeName.html b/testing/web-platform/tests/dom/nodes/Node-nodeName.html new file mode 100644 index 000000000..911f93455 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-nodeName.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<title>Node.nodeName</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + var HTMLNS = "http://www.w3.org/1999/xhtml", + SVGNS = "http://www.w3.org/2000/svg" + assert_equals(document.createElementNS(HTMLNS, "I").nodeName, "I") + assert_equals(document.createElementNS(HTMLNS, "i").nodeName, "I") + assert_equals(document.createElementNS(SVGNS, "svg").nodeName, "svg") + assert_equals(document.createElementNS(SVGNS, "SVG").nodeName, "SVG") + assert_equals(document.createElementNS(HTMLNS, "x:b").nodeName, "X:B") +}, "For Element nodes, nodeName should return the same as tagName.") +test(function() { + assert_equals(document.createTextNode("foo").nodeName, "#text") +}, "For Text nodes, nodeName should return \"#text\".") +test(function() { + assert_equals(document.createComment("foo").nodeName, "#comment") +}, "For Comment nodes, nodeName should return \"#comment\".") +test(function() { + assert_equals(document.nodeName, "#document") +}, "For Document nodes, nodeName should return \"#document\".") +test(function() { + assert_equals(document.doctype.nodeName, "html") +}, "For DocumentType nodes, nodeName should return the name.") +test(function() { + assert_equals(document.createDocumentFragment().nodeName, + "#document-fragment") +}, "For DocumentFragment nodes, nodeName should return \"#document-fragment\".") +</script> diff --git a/testing/web-platform/tests/dom/nodes/Node-nodeValue.html b/testing/web-platform/tests/dom/nodes/Node-nodeValue.html new file mode 100644 index 000000000..79ce80b87 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-nodeValue.html @@ -0,0 +1,71 @@ +<!doctype html> +<meta charset=utf-8> +<title>Node.nodeValue</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodevalue"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<script> +test(function() { + var the_text = document.createTextNode("A span!"); + assert_equals(the_text.nodeValue, "A span!"); + assert_equals(the_text.data, "A span!"); + the_text.nodeValue = "test again"; + assert_equals(the_text.nodeValue, "test again"); + assert_equals(the_text.data, "test again"); + the_text.nodeValue = null; + assert_equals(the_text.nodeValue, ""); + assert_equals(the_text.data, ""); +}, "Text.nodeValue"); + +test(function() { + var the_comment = document.createComment("A comment!"); + assert_equals(the_comment.nodeValue, "A comment!"); + assert_equals(the_comment.data, "A comment!"); + the_comment.nodeValue = "test again"; + assert_equals(the_comment.nodeValue, "test again"); + assert_equals(the_comment.data, "test again"); + the_comment.nodeValue = null; + assert_equals(the_comment.nodeValue, ""); + assert_equals(the_comment.data, ""); +}, "Comment.nodeValue"); + +test(function() { + var the_pi = document.createProcessingInstruction("pi", "A PI!"); + assert_equals(the_pi.nodeValue, "A PI!"); + assert_equals(the_pi.data, "A PI!"); + the_pi.nodeValue = "test again"; + assert_equals(the_pi.nodeValue, "test again"); + assert_equals(the_pi.data, "test again"); + the_pi.nodeValue = null; + assert_equals(the_pi.nodeValue, ""); + assert_equals(the_pi.data, ""); +}, "ProcessingInstruction.nodeValue"); + +test(function() { + var the_link = document.createElement("a"); + assert_equals(the_link.nodeValue, null); + the_link.nodeValue = "foo"; + assert_equals(the_link.nodeValue, null); +}, "Element.nodeValue"); + +test(function() { + assert_equals(document.nodeValue, null); + document.nodeValue = "foo"; + assert_equals(document.nodeValue, null); +}, "Document.nodeValue"); + +test(function() { + var the_frag = document.createDocumentFragment(); + assert_equals(the_frag.nodeValue, null); + the_frag.nodeValue = "foo"; + assert_equals(the_frag.nodeValue, null); +}, "DocumentFragment.nodeValue"); + +test(function() { + var the_doctype = document.doctype; + assert_equals(the_doctype.nodeValue, null); + the_doctype.nodeValue = "foo"; + assert_equals(the_doctype.nodeValue, null); +}, "DocumentType.nodeValue"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Node-normalize.html b/testing/web-platform/tests/dom/nodes/Node-normalize.html new file mode 100644 index 000000000..7598852e6 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-normalize.html @@ -0,0 +1,54 @@ +<!DOCTYPE html> +<title>Node.normalize()</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +test(function() { + var df = document.createDocumentFragment(), + t1 = document.createTextNode("1"), + t2 = document.createTextNode("2"), + t3 = document.createTextNode("3"), + t4 = document.createTextNode("4") + df.appendChild(t1) + df.appendChild(t2) + assert_equals(df.childNodes.length, 2) + assert_equals(df.textContent, "12") + var el = document.createElement('x') + df.appendChild(el) + el.appendChild(t3) + el.appendChild(t4) + document.normalize() + assert_equals(el.childNodes.length, 2) + assert_equals(el.textContent, "34") + assert_equals(df.childNodes.length, 3) + assert_equals(t1.data, "1") + df.normalize() + assert_equals(df.childNodes.length, 2) + assert_equals(df.firstChild, t1) + assert_equals(t1.data, "12") + assert_equals(t2.data, "2") + assert_equals(el.firstChild, t3) + assert_equals(t3.data, "34") + assert_equals(t4.data, "4") +}) + +// https://www.w3.org/Bugs/Public/show_bug.cgi?id=19837 +test(function() { + var div = document.createElement("div") + var t1 = div.appendChild(document.createTextNode("")) + var t2 = div.appendChild(document.createTextNode("a")) + var t3 = div.appendChild(document.createTextNode("")) + assert_array_equals(div.childNodes, [t1, t2, t3]) + div.normalize(); + assert_array_equals(div.childNodes, [t2]) +}, "Empty text nodes separated by a non-empty text node") +test(function() { + var div = document.createElement("div") + var t1 = div.appendChild(document.createTextNode("")) + var t2 = div.appendChild(document.createTextNode("")) + assert_array_equals(div.childNodes, [t1, t2]) + div.normalize(); + assert_array_equals(div.childNodes, []) +}, "Empty text nodes") +</script> diff --git a/testing/web-platform/tests/dom/nodes/Node-parentElement.html b/testing/web-platform/tests/dom/nodes/Node-parentElement.html new file mode 100644 index 000000000..bc564bee0 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-parentElement.html @@ -0,0 +1,82 @@ +<!DOCTYPE html> +<title>Node.parentElement</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + assert_equals(document.parentElement, null) +}, "When the parent is null, parentElement should be null") +test(function() { + assert_equals(document.doctype.parentElement, null) +}, "When the parent is a document, parentElement should be null (doctype)") +test(function() { + assert_equals(document.documentElement.parentElement, null) +}, "When the parent is a document, parentElement should be null (element)") +test(function() { + var comment = document.appendChild(document.createComment("foo")) + assert_equals(comment.parentElement, null) +}, "When the parent is a document, parentElement should be null (comment)") +test(function() { + var df = document.createDocumentFragment() + assert_equals(df.parentElement, null) + var el = document.createElement("div") + assert_equals(el.parentElement, null) + df.appendChild(el) + assert_equals(el.parentNode, df) + assert_equals(el.parentElement, null) +}, "parentElement should return null for children of DocumentFragments (element)") +test(function() { + var df = document.createDocumentFragment() + assert_equals(df.parentElement, null) + var text = document.createTextNode("bar") + assert_equals(text.parentElement, null) + df.appendChild(text) + assert_equals(text.parentNode, df) + assert_equals(text.parentElement, null) +}, "parentElement should return null for children of DocumentFragments (text)") +test(function() { + var df = document.createDocumentFragment() + var parent = document.createElement("div") + df.appendChild(parent) + var el = document.createElement("div") + assert_equals(el.parentElement, null) + parent.appendChild(el) + assert_equals(el.parentElement, parent) +}, "parentElement should work correctly with DocumentFragments (element)") +test(function() { + var df = document.createDocumentFragment() + var parent = document.createElement("div") + df.appendChild(parent) + var text = document.createTextNode("bar") + assert_equals(text.parentElement, null) + parent.appendChild(text) + assert_equals(text.parentElement, parent) +}, "parentElement should work correctly with DocumentFragments (text)") +test(function() { + var parent = document.createElement("div") + var el = document.createElement("div") + assert_equals(el.parentElement, null) + parent.appendChild(el) + assert_equals(el.parentElement, parent) +}, "parentElement should work correctly in disconnected subtrees (element)") +test(function() { + var parent = document.createElement("div") + var text = document.createTextNode("bar") + assert_equals(text.parentElement, null) + parent.appendChild(text) + assert_equals(text.parentElement, parent) +}, "parentElement should work correctly in disconnected subtrees (text)") +test(function() { + var el = document.createElement("div") + assert_equals(el.parentElement, null) + document.body.appendChild(el) + assert_equals(el.parentElement, document.body) +}, "parentElement should work correctly in a document (element)") +test(function() { + var text = document.createElement("div") + assert_equals(text.parentElement, null) + document.body.appendChild(text) + assert_equals(text.parentElement, document.body) +}, "parentElement should work correctly in a document (text)") +</script> diff --git a/testing/web-platform/tests/dom/nodes/Node-parentNode-iframe.html b/testing/web-platform/tests/dom/nodes/Node-parentNode-iframe.html new file mode 100644 index 000000000..88bc5ab43 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-parentNode-iframe.html @@ -0,0 +1 @@ +<a name='c'>c</a>
\ No newline at end of file diff --git a/testing/web-platform/tests/dom/nodes/Node-parentNode.html b/testing/web-platform/tests/dom/nodes/Node-parentNode.html new file mode 100644 index 000000000..cff617862 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-parentNode.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<title>Node.parentNode</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +// XXX need to test for more node types +test(function() { + assert_equals(document.parentNode, null) +}, "Document") +test(function() { + assert_equals(document.doctype.parentNode, document) +}, "Doctype") +test(function() { + assert_equals(document.documentElement.parentNode, document) +}, "Root element") +test(function() { + var el = document.createElement("div") + assert_equals(el.parentNode, null) + document.body.appendChild(el) + assert_equals(el.parentNode, document.body) +}, "Element") +var t = async_test("Removed iframe"); +function testIframe(iframe) { + t.step(function() { + var doc = iframe.contentDocument; + iframe.parentNode.removeChild(iframe); + assert_equals(doc.firstChild.parentNode, doc); + }); + t.done(); +} +</script> +<iframe id=a src="Node-parentNode-iframe.html" onload="testIframe(this)"></iframe> diff --git a/testing/web-platform/tests/dom/nodes/Node-properties.html b/testing/web-platform/tests/dom/nodes/Node-properties.html new file mode 100644 index 000000000..10f92e7d7 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-properties.html @@ -0,0 +1,688 @@ +<!doctype html> +<title>Node assorted property tests</title> +<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name> +<meta charset=utf-8> +<div id=log></div> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=../common.js></script> +<script> +"use strict"; +/** + * First we define a data structure to tell us what tests to run. The keys + * will be eval()ed, and are mostly global variables defined in common.js. The + * values are objects, which maps properties to expected values. So + * + * foo: { + * bar: "baz", + * quz: 7, + * }, + * + * will test that eval("foo.bar") === "baz" and eval("foo.quz") === 7. "foo" + * and "bar" could thus be expressions, like "document.documentElement" and + * "childNodes[4]" respectively. + * + * To avoid repetition, some values are automatically added based on others. + * For instance, if we specify nodeType: Node.TEXT_NODE, we'll automatically + * also test nodeName: "#text". This is handled by code after this variable is + * defined. + */ +var expected = { + testDiv: { + // Node + nodeType: Node.ELEMENT_NODE, + ownerDocument: document, + parentNode: document.body, + parentElement: document.body, + "childNodes.length": 6, + "childNodes[0]": paras[0], + "childNodes[1]": paras[1], + "childNodes[2]": paras[2], + "childNodes[3]": paras[3], + "childNodes[4]": paras[4], + "childNodes[5]": comment, + previousSibling: null, + nextSibling: document.getElementById("log"), + textContent: "A\u0308b\u0308c\u0308d\u0308e\u0308f\u0308g\u0308h\u0308\nIjklmnop\nQrstuvwxYzabcdefGhijklmn", + + // Element + namespaceURI: "http://www.w3.org/1999/xhtml", + prefix: null, + localName: "div", + tagName: "DIV", + id: "test", + "children[0]": paras[0], + "children[1]": paras[1], + "children[2]": paras[2], + "children[3]": paras[3], + "children[4]": paras[4], + previousElementSibling: null, + // nextSibling isn't explicitly set + //nextElementSibling: , + childElementCount: 5, + }, + detachedDiv: { + // Node + nodeType: Node.ELEMENT_NODE, + ownerDocument: document, + parentNode: null, + parentElement: null, + "childNodes.length": 2, + "childNodes[0]": detachedPara1, + "childNodes[1]": detachedPara2, + previousSibling: null, + nextSibling: null, + textContent: "OpqrstuvWxyzabcd", + + // Element + namespaceURI: "http://www.w3.org/1999/xhtml", + prefix: null, + localName: "div", + tagName: "DIV", + "children[0]": detachedPara1, + "children[1]": detachedPara2, + previousElementSibling: null, + nextElementSibling: null, + childElementCount: 2, + }, + detachedPara1: { + // Node + nodeType: Node.ELEMENT_NODE, + ownerDocument: document, + parentNode: detachedDiv, + parentElement: detachedDiv, + "childNodes.length": 1, + previousSibling: null, + nextSibling: detachedPara2, + textContent: "Opqrstuv", + + // Element + namespaceURI: "http://www.w3.org/1999/xhtml", + prefix: null, + localName: "p", + tagName: "P", + previousElementSibling: null, + nextElementSibling: detachedPara2, + childElementCount: 0, + }, + detachedPara2: { + // Node + nodeType: Node.ELEMENT_NODE, + ownerDocument: document, + parentNode: detachedDiv, + parentElement: detachedDiv, + "childNodes.length": 1, + previousSibling: detachedPara1, + nextSibling: null, + textContent: "Wxyzabcd", + + // Element + namespaceURI: "http://www.w3.org/1999/xhtml", + prefix: null, + localName: "p", + tagName: "P", + previousElementSibling: detachedPara1, + nextElementSibling: null, + childElementCount: 0, + }, + document: { + // Node + nodeType: Node.DOCUMENT_NODE, + "childNodes.length": 2, + "childNodes[0]": document.doctype, + "childNodes[1]": document.documentElement, + + // Document + URL: String(location), + compatMode: "CSS1Compat", + characterSet: "UTF-8", + contentType: "text/html", + doctype: doctype, + //documentElement: , + }, + foreignDoc: { + // Node + nodeType: Node.DOCUMENT_NODE, + "childNodes.length": 3, + "childNodes[0]": foreignDoc.doctype, + "childNodes[1]": foreignDoc.documentElement, + "childNodes[2]": foreignComment, + + // Document + URL: "about:blank", + compatMode: "CSS1Compat", + characterSet: "UTF-8", + contentType: "text/html", + //doctype: , + //documentElement: , + }, + foreignPara1: { + // Node + nodeType: Node.ELEMENT_NODE, + ownerDocument: foreignDoc, + parentNode: foreignDoc.body, + parentElement: foreignDoc.body, + "childNodes.length": 1, + previousSibling: null, + nextSibling: foreignPara2, + textContent: "Efghijkl", + + // Element + namespaceURI: "http://www.w3.org/1999/xhtml", + prefix: null, + localName: "p", + tagName: "P", + previousElementSibling: null, + nextElementSibling: foreignPara2, + childElementCount: 0, + }, + foreignPara2: { + // Node + nodeType: Node.ELEMENT_NODE, + ownerDocument: foreignDoc, + parentNode: foreignDoc.body, + parentElement: foreignDoc.body, + "childNodes.length": 1, + previousSibling: foreignPara1, + nextSibling: foreignTextNode, + textContent: "Mnopqrst", + + // Element + namespaceURI: "http://www.w3.org/1999/xhtml", + prefix: null, + localName: "p", + tagName: "P", + previousElementSibling: foreignPara1, + nextElementSibling: null, + childElementCount: 0, + }, + xmlDoc: { + // Node + nodeType: Node.DOCUMENT_NODE, + "childNodes.length": 4, + "childNodes[0]": xmlDoctype, + "childNodes[1]": xmlElement, + "childNodes[2]": processingInstruction, + "childNodes[3]": xmlComment, + + // Document + URL: "about:blank", + compatMode: "CSS1Compat", + characterSet: "UTF-8", + contentType: "application/xml", + //doctype: , + //documentElement: , + }, + xmlElement: { + // Node + nodeType: Node.ELEMENT_NODE, + ownerDocument: xmlDoc, + parentNode: xmlDoc, + parentElement: null, + "childNodes.length": 1, + "childNodes[0]": xmlTextNode, + previousSibling: xmlDoctype, + nextSibling: processingInstruction, + textContent: "do re mi fa so la ti", + + // Element + namespaceURI: null, + prefix: null, + localName: "igiveuponcreativenames", + tagName: "igiveuponcreativenames", + previousElementSibling: null, + nextElementSibling: null, + childElementCount: 0, + }, + detachedXmlElement: { + // Node + nodeType: Node.ELEMENT_NODE, + ownerDocument: xmlDoc, + parentNode: null, + parentElement: null, + "childNodes.length": 0, + previousSibling: null, + nextSibling: null, + textContent: "", + + // Element + namespaceURI: null, + prefix: null, + localName: "everyone-hates-hyphenated-element-names", + tagName: "everyone-hates-hyphenated-element-names", + previousElementSibling: null, + nextElementSibling: null, + childElementCount: 0, + }, + detachedTextNode: { + // Node + nodeType: Node.TEXT_NODE, + ownerDocument: document, + parentNode: null, + parentElement: null, + previousSibling: null, + nextSibling: null, + nodeValue: "Uvwxyzab", + + // Text + wholeText: "Uvwxyzab", + }, + foreignTextNode: { + // Node + nodeType: Node.TEXT_NODE, + ownerDocument: foreignDoc, + parentNode: foreignDoc.body, + parentElement: foreignDoc.body, + previousSibling: foreignPara2, + nextSibling: null, + nodeValue: "I admit that I harbor doubts about whether we really need so many things to test, but it's too late to stop now.", + + // Text + wholeText: "I admit that I harbor doubts about whether we really need so many things to test, but it's too late to stop now.", + }, + detachedForeignTextNode: { + // Node + nodeType: Node.TEXT_NODE, + ownerDocument: foreignDoc, + parentNode: null, + parentElement: null, + previousSibling: null, + nextSibling: null, + nodeValue: "Cdefghij", + + // Text + wholeText: "Cdefghij", + }, + xmlTextNode: { + // Node + nodeType: Node.TEXT_NODE, + ownerDocument: xmlDoc, + parentNode: xmlElement, + parentElement: xmlElement, + previousSibling: null, + nextSibling: null, + nodeValue: "do re mi fa so la ti", + + // Text + wholeText: "do re mi fa so la ti", + }, + detachedXmlTextNode: { + // Node + nodeType: Node.TEXT_NODE, + ownerDocument: xmlDoc, + parentNode: null, + parentElement: null, + previousSibling: null, + nextSibling: null, + nodeValue: "Klmnopqr", + + // Text + wholeText: "Klmnopqr", + }, + processingInstruction: { + // Node + nodeType: Node.PROCESSING_INSTRUCTION_NODE, + ownerDocument: xmlDoc, + parentNode: xmlDoc, + parentElement: null, + previousSibling: xmlElement, + nextSibling: xmlComment, + nodeValue: 'Did you know that ":syn sync fromstart" is very useful when using vim to edit large amounts of JavaScript embedded in HTML?', + + // ProcessingInstruction + target: "somePI", + }, + detachedProcessingInstruction: { + // Node + nodeType: Node.PROCESSING_INSTRUCTION_NODE, + ownerDocument: xmlDoc, + parentNode: null, + parentElement: null, + previousSibling: null, + nextSibling: null, + nodeValue: "chirp chirp chirp", + + // ProcessingInstruction + target: "whippoorwill", + }, + comment: { + // Node + nodeType: Node.COMMENT_NODE, + ownerDocument: document, + parentNode: testDiv, + parentElement: testDiv, + previousSibling: paras[4], + nextSibling: null, + nodeValue: "Alphabet soup?", + }, + detachedComment: { + // Node + nodeType: Node.COMMENT_NODE, + ownerDocument: document, + parentNode: null, + parentElement: null, + previousSibling: null, + nextSibling: null, + nodeValue: "Stuvwxyz", + }, + foreignComment: { + // Node + nodeType: Node.COMMENT_NODE, + ownerDocument: foreignDoc, + parentNode: foreignDoc, + parentElement: null, + previousSibling: foreignDoc.documentElement, + nextSibling: null, + nodeValue: '"Commenter" and "commentator" mean different things. I\'ve seen non-native speakers trip up on this.', + }, + detachedForeignComment: { + // Node + nodeType: Node.COMMENT_NODE, + ownerDocument: foreignDoc, + parentNode: null, + parentElement: null, + previousSibling: null, + nextSibling: null, + nodeValue: "אריה יהודה", + }, + xmlComment: { + // Node + nodeType: Node.COMMENT_NODE, + ownerDocument: xmlDoc, + parentNode: xmlDoc, + parentElement: null, + previousSibling: processingInstruction, + nextSibling: null, + nodeValue: "I maliciously created a comment that will break incautious XML serializers, but Firefox threw an exception, so all I got was this lousy T-shirt", + }, + detachedXmlComment: { + // Node + nodeType: Node.COMMENT_NODE, + ownerDocument: xmlDoc, + parentNode: null, + parentElement: null, + previousSibling: null, + nextSibling: null, + nodeValue: "בן חיים אליעזר", + }, + docfrag: { + // Node + nodeType: Node.DOCUMENT_FRAGMENT_NODE, + ownerDocument: document, + "childNodes.length": 0, + textContent: "", + }, + foreignDocfrag: { + // Node + nodeType: Node.DOCUMENT_FRAGMENT_NODE, + ownerDocument: foreignDoc, + "childNodes.length": 0, + textContent: "", + }, + xmlDocfrag: { + // Node + nodeType: Node.DOCUMENT_FRAGMENT_NODE, + ownerDocument: xmlDoc, + "childNodes.length": 0, + textContent: "", + }, + doctype: { + // Node + nodeType: Node.DOCUMENT_TYPE_NODE, + ownerDocument: document, + parentNode: document, + previousSibling: null, + nextSibling: document.documentElement, + + // DocumentType + name: "html", + publicId: "", + systemId: "", + }, + foreignDoctype: { + // Node + nodeType: Node.DOCUMENT_TYPE_NODE, + ownerDocument: foreignDoc, + parentNode: foreignDoc, + previousSibling: null, + nextSibling: foreignDoc.documentElement, + + // DocumentType + name: "html", + publicId: "", + systemId: "", + }, + xmlDoctype: { + // Node + nodeType: Node.DOCUMENT_TYPE_NODE, + ownerDocument: xmlDoc, + parentNode: xmlDoc, + previousSibling: null, + nextSibling: xmlElement, + + // DocumentType + name: "qorflesnorf", + publicId: "abcde", + systemId: "x\"'y", + }, + "paras[0]": { + // Node + nodeType: Node.ELEMENT_NODE, + ownerDocument: document, + parentNode: testDiv, + parentElement: testDiv, + "childNodes.length": 1, + previousSibling: null, + nextSibling: paras[1], + textContent: "A\u0308b\u0308c\u0308d\u0308e\u0308f\u0308g\u0308h\u0308\n", + + // Element + namespaceURI: "http://www.w3.org/1999/xhtml", + prefix: null, + localName: "p", + tagName: "P", + id: "a", + previousElementSibling: null, + nextElementSibling: paras[1], + childElementCount: 0, + }, + "paras[1]": { + // Node + nodeType: Node.ELEMENT_NODE, + ownerDocument: document, + parentNode: testDiv, + parentElement: testDiv, + "childNodes.length": 1, + previousSibling: paras[0], + nextSibling: paras[2], + textContent: "Ijklmnop\n", + + // Element + namespaceURI: "http://www.w3.org/1999/xhtml", + prefix: null, + localName: "p", + tagName: "P", + id: "b", + previousElementSibling: paras[0], + nextElementSibling: paras[2], + childElementCount: 0, + }, + "paras[2]": { + // Node + nodeType: Node.ELEMENT_NODE, + ownerDocument: document, + parentNode: testDiv, + parentElement: testDiv, + "childNodes.length": 1, + previousSibling: paras[1], + nextSibling: paras[3], + textContent: "Qrstuvwx", + + // Element + namespaceURI: "http://www.w3.org/1999/xhtml", + prefix: null, + localName: "p", + tagName: "P", + id: "c", + previousElementSibling: paras[1], + nextElementSibling: paras[3], + childElementCount: 0, + }, + "paras[3]": { + // Node + nodeType: Node.ELEMENT_NODE, + ownerDocument: document, + parentNode: testDiv, + parentElement: testDiv, + "childNodes.length": 1, + previousSibling: paras[2], + nextSibling: paras[4], + textContent: "Yzabcdef", + + // Element + namespaceURI: "http://www.w3.org/1999/xhtml", + prefix: null, + localName: "p", + tagName: "P", + id: "d", + previousElementSibling: paras[2], + nextElementSibling: paras[4], + childElementCount: 0, + }, + "paras[4]": { + // Node + nodeType: Node.ELEMENT_NODE, + ownerDocument: document, + parentNode: testDiv, + parentElement: testDiv, + "childNodes.length": 1, + previousSibling: paras[3], + nextSibling: comment, + textContent: "Ghijklmn", + + // Element + namespaceURI: "http://www.w3.org/1999/xhtml", + prefix: null, + localName: "p", + tagName: "P", + id: "e", + previousElementSibling: paras[3], + nextElementSibling: null, + childElementCount: 0, + }, +}; + +for (var node in expected) { + // Now we set various default values by node type. + switch (expected[node].nodeType) { + case Node.ELEMENT_NODE: + expected[node].nodeName = expected[node].tagName; + expected[node].nodeValue = null; + expected[node]["children.length"] = expected[node].childElementCount; + + if (expected[node].id === undefined) { + expected[node].id = ""; + } + if (expected[node].className === undefined) { + expected[node].className = ""; + } + + var len = expected[node].childElementCount; + if (len === 0) { + expected[node].firstElementChild = + expected[node].lastElementChild = null; + } else { + // If we have expectations for the first/last child in children, + // use those. Otherwise, at least check that .firstElementChild == + // .children[0] and .lastElementChild == .children[len - 1], even + // if we aren't sure what they should be. + expected[node].firstElementChild = expected[node]["children[0]"] + ? expected[node]["children[0]"] + : eval(node).children[0]; + expected[node].lastElementChild = + expected[node]["children[" + (len - 1) + "]"] + ? expected[node]["children[" + (len - 1) + "]"] + : eval(node).children[len - 1]; + } + break; + + case Node.TEXT_NODE: + expected[node].nodeName = "#text"; + expected[node]["childNodes.length"] = 0; + expected[node].textContent = expected[node].data = + expected[node].nodeValue; + expected[node].length = expected[node].nodeValue.length; + break; + + case Node.PROCESSING_INSTRUCTION_NODE: + expected[node].nodeName = expected[node].target; + expected[node]["childNodes.length"] = 0; + expected[node].textContent = expected[node].data = + expected[node].nodeValue; + expected[node].length = expected[node].nodeValue.length; + break; + + case Node.COMMENT_NODE: + expected[node].nodeName = "#comment"; + expected[node]["childNodes.length"] = 0; + expected[node].textContent = expected[node].data = + expected[node].nodeValue; + expected[node].length = expected[node].nodeValue.length; + break; + + case Node.DOCUMENT_NODE: + expected[node].nodeName = "#document"; + expected[node].ownerDocument = expected[node].parentNode = + expected[node].parentElement = expected[node].previousSibling = + expected[node].nextSibling = expected[node].nodeValue = + expected[node].textContent = null; + expected[node].documentURI = expected[node].URL; + expected[node].charset = expected[node].inputEncoding = + expected[node].characterSet; + break; + + case Node.DOCUMENT_TYPE_NODE: + expected[node].nodeName = expected[node].name; + expected[node]["childNodes.length"] = 0; + expected[node].parentElement = expected[node].nodeValue = + expected[node].textContent = null; + break; + + case Node.DOCUMENT_FRAGMENT_NODE: + expected[node].nodeName = "#document-fragment"; + expected[node].parentNode = expected[node].parentElement = + expected[node].previousSibling = expected[node].nextSibling = + expected[node].nodeValue = null; + break; + } + + // Now we set some further default values that are independent of node + // type. + var len = expected[node]["childNodes.length"]; + if (len === 0) { + expected[node].firstChild = expected[node].lastChild = null; + } else { + // If we have expectations for the first/last child in childNodes, use + // those. Otherwise, at least check that .firstChild == .childNodes[0] + // and .lastChild == .childNodes[len - 1], even if we aren't sure what + // they should be. + expected[node].firstChild = expected[node]["childNodes[0]"] + ? expected[node]["childNodes[0]"] + : eval(node).childNodes[0]; + expected[node].lastChild = + expected[node]["childNodes[" + (len - 1) + "]"] + ? expected[node]["childNodes[" + (len - 1) + "]"] + : eval(node).childNodes[len - 1]; + } + expected[node]["hasChildNodes()"] = !!expected[node]["childNodes.length"]; + + // Finally, we test! + for (var prop in expected[node]) { + test(function() { + assert_equals(eval(node + "." + prop), expected[node][prop]); + }, node + "." + prop); + } +} + +testDiv.parentNode.removeChild(testDiv); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Node-removeChild.html b/testing/web-platform/tests/dom/nodes/Node-removeChild.html new file mode 100644 index 000000000..fb2258322 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-removeChild.html @@ -0,0 +1,54 @@ +<!DOCTYPE html> +<title>Node.removeChild</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="creators.js"></script> +<div id="log"></div> +<iframe src=about:blank></iframe> +<script> +var documents = [ + [function() { return document }, "the main document"], + [function() { return frames[0].document }, "a frame document"], + [function() { return document.implementation.createHTMLDocument() }, + "a synthetic document"], +]; + +documents.forEach(function(d) { + var get = d[0], description = d[1] + for (var p in creators) { + var creator = creators[p]; + test(function() { + var doc = get(); + var s = doc[creator]("a") + assert_equals(s.ownerDocument, doc) + assert_throws("NOT_FOUND_ERR", function() { document.body.removeChild(s) }) + assert_equals(s.ownerDocument, doc) + }, "Passing a detached " + p + " from " + description + + " to removeChild should not affect it.") + + test(function() { + var doc = get(); + var s = doc[creator]("b") + doc.documentElement.appendChild(s) + assert_equals(s.ownerDocument, doc) + assert_throws("NOT_FOUND_ERR", function() { document.body.removeChild(s) }) + assert_equals(s.ownerDocument, doc) + }, "Passing a non-detached " + p + " from " + description + + " to removeChild should not affect it.") + + test(function() { + var doc = get(); + var s = doc[creator]("test") + doc.body.appendChild(s) + assert_equals(s.ownerDocument, doc) + assert_throws("NOT_FOUND_ERR", function() { s.removeChild(doc) }) + }, "Calling removeChild on a " + p + " from " + description + + " with no children should throw NOT_FOUND_ERR.") + } +}); + +test(function() { + assert_throws(new TypeError(), function() { document.body.removeChild(null) }) + assert_throws(new TypeError(), function() { document.body.removeChild({'a':'b'}) }) +}, "Passing a value that is not a Node reference to removeChild should throw TypeError.") +</script> diff --git a/testing/web-platform/tests/dom/nodes/Node-replaceChild.html b/testing/web-platform/tests/dom/nodes/Node-replaceChild.html new file mode 100644 index 000000000..e8ba496cd --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-replaceChild.html @@ -0,0 +1,345 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Node.replaceChild</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body><a><b></b><c></c></a> +<div id="log"></div> +<script> +// IDL. +test(function() { + var a = document.createElement("div"); + assert_throws(new TypeError(), function() { + a.replaceChild(null, null); + }); + + var b = document.createElement("div"); + assert_throws(new TypeError(), function() { + a.replaceChild(b, null); + }); + assert_throws(new TypeError(), function() { + a.replaceChild(null, b); + }); +}, "Passing null to replaceChild should throw a TypeError.") + +// Step 1. +test(function() { + var a = document.createElement("div"); + var b = document.createElement("div"); + var c = document.createElement("div"); + assert_throws("NotFoundError", function() { + a.replaceChild(b, c); + }); + + var d = document.createElement("div"); + d.appendChild(b); + assert_throws("NotFoundError", function() { + a.replaceChild(b, c); + }); + assert_throws("NotFoundError", function() { + a.replaceChild(b, a); + }); +}, "If child's parent is not the context node, a NotFoundError exception should be thrown") +test(function() { + var nodes = [ + document.implementation.createDocumentType("html", "", ""), + document.createTextNode("text"), + document.implementation.createDocument(null, "foo", null).createProcessingInstruction("foo", "bar"), + document.createComment("comment") + ]; + + var a = document.createElement("div"); + var b = document.createElement("div"); + nodes.forEach(function(node) { + assert_throws("HierarchyRequestError", function() { + node.replaceChild(a, b); + }); + }); +}, "If the context node is not a node that can contain children, a NotFoundError exception should be thrown") + +// Step 2. +test(function() { + var a = document.createElement("div"); + var b = document.createElement("div"); + + assert_throws("HierarchyRequestError", function() { + a.replaceChild(a, a); + }); + + a.appendChild(b); + assert_throws("HierarchyRequestError", function() { + a.replaceChild(a, b); + }); + + var c = document.createElement("div"); + c.appendChild(a); + assert_throws("HierarchyRequestError", function() { + a.replaceChild(c, b); + }); +}, "If node is an inclusive ancestor of the context node, a HierarchyRequestError should be thrown.") + +// Step 3.1. +test(function() { + var doc = document.implementation.createHTMLDocument("title"); + var doc2 = document.implementation.createHTMLDocument("title2"); + assert_throws("HierarchyRequestError", function() { + doc.replaceChild(doc2, doc.documentElement); + }); + + assert_throws("HierarchyRequestError", function() { + doc.replaceChild(doc.createTextNode("text"), doc.documentElement); + }); +}, "If the context node is a document, inserting a document or text node should throw a HierarchyRequestError.") + +// Step 3.2.1. +test(function() { + var doc = document.implementation.createHTMLDocument("title"); + + var df = doc.createDocumentFragment(); + df.appendChild(doc.createElement("a")); + df.appendChild(doc.createElement("b")); + assert_throws("HierarchyRequestError", function() { + doc.replaceChild(df, doc.documentElement); + }); + + df = doc.createDocumentFragment(); + df.appendChild(doc.createTextNode("text")); + assert_throws("HierarchyRequestError", function() { + doc.replaceChild(df, doc.documentElement); + }); + + df = doc.createDocumentFragment(); + df.appendChild(doc.createComment("comment")); + df.appendChild(doc.createTextNode("text")); + assert_throws("HierarchyRequestError", function() { + doc.replaceChild(df, doc.documentElement); + }); +}, "If the context node is a document, inserting a DocumentFragment that contains a text node or too many elements should throw a HierarchyRequestError.") +test(function() { + var doc = document.implementation.createHTMLDocument("title"); + doc.removeChild(doc.documentElement); + + var df = doc.createDocumentFragment(); + df.appendChild(doc.createElement("a")); + df.appendChild(doc.createElement("b")); + assert_throws("HierarchyRequestError", function() { + doc.replaceChild(df, doc.doctype); + }); +}, "If the context node is a document (without element children), inserting a DocumentFragment that contains multiple elements should throw a HierarchyRequestError.") + +// Step 3.2.2. +test(function() { + // The context node has an element child that is not /child/. + var doc = document.implementation.createHTMLDocument("title"); + var comment = doc.appendChild(doc.createComment("foo")); + assert_array_equals(doc.childNodes, [doc.doctype, doc.documentElement, comment]); + + var df = doc.createDocumentFragment(); + df.appendChild(doc.createElement("a")); + assert_throws("HierarchyRequestError", function() { + doc.replaceChild(df, comment); + }); + assert_throws("HierarchyRequestError", function() { + doc.replaceChild(df, doc.doctype); + }); +}, "If the context node is a document, inserting a DocumentFragment with an element if there already is an element child should throw a HierarchyRequestError.") +test(function() { + // A doctype is following /child/. + var doc = document.implementation.createHTMLDocument("title"); + var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild); + doc.removeChild(doc.documentElement); + assert_array_equals(doc.childNodes, [comment, doc.doctype]); + + var df = doc.createDocumentFragment(); + df.appendChild(doc.createElement("a")); + assert_throws("HierarchyRequestError", function() { + doc.replaceChild(df, comment); + }); +}, "If the context node is a document, inserting a DocumentFragment with an element before the doctype should throw a HierarchyRequestError.") + +// Step 3.3. +test(function() { + var doc = document.implementation.createHTMLDocument("title"); + var comment = doc.appendChild(doc.createComment("foo")); + assert_array_equals(doc.childNodes, [doc.doctype, doc.documentElement, comment]); + + var a = doc.createElement("a"); + assert_throws("HierarchyRequestError", function() { + doc.replaceChild(a, comment); + }); + assert_throws("HierarchyRequestError", function() { + doc.replaceChild(a, doc.doctype); + }); +}, "If the context node is a document, inserting an element if there already is an element child should throw a HierarchyRequestError.") +test(function() { + var doc = document.implementation.createHTMLDocument("title"); + var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild); + doc.removeChild(doc.documentElement); + assert_array_equals(doc.childNodes, [comment, doc.doctype]); + + var a = doc.createElement("a"); + assert_throws("HierarchyRequestError", function() { + doc.replaceChild(a, comment); + }); +}, "If the context node is a document, inserting an element before the doctype should throw a HierarchyRequestError.") + +// Step 3.4. +test(function() { + var doc = document.implementation.createHTMLDocument("title"); + var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild); + assert_array_equals(doc.childNodes, [comment, doc.doctype, doc.documentElement]); + + var doctype = document.implementation.createDocumentType("html", "", ""); + assert_throws("HierarchyRequestError", function() { + doc.replaceChild(doctype, comment); + }); + assert_throws("HierarchyRequestError", function() { + doc.replaceChild(doctype, doc.documentElement); + }); +}, "If the context node is a document, inserting a doctype if there already is a doctype child should throw a HierarchyRequestError.") +test(function() { + var doc = document.implementation.createHTMLDocument("title"); + var comment = doc.appendChild(doc.createComment("foo")); + doc.removeChild(doc.doctype); + assert_array_equals(doc.childNodes, [doc.documentElement, comment]); + + var doctype = document.implementation.createDocumentType("html", "", ""); + assert_throws("HierarchyRequestError", function() { + doc.replaceChild(doctype, comment); + }); +}, "If the context node is a document, inserting a doctype after the document element should throw a HierarchyRequestError.") + +// Step 4. +test(function() { + var df = document.createDocumentFragment(); + var a = df.appendChild(document.createElement("a")); + + var doc = document.implementation.createHTMLDocument("title"); + assert_throws("HierarchyRequestError", function() { + df.replaceChild(doc, a); + }); + + var doctype = document.implementation.createDocumentType("html", "", ""); + assert_throws("HierarchyRequestError", function() { + df.replaceChild(doctype, a); + }); +}, "If the context node is a DocumentFragment, inserting a document or a doctype should throw a HierarchyRequestError.") +test(function() { + var el = document.createElement("div"); + var a = el.appendChild(document.createElement("a")); + + var doc = document.implementation.createHTMLDocument("title"); + assert_throws("HierarchyRequestError", function() { + el.replaceChild(doc, a); + }); + + var doctype = document.implementation.createDocumentType("html", "", ""); + assert_throws("HierarchyRequestError", function() { + el.replaceChild(doctype, a); + }); +}, "If the context node is an element, inserting a document or a doctype should throw a HierarchyRequestError.") + +// Step 6. +test(function() { + var a = document.createElement("div"); + var b = document.createElement("div"); + var c = document.createElement("div"); + a.appendChild(b); + a.appendChild(c); + assert_array_equals(a.childNodes, [b, c]); + assert_equals(a.replaceChild(c, b), b); + assert_array_equals(a.childNodes, [c]); +}, "Replacing a node with its next sibling should work (2 children)"); +test(function() { + var a = document.createElement("div"); + var b = document.createElement("div"); + var c = document.createElement("div"); + var d = document.createElement("div"); + var e = document.createElement("div"); + a.appendChild(b); + a.appendChild(c); + a.appendChild(d); + a.appendChild(e); + assert_array_equals(a.childNodes, [b, c, d, e]); + assert_equals(a.replaceChild(d, c), c); + assert_array_equals(a.childNodes, [b, d, e]); +}, "Replacing a node with its next sibling should work (4 children)"); +test(function() { + var a = document.createElement("div"); + var b = document.createElement("div"); + var c = document.createElement("div"); + a.appendChild(b); + a.appendChild(c); + assert_array_equals(a.childNodes, [b, c]); + assert_equals(a.replaceChild(b, b), b); + assert_array_equals(a.childNodes, [b, c]); + assert_equals(a.replaceChild(c, c), c); + assert_array_equals(a.childNodes, [b, c]); +}, "Replacing a node with itself should not move the node"); + +// Step 7. +test(function() { + var doc = document.implementation.createHTMLDocument("title"); + var doctype = doc.doctype; + assert_array_equals(doc.childNodes, [doctype, doc.documentElement]); + + var doc2 = document.implementation.createHTMLDocument("title2"); + var doctype2 = doc2.doctype; + assert_array_equals(doc2.childNodes, [doctype2, doc2.documentElement]); + + doc.replaceChild(doc2.doctype, doc.doctype); + assert_array_equals(doc.childNodes, [doctype2, doc.documentElement]); + assert_array_equals(doc2.childNodes, [doc2.documentElement]); + assert_equals(doctype.parentNode, null); + assert_equals(doctype.ownerDocument, doc); + assert_equals(doctype2.parentNode, doc); + assert_equals(doctype2.ownerDocument, doc); +}, "If the context node is a document, inserting a new doctype should work.") + +// Bugs. +test(function() { + var doc = document.implementation.createHTMLDocument("title"); + var df = doc.createDocumentFragment(); + var a = df.appendChild(doc.createElement("a")); + assert_equals(doc.documentElement, doc.replaceChild(df, doc.documentElement)); + assert_array_equals(doc.childNodes, [doc.doctype, a]); +}, "Replacing the document element with a DocumentFragment containing a single element should work."); +test(function() { + var doc = document.implementation.createHTMLDocument("title"); + var df = doc.createDocumentFragment(); + var a = df.appendChild(doc.createComment("a")); + var b = df.appendChild(doc.createElement("b")); + var c = df.appendChild(doc.createComment("c")); + assert_equals(doc.documentElement, doc.replaceChild(df, doc.documentElement)); + assert_array_equals(doc.childNodes, [doc.doctype, a, b, c]); +}, "Replacing the document element with a DocumentFragment containing a single element and comments should work."); +test(function() { + var doc = document.implementation.createHTMLDocument("title"); + var a = doc.createElement("a"); + assert_equals(doc.documentElement, doc.replaceChild(a, doc.documentElement)); + assert_array_equals(doc.childNodes, [doc.doctype, a]); +}, "Replacing the document element with a single element should work."); +test(function() { + document.addEventListener("DOMNodeRemoved", function(e) { + document.body.appendChild(document.createElement("x")); + }, false); + var a = document.body.firstChild, b = a.firstChild, c = b.nextSibling; + assert_equals(a.replaceChild(c, b), b); + assert_equals(b.parentNode, null); + assert_equals(a.firstChild, c); + assert_equals(c.parentNode, a); +}, "replaceChild should work in the presence of mutation events.") +test(function() { + var TEST_ID = "findme"; + var gBody = document.getElementsByTagName("body")[0]; + var parent = document.createElement("div"); + gBody.appendChild(parent); + var child = document.createElement("div"); + parent.appendChild(child); + var df = document.createDocumentFragment(); + var fragChild = df.appendChild(document.createElement("div")); + fragChild.setAttribute("id", TEST_ID); + parent.replaceChild(df, child); + assert_equals(document.getElementById(TEST_ID), fragChild, "should not be null"); +}, "Replacing an element with a DocumentFragment should allow a child of the DocumentFragment to be found by Id.") +</script> diff --git a/testing/web-platform/tests/dom/nodes/Node-textContent.html b/testing/web-platform/tests/dom/nodes/Node-textContent.html new file mode 100644 index 000000000..9378dec80 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Node-textContent.html @@ -0,0 +1,265 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Node.textContent</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +// XXX mutation observers? +// XXX Range gravitation? + +var documents, doctypes; +setup(function() { + documents = [ + [document, "parser"], + [document.implementation.createDocument("", "test", null), "createDocument"], + [document.implementation.createHTMLDocument("title"), "createHTMLDocument"], + ] + doctypes = [ + [document.doctype, "parser"], + [document.implementation.createDocumentType("x", "", ""), "script"], + ] +}) + +// Getting +// DocumentFragment, Element: +test(function() { + var element = document.createElement("div") + assert_equals(element.textContent, "") +}, "For an empty Element, textContent should be the empty string") + +test(function() { + assert_equals(document.createDocumentFragment().textContent, "") +}, "For an empty DocumentFragment, textContent should be the empty string") + +test(function() { + var el = document.createElement("div") + el.appendChild(document.createComment(" abc ")) + el.appendChild(document.createTextNode("\tDEF\t")) + el.appendChild(document.createProcessingInstruction("x", " ghi ")) + assert_equals(el.textContent, "\tDEF\t") +}, "Element with children") + +test(function() { + var el = document.createElement("div") + var child = document.createElement("div") + el.appendChild(child) + child.appendChild(document.createComment(" abc ")) + child.appendChild(document.createTextNode("\tDEF\t")) + child.appendChild(document.createProcessingInstruction("x", " ghi ")) + assert_equals(el.textContent, "\tDEF\t") +}, "Element with descendants") + +test(function() { + var df = document.createDocumentFragment() + df.appendChild(document.createComment(" abc ")) + df.appendChild(document.createTextNode("\tDEF\t")) + df.appendChild(document.createProcessingInstruction("x", " ghi ")) + assert_equals(df.textContent, "\tDEF\t") +}, "DocumentFragment with children") + +test(function() { + var df = document.createDocumentFragment() + var child = document.createElement("div") + df.appendChild(child) + child.appendChild(document.createComment(" abc ")) + child.appendChild(document.createTextNode("\tDEF\t")) + child.appendChild(document.createProcessingInstruction("x", " ghi ")) + assert_equals(df.textContent, "\tDEF\t") +}, "DocumentFragment with descendants") + +// Text, ProcessingInstruction, Comment: +test(function() { + assert_equals(document.createTextNode("").textContent, "") +}, "For an empty Text, textContent should be the empty string") + +test(function() { + assert_equals(document.createProcessingInstruction("x", "").textContent, "") +}, "For an empty ProcessingInstruction, textContent should be the empty string") + +test(function() { + assert_equals(document.createComment("").textContent, "") +}, "For an empty Comment, textContent should be the empty string") + +test(function() { + assert_equals(document.createTextNode("abc").textContent, "abc") +}, "For a Text with data, textContent should be that data") + +test(function() { + assert_equals(document.createProcessingInstruction("x", "abc").textContent, + "abc") +}, "For a ProcessingInstruction with data, textContent should be that data") + +test(function() { + assert_equals(document.createComment("abc").textContent, "abc") +}, "For a Comment with data, textContent should be that data") + +// Any other node: +documents.forEach(function(argument) { + var doc = argument[0], creator = argument[1] + test(function() { + assert_equals(doc.textContent, null) + }, "For Documents created by " + creator + ", textContent should be null") +}) + +doctypes.forEach(function(argument) { + var doctype = argument[0], creator = argument[1] + test(function() { + assert_equals(doctype.textContent, null) + }, "For DocumentType created by " + creator + ", textContent should be null") +}) + +// Setting +// DocumentFragment, Element: +var arguments = [ + [null, null], + [undefined, null], + ["", null], + [42, "42"], + ["abc", "abc"], + ["<b>xyz<\/b>", "<b>xyz<\/b>"], + ["d\0e", "d\0e"] + // XXX unpaired surrogate? +] +arguments.forEach(function(aValue) { + var argument = aValue[0], expectation = aValue[1] + var check = function(aElementOrDocumentFragment) { + if (expectation === null) { + assert_equals(aElementOrDocumentFragment.textContent, "") + assert_equals(aElementOrDocumentFragment.firstChild, null) + } else { + assert_equals(aElementOrDocumentFragment.textContent, expectation) + assert_equals(aElementOrDocumentFragment.childNodes.length, 1, + "Should have one child") + var firstChild = aElementOrDocumentFragment.firstChild + assert_true(firstChild instanceof Text, "child should be a Text") + assert_equals(firstChild.data, expectation) + } + } + + test(function() { + var el = document.createElement("div") + el.textContent = argument + check(el) + }, "Element without children set to " + format_value(argument)) + + test(function() { + var el = document.createElement("div") + var text = el.appendChild(document.createTextNode("")) + el.textContent = argument + check(el) + assert_equals(text.parentNode, null, + "Preexisting Text should have been removed") + }, "Element with empty text node as child set to " + format_value(argument)) + + test(function() { + var el = document.createElement("div") + el.appendChild(document.createComment(" abc ")) + el.appendChild(document.createTextNode("\tDEF\t")) + el.appendChild(document.createProcessingInstruction("x", " ghi ")) + el.textContent = argument + check(el) + }, "Element with children set to " + format_value(argument)) + + test(function() { + var el = document.createElement("div") + var child = document.createElement("div") + el.appendChild(child) + child.appendChild(document.createComment(" abc ")) + child.appendChild(document.createTextNode("\tDEF\t")) + child.appendChild(document.createProcessingInstruction("x", " ghi ")) + el.textContent = argument + check(el) + assert_equals(child.childNodes.length, 3, + "Should not have changed the internal structure of the removed nodes.") + }, "Element with descendants set to " + format_value(argument)) + + test(function() { + var df = document.createDocumentFragment() + df.textContent = argument + check(df) + }, "DocumentFragment without children set to " + format_value(argument)) + + test(function() { + var df = document.createDocumentFragment() + var text = df.appendChild(document.createTextNode("")) + df.textContent = argument + check(df) + assert_equals(text.parentNode, null, + "Preexisting Text should have been removed") + }, "DocumentFragment with empty text node as child set to " + format_value(argument)) + + test(function() { + var df = document.createDocumentFragment() + df.appendChild(document.createComment(" abc ")) + df.appendChild(document.createTextNode("\tDEF\t")) + df.appendChild(document.createProcessingInstruction("x", " ghi ")) + df.textContent = argument + check(df) + }, "DocumentFragment with children set to " + format_value(argument)) + + test(function() { + var df = document.createDocumentFragment() + var child = document.createElement("div") + df.appendChild(child) + child.appendChild(document.createComment(" abc ")) + child.appendChild(document.createTextNode("\tDEF\t")) + child.appendChild(document.createProcessingInstruction("x", " ghi ")) + df.textContent = argument + check(df) + assert_equals(child.childNodes.length, 3, + "Should not have changed the internal structure of the removed nodes.") + }, "DocumentFragment with descendants set to " + format_value(argument)) +}) + +// Text, ProcessingInstruction, Comment: +test(function() { + var text = document.createTextNode("abc") + text.textContent = "def" + assert_equals(text.textContent, "def") + assert_equals(text.data, "def") +}, "For a Text, textContent should set the data") + +test(function() { + var pi = document.createProcessingInstruction("x", "abc") + pi.textContent = "def" + assert_equals(pi.textContent, "def") + assert_equals(pi.data, "def") + assert_equals(pi.target, "x") +}, "For a ProcessingInstruction, textContent should set the data") + +test(function() { + var comment = document.createComment("abc") + comment.textContent = "def" + assert_equals(comment.textContent, "def") + assert_equals(comment.data, "def") +}, "For a Comment, textContent should set the data") + +// Any other node: +documents.forEach(function(argument) { + var doc = argument[0], creator = argument[1] + test(function() { + var root = doc.documentElement + doc.textContent = "a" + assert_equals(doc.textContent, null) + assert_equals(doc.documentElement, root) + }, "For Documents created by " + creator + ", setting textContent should do nothing") +}) + +doctypes.forEach(function(argument) { + var doctype = argument[0], creator = argument[1] + test(function() { + var props = { + name: doctype.name, + publicId: doctype.publicId, + systemId: doctype.systemId, + } + doctype.textContent = "b" + assert_equals(doctype.textContent, null) + assert_equals(doctype.name, props.name, "name should not change") + assert_equals(doctype.publicId, props.publicId, "publicId should not change") + assert_equals(doctype.systemId, props.systemId, "systemId should not change") + }, "For DocumentType created by " + creator + ", setting textContent should do nothing") +}) + +</script> diff --git a/testing/web-platform/tests/dom/nodes/NodeList-Iterable.html b/testing/web-platform/tests/dom/nodes/NodeList-Iterable.html new file mode 100644 index 000000000..e1349cd76 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/NodeList-Iterable.html @@ -0,0 +1,37 @@ +<!doctype html> +<meta charset="utf-8"> +<title>NodeList Iterable Test</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + <p id="1"></p> + <p id="2"></p> + <p id="3"></p> + <p id="4"></p> + <p id="5"></p> +<script> + var paragraphs; + setup(function() { + paragraphs = document.querySelectorAll('p'); + }) + test(function() { + assert_true('length' in paragraphs); + }, 'NodeList has length method.'); + test(function() { + assert_true('values' in paragraphs); + }, 'NodeList has values method.'); + test(function() { + assert_true('entries' in paragraphs); + }, 'NodeList has entries method.'); + test(function() { + assert_true('forEach' in paragraphs); + }, 'NodeList has forEach method.'); + test(function() { + assert_true(Symbol.iterator in paragraphs); + }, 'NodeList has Symbol.iterator.'); + test(function() { + var ids = "12345", idx=0; + for(var node of paragraphs){ + assert_equals(node.getAttribute('id'), ids[idx++]); + } + }, 'NodeList is iterable via for-of loop.'); +</script> diff --git a/testing/web-platform/tests/dom/nodes/ParentNode-append.html b/testing/web-platform/tests/dom/nodes/ParentNode-append.html new file mode 100644 index 000000000..dcc398f3f --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/ParentNode-append.html @@ -0,0 +1,66 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>ParentNode.append</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-parentnode-append"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + +function test_append(node, nodeName) { + + test(function() { + var parent = node.cloneNode(); + parent.append(); + assert_array_equals(parent.childNodes, []); + }, nodeName + '.append() without any argument, on a parent having no child.'); + + test(function() { + var parent = node.cloneNode(); + parent.append(null); + assert_equals(parent.childNodes[0].textContent, 'null'); + }, nodeName + '.append() with null as an argument, on a parent having no child.'); + + test(function() { + var parent = node.cloneNode(); + parent.append(undefined); + assert_equals(parent.childNodes[0].textContent, 'undefined'); + }, nodeName + '.append() with undefined as an argument, on a parent having no child.'); + + test(function() { + var parent = node.cloneNode(); + parent.append('text'); + assert_equals(parent.childNodes[0].textContent, 'text'); + }, nodeName + '.append() with only text as an argument, on a parent having no child.'); + + test(function() { + var parent = node.cloneNode(); + var x = document.createElement('x'); + parent.append(x); + assert_array_equals(parent.childNodes, [x]); + }, nodeName + '.append() with only one element as an argument, on a parent having no child.'); + + test(function() { + var parent = node.cloneNode(); + var child = document.createElement('test'); + parent.appendChild(child); + parent.append(null); + assert_equals(parent.childNodes[0], child); + assert_equals(parent.childNodes[1].textContent, 'null'); + }, nodeName + '.append() with null as an argument, on a parent having a child.'); + + test(function() { + var parent = node.cloneNode(); + var x = document.createElement('x'); + var child = document.createElement('test'); + parent.appendChild(child); + parent.append(x, 'text'); + assert_equals(parent.childNodes[0], child); + assert_equals(parent.childNodes[1], x); + assert_equals(parent.childNodes[2].textContent, 'text'); + }, nodeName + '.append() with one element and text as argument, on a parent having a child.'); +} + +test_append(document.createElement('div'), 'Element'); +test_append(document.createDocumentFragment(), 'DocumentFrgment'); +</script> +</html> diff --git a/testing/web-platform/tests/dom/nodes/ParentNode-prepend.html b/testing/web-platform/tests/dom/nodes/ParentNode-prepend.html new file mode 100644 index 000000000..644693ffe --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/ParentNode-prepend.html @@ -0,0 +1,66 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>ParentNode.prepend</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-parentnode-prepend"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + +function test_prepend(node, nodeName) { + + test(function() { + var parent = node.cloneNode(); + parent.prepend(); + assert_array_equals(parent.childNodes, []); + }, nodeName + '.prepend() without any argument, on a parent having no child.'); + + test(function() { + var parent = node.cloneNode(); + parent.prepend(null); + assert_equals(parent.childNodes[0].textContent, 'null'); + }, nodeName + '.prepend() with null as an argument, on a parent having no child.'); + + test(function() { + var parent = node.cloneNode(); + parent.prepend(undefined); + assert_equals(parent.childNodes[0].textContent, 'undefined'); + }, nodeName + '.prepend() with undefined as an argument, on a parent having no child.'); + + test(function() { + var parent = node.cloneNode(); + parent.prepend('text'); + assert_equals(parent.childNodes[0].textContent, 'text'); + }, nodeName + '.prepend() with only text as an argument, on a parent having no child.'); + + test(function() { + var parent = node.cloneNode(); + var x = document.createElement('x'); + parent.prepend(x); + assert_array_equals(parent.childNodes, [x]); + }, nodeName + '.prepend() with only one element as an argument, on a parent having no child.'); + + test(function() { + var parent = node.cloneNode(); + var child = document.createElement('test'); + parent.appendChild(child); + parent.prepend(null); + assert_equals(parent.childNodes[0].textContent, 'null'); + assert_equals(parent.childNodes[1], child); + }, nodeName + '.prepend() with null as an argument, on a parent having a child.'); + + test(function() { + var parent = node.cloneNode(); + var x = document.createElement('x'); + var child = document.createElement('test'); + parent.appendChild(child); + parent.prepend(x, 'text'); + assert_equals(parent.childNodes[0], x); + assert_equals(parent.childNodes[1].textContent, 'text'); + assert_equals(parent.childNodes[2], child); + }, nodeName + '.prepend() with one element and text as argument, on a parent having a child.'); +} + +test_prepend(document.createElement('div'), 'Element'); +test_prepend(document.createDocumentFragment(), 'DocumentFrgment'); +</script> +</html> diff --git a/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All-content.html b/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All-content.html new file mode 100644 index 000000000..affb00af2 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All-content.html @@ -0,0 +1,377 @@ +<!DOCTYPE html> +<html id="html" lang="en"> +<head id="head"> + <meta id="meta" charset="UTF-8"> + <title id="title">Selectors-API Test Suite: HTML with Selectors Level 2 using TestHarness: Test Document</title> + + <!-- Links for :link and :visited pseudo-class test --> + <link id="pseudo-link-link1" href=""> + <link id="pseudo-link-link2" href="http://example.org/"> + <link id="pseudo-link-link3"> + <style> + @namespace ns "http://www.w3.org/1999/xhtml"; + /* Declare the namespace prefix used in tests. This declaration should not be used by the API. */ + </style> +</head> +<body id="body"> +<div id="root"> + <div id="target"></div> + + <div id="universal"> + <p id="universal-p1">Universal selector tests inside element with <code id="universal-code1">id="universal"</code>.</p> + <hr id="universal-hr1"> + <pre id="universal-pre1">Some preformatted text with some <span id="universal-span1">embedded code</span></pre> + <p id="universal-p2">This is a normal link: <a id="universal-a1" href="http://www.w3.org/">W3C</a></p> + <address id="universal-address1">Some more nested elements <code id="universal-code2"><a href="#" id="universal-a2">code hyperlink</a></code></address> + </div> + + <div id="attr-presence"> + <div class="attr-presence-div1" id="attr-presence-div1" align="center"></div> + <div class="attr-presence-div2" id="attr-presence-div2" align=""></div> + <div class="attr-presence-div3" id="attr-presence-div3" valign="center"></div> + <div class="attr-presence-div4" id="attr-presence-div4" alignv="center"></div> + <p id="attr-presence-p1"><a id="attr-presence-a1" tItLe=""></a><span id="attr-presence-span1" TITLE="attr-presence-span1"></span></p> + <pre id="attr-presence-pre1" data-attr-presence="pre1"></pre> + <blockquote id="attr-presence-blockquote1" data-attr-presence="blockquote1"></blockquote> + <ul id="attr-presence-ul1" data-中文=""></ul> + + <select id="attr-presence-select1"> + <option id="attr-presence-select1-option1">A</option> + <option id="attr-presence-select1-option2">B</option> + <option id="attr-presence-select1-option3">C</option> + <option id="attr-presence-select1-option4">D</option> + </select> + <select id="attr-presence-select2"> + <option id="attr-presence-select2-option1">A</option> + <option id="attr-presence-select2-option2">B</option> + <option id="attr-presence-select2-option3">C</option> + <option id="attr-presence-select2-option4" selected="selected">D</option> + </select> + <select id="attr-presence-select3" multiple="multiple"> + <option id="attr-presence-select3-option1">A</option> + <option id="attr-presence-select3-option2" selected="">B</option> + <option id="attr-presence-select3-option3" selected="selected">C</option> + <option id="attr-presence-select3-option4">D</option> + </select> + </div> + + <div id="attr-value"> + <div id="attr-value-div1" align="center"></div> + <div id="attr-value-div2" align=""></div> + <div id="attr-value-div3" data-attr-value="é"></div> + <div id="attr-value-div4" data-attr-value_foo="é"></div> + + <form id="attr-value-form1"> + <input id="attr-value-input1" type="text"> + <input id="attr-value-input2" type="password"> + <input id="attr-value-input3" type="hidden"> + <input id="attr-value-input4" type="radio"> + <input id="attr-value-input5" type="checkbox"> + <input id="attr-value-input6" type="radio"> + <input id="attr-value-input7" type="text"> + <input id="attr-value-input8" type="hidden"> + <input id="attr-value-input9" type="radio"> + </form> + + <div id="attr-value-div5" data-attr-value="中文"></div> + </div> + + <div id="attr-whitespace"> + <div id="attr-whitespace-div1" class="foo div1 bar"></div> + <div id="attr-whitespace-div2" class=""></div> + <div id="attr-whitespace-div3" class="foo div3 bar"></div> + + <div id="attr-whitespace-div4" data-attr-whitespace="foo é bar"></div> + <div id="attr-whitespace-div5" data-attr-whitespace_foo="é foo"></div> + + <a id="attr-whitespace-a1" rel="next bookmark"></a> + <a id="attr-whitespace-a2" rel="tag nofollow"></a> + <a id="attr-whitespace-a3" rel="tag bookmark"></a> + <a id="attr-whitespace-a4" rel="book mark"></a> <!-- Intentional space in "book mark" --> + <a id="attr-whitespace-a5" rel="nofollow"></a> + <a id="attr-whitespace-a6" rev="bookmark nofollow"></a> + <a id="attr-whitespace-a7" rel="prev next tag alternate nofollow author help icon noreferrer prefetch search stylesheet tag"></a> + + <p id="attr-whitespace-p1" title="Chinese 中文 characters"></p> + </div> + + <div id="attr-hyphen"> + <div id="attr-hyphen-div1"></div> + <div id="attr-hyphen-div2" lang="fr"></div> + <div id="attr-hyphen-div3" lang="en-AU"></div> + <div id="attr-hyphen-div4" lang="es"></div> + </div> + + <div id="attr-begins"> + <a id="attr-begins-a1" href="http://www.example.org"></a> + <a id="attr-begins-a2" href="http://example.org/"></a> + <a id="attr-begins-a3" href="http://www.example.com/"></a> + + <div id="attr-begins-div1" lang="fr"></div> + <div id="attr-begins-div2" lang="en-AU"></div> + <div id="attr-begins-div3" lang="es"></div> + <div id="attr-begins-div4" lang="en-US"></div> + <div id="attr-begins-div5" lang="en"></div> + + <p id="attr-begins-p1" class=" apple"></p> <!-- Intentional space in class value " apple". --> + </div> + + <div id="attr-ends"> + <a id="attr-ends-a1" href="http://www.example.org"></a> + <a id="attr-ends-a2" href="http://example.org/"></a> + <a id="attr-ends-a3" href="http://www.example.org"></a> + + <div id="attr-ends-div1" lang="fr"></div> + <div id="attr-ends-div2" lang="de-CH"></div> + <div id="attr-ends-div3" lang="es"></div> + <div id="attr-ends-div4" lang="fr-CH"></div> + + <p id="attr-ends-p1" class="apple "></p> <!-- Intentional space in class value "apple ". --> + </div> + + <div id="attr-contains"> + <a id="attr-contains-a1" href="http://www.example.org"></a> + <a id="attr-contains-a2" href="http://example.org/"></a> + <a id="attr-contains-a3" href="http://www.example.com/"></a> + + <div id="attr-contains-div1" lang="fr"></div> + <div id="attr-contains-div2" lang="en-AU"></div> + <div id="attr-contains-div3" lang="de-CH"></div> + <div id="attr-contains-div4" lang="es"></div> + <div id="attr-contains-div5" lang="fr-CH"></div> + <div id="attr-contains-div6" lang="en-US"></div> + + <p id="attr-contains-p1" class=" apple banana orange "></p> + </div> + + <div id="pseudo-nth"> + <table id="pseudo-nth-table1"> + <tr id="pseudo-nth-tr1"><td id="pseudo-nth-td1"></td><td id="pseudo-nth-td2"></td><td id="pseudo-nth-td3"></td><td id="pseudo-nth-td4"></td><td id="pseudo-nth--td5"></td><td id="pseudo-nth-td6"></td></tr> + <tr id="pseudo-nth-tr2"><td id="pseudo-nth-td7"></td><td id="pseudo-nth-td8"></td><td id="pseudo-nth-td9"></td><td id="pseudo-nth-td10"></td><td id="pseudo-nth-td11"></td><td id="pseudo-nth-td12"></td></tr> + <tr id="pseudo-nth-tr3"><td id="pseudo-nth-td13"></td><td id="pseudo-nth-td14"></td><td id="pseudo-nth-td15"></td><td id="pseudo-nth-td16"></td><td id="pseudo-nth-td17"></td><td id="pseudo-nth-td18"></td></tr> + </table> + + <ol id="pseudo-nth-ol1"> + <li id="pseudo-nth-li1"></li> + <li id="pseudo-nth-li2"></li> + <li id="pseudo-nth-li3"></li> + <li id="pseudo-nth-li4"></li> + <li id="pseudo-nth-li5"></li> + <li id="pseudo-nth-li6"></li> + <li id="pseudo-nth-li7"></li> + <li id="pseudo-nth-li8"></li> + <li id="pseudo-nth-li9"></li> + <li id="pseudo-nth-li10"></li> + <li id="pseudo-nth-li11"></li> + <li id="pseudo-nth-li12"></li> + </ol> + + <p id="pseudo-nth-p1"> + <span id="pseudo-nth-span1">span1</span> + <em id="pseudo-nth-em1">em1</em> + <!-- comment node--> + <em id="pseudo-nth-em2">em2</em> + <span id="pseudo-nth-span2">span2</span> + <strong id="pseudo-nth-strong1">strong1</strong> + <em id="pseudo-nth-em3">em3</em> + <span id="pseudo-nth-span3">span3</span> + <span id="pseudo-nth-span4">span4</span> + <strong id="pseudo-nth-strong2">strong2</strong> + <em id="pseudo-nth-em4">em4</em> + </p> + </div> + + <div id="pseudo-first-child"> + <div id="pseudo-first-child-div1"></div> + <div id="pseudo-first-child-div2"></div> + <div id="pseudo-first-child-div3"></div> + + <p id="pseudo-first-child-p1"><span id="pseudo-first-child-span1"></span><span id="pseudo-first-child-span2"></span></p> + <p id="pseudo-first-child-p2"><span id="pseudo-first-child-span3"></span><span id="pseudo-first-child-span4"></span></p> + <p id="pseudo-first-child-p3"><span id="pseudo-first-child-span5"></span><span id="pseudo-first-child-span6"></span></p> + </div> + + <div id="pseudo-last-child"> + <p id="pseudo-last-child-p1"><span id="pseudo-last-child-span1"></span><span id="pseudo-last-child-span2"></span></p> + <p id="pseudo-last-child-p2"><span id="pseudo-last-child-span3"></span><span id="pseudo-last-child-span4"></span></p> + <p id="pseudo-last-child-p3"><span id="pseudo-last-child-span5"></span><span id="pseudo-last-child-span6"></span></p> + + <div id="pseudo-last-child-div1"></div> + <div id="pseudo-last-child-div2"></div> + <div id="pseudo-last-child-div3"></div> + </div> + + <div id="pseudo-only"> + <p id="pseudo-only-p1"> + <span id="pseudo-only-span1"></span> + </p> + <p id="pseudo-only-p2"> + <span id="pseudo-only-span2"></span> + <span id="pseudo-only-span3"></span> + </p> + <p id="pseudo-only-p3"> + <span id="pseudo-only-span4"></span> + <em id="pseudo-only-em1"></em> + <span id="pseudo-only-span5"></span> + </p> + </div>> + + <div id="pseudo-empty"> + <p id="pseudo-empty-p1"></p> + <p id="pseudo-empty-p2"><!-- comment node --></p> + <p id="pseudo-empty-p3"> </p> + <p id="pseudo-empty-p4">Text node</p> + <p id="pseudo-empty-p5"><span id="pseudo-empty-span1"></span></p> + </div> + + <div id="pseudo-link"> + <a id="pseudo-link-a1" href="">with href</a> + <a id="pseudo-link-a2" href="http://example.org/">with href</a> + <a id="pseudo-link-a3">without href</a> + <map name="pseudo-link-map1" id="pseudo-link-map1"> + <area id="pseudo-link-area1" href=""> + <area id="pseudo-link-area2"> + </map> + </div> + + <div id="pseudo-lang"> + <div id="pseudo-lang-div1"></div> + <div id="pseudo-lang-div2" lang="fr"></div> + <div id="pseudo-lang-div3" lang="en-AU"></div> + <div id="pseudo-lang-div4" lang="es"></div> + </div> + + <div id="pseudo-ui"> + <input id="pseudo-ui-input1" type="text"> + <input id="pseudo-ui-input2" type="password"> + <input id="pseudo-ui-input3" type="radio"> + <input id="pseudo-ui-input4" type="radio" checked="checked"> + <input id="pseudo-ui-input5" type="checkbox"> + <input id="pseudo-ui-input6" type="checkbox" checked="checked"> + <input id="pseudo-ui-input7" type="submit"> + <input id="pseudo-ui-input8" type="button"> + <input id="pseudo-ui-input9" type="hidden"> + <textarea id="pseudo-ui-textarea1"></textarea> + <button id="pseudo-ui-button1">Enabled</button> + + <input id="pseudo-ui-input10" disabled="disabled" type="text"> + <input id="pseudo-ui-input11" disabled="disabled" type="password"> + <input id="pseudo-ui-input12" disabled="disabled" type="radio"> + <input id="pseudo-ui-input13" disabled="disabled" type="radio" checked="checked"> + <input id="pseudo-ui-input14" disabled="disabled" type="checkbox"> + <input id="pseudo-ui-input15" disabled="disabled" type="checkbox" checked="checked"> + <input id="pseudo-ui-input16" disabled="disabled" type="submit"> + <input id="pseudo-ui-input17" disabled="disabled" type="button"> + <input id="pseudo-ui-input18" disabled="disabled" type="hidden"> + <textarea id="pseudo-ui-textarea2" disabled="disabled"></textarea> + <button id="pseudo-ui-button2" disabled="disabled">Disabled</button> + </div> + + <div id="not"> + <div id="not-div1"></div> + <div id="not-div2"></div> + <div id="not-div3"></div> + + <p id="not-p1"><span id="not-span1"></span><em id="not-em1"></em></p> + <p id="not-p2"><span id="not-span2"></span><em id="not-em2"></em></p> + <p id="not-p3"><span id="not-span3"></span><em id="not-em3"></em></p> + </div> + + <div id="pseudo-element">All pseudo-element tests</div> + + <div id="class"> + <p id="class-p1" class="foo class-p bar"></p> + <p id="class-p2" class="class-p foo bar"></p> + <p id="class-p3" class="foo bar class-p"></p> + + <!-- All permutations of the classes should match --> + <div id="class-div1" class="apple orange banana"></div> + <div id="class-div2" class="apple banana orange"></div> + <p id="class-p4" class="orange apple banana"></p> + <div id="class-div3" class="orange banana apple"></div> + <p id="class-p6" class="banana apple orange"></p> + <div id="class-div4" class="banana orange apple"></div> + <div id="class-div5" class="apple orange"></div> + <div id="class-div6" class="apple banana"></div> + <div id="class-div7" class="orange banana"></div> + + <span id="class-span1" class="台北Táiběi 台北"></span> + <span id="class-span2" class="台北"></span> + + <span id="class-span3" class="foo:bar"></span> + <span id="class-span4" class="test.foo[5]bar"></span> + </div> + + <div id="id"> + <div id="id-div1"></div> + <div id="id-div2"></div> + + <ul id="id-ul1"> + <li id="id-li-duplicate"></li> + <li id="id-li-duplicate"></li> + <li id="id-li-duplicate"></li> + <li id="id-li-duplicate"></li> + </ul> + + <span id="台北Táiběi"></span> + <span id="台北"></span> + + <span id="#foo:bar"></span> + <span id="test.foo[5]bar"></span> + </div> + + <div id="descendant"> + <div id="descendant-div1" class="descendant-div1"> + <div id="descendant-div2" class="descendant-div2"> + <div id="descendant-div3" class="descendant-div3"> + </div> + </div> + </div> + <div id="descendant-div4" class="descendant-div4"></div> + </div> + + <div id="child"> + <div id="child-div1" class="child-div1"> + <div id="child-div2" class="child-div2"> + <div id="child-div3" class="child-div3"> + </div> + </div> + </div> + <div id="child-div4" class="child-div4"></div> + </div> + + <div id="adjacent"> + <div id="adjacent-div1" class="adjacent-div1"></div> + <div id="adjacent-div2" class="adjacent-div2"> + <div id="adjacent-div3" class="adjacent-div3"></div> + </div> + <div id="adjacent-div4" class="adjacent-div4"> + <p id="adjacent-p1" class="adjacent-p1"></p> + <div id="adjacent-div5" class="adjacent-div5"></div> + </div> + <div id="adjacent-div6" class="adjacent-div6"></div> + <p id="adjacent-p2" class="adjacent-p2"></p> + <p id="adjacent-p3" class="adjacent-p3"></p> + </div> + + <div id="sibling"> + <div id="sibling-div1" class="sibling-div"></div> + <div id="sibling-div2" class="sibling-div"> + <div id="sibling-div3" class="sibling-div"></div> + </div> + <div id="sibling-div4" class="sibling-div"> + <p id="sibling-p1" class="sibling-p"></p> + <div id="sibling-div5" class="sibling-div"></div> + </div> + <div id="sibling-div6" class="sibling-div"></div> + <p id="sibling-p2" class="sibling-p"></p> + <p id="sibling-p3" class="sibling-p"></p> + </div> + + <div id="group"> + <em id="group-em1"></em> + <strong id="group-strong1"></strong> + </div> +</div> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All-content.xht b/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All-content.xht new file mode 100644 index 000000000..14faa9bd4 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All-content.xht @@ -0,0 +1,372 @@ +<!DOCTYPE html> +<html id="html" lang="en" xmlns="http://www.w3.org/1999/xhtml"> +<head id="head"> + <title id="title">Selectors-API Test Suite: HTML with Selectors Level 2 using TestHarness: Test Document</title> + + <!-- Links for :link and :visited pseudo-class test --> + <link id="pseudo-link-link1" href=""/> + <link id="pseudo-link-link2" href="http://example.org/"/> + <link id="pseudo-link-link3"/> +</head> +<body id="body"> +<div id="root"> + <div id="target"></div> + + <div id="universal"> + <p id="universal-p1">Universal selector tests inside element with <code id="universal-code1">id="universal"</code>.</p> + <hr id="universal-hr1"/> + <pre id="universal-pre1">Some preformatted text with some <span id="universal-span1">embedded code</span></pre> + <p id="universal-p2">This is a normal link: <a id="universal-a1" href="http://www.w3.org/">W3C</a></p> + <address id="universal-address1">Some more nested elements <code id="universal-code2"><a href="#" id="universal-a2">code hyperlink</a></code></address> + </div> + + <div id="attr-presence"> + <div class="attr-presence-div1" id="attr-presence-div1" align="center"></div> + <div class="attr-presence-div2" id="attr-presence-div2" align=""></div> + <div class="attr-presence-div3" id="attr-presence-div3" valign="center"></div> + <div class="attr-presence-div4" id="attr-presence-div4" alignv="center"></div> + <p id="attr-presence-p1"><a id="attr-presence-a1" tItLe=""></a><span id="attr-presence-span1" TITLE="attr-presence-span1"></span></p> + <pre id="attr-presence-pre1" data-attr-presence="pre1"></pre> + <blockquote id="attr-presence-blockquote1" data-attr-presence="blockquote1"></blockquote> + <ul id="attr-presence-ul1" data-中文=""></ul> + + <select id="attr-presence-select1"> + <option id="attr-presence-select1-option1">A</option> + <option id="attr-presence-select1-option2">B</option> + <option id="attr-presence-select1-option3">C</option> + <option id="attr-presence-select1-option4">D</option> + </select> + <select id="attr-presence-select2"> + <option id="attr-presence-select2-option1">A</option> + <option id="attr-presence-select2-option2">B</option> + <option id="attr-presence-select2-option3">C</option> + <option id="attr-presence-select2-option4" selected="selected">D</option> + </select> + <select id="attr-presence-select3" multiple="multiple"> + <option id="attr-presence-select3-option1">A</option> + <option id="attr-presence-select3-option2" selected="">B</option> + <option id="attr-presence-select3-option3" selected="selected">C</option> + <option id="attr-presence-select3-option4">D</option> + </select> + </div> + + <div id="attr-value"> + <div id="attr-value-div1" align="center"></div> + <div id="attr-value-div2" align=""></div> + <div id="attr-value-div3" data-attr-value="é"></div> + <div id="attr-value-div4" data-attr-value_foo="é"></div> + + <form id="attr-value-form1"> + <input id="attr-value-input1" type="text"/> + <input id="attr-value-input2" type="password"/> + <input id="attr-value-input3" type="hidden"/> + <input id="attr-value-input4" type="radio"/> + <input id="attr-value-input5" type="checkbox"/> + <input id="attr-value-input6" type="radio"/> + <input id="attr-value-input7" type="text"/> + <input id="attr-value-input8" type="hidden"/> + <input id="attr-value-input9" type="radio"/> + </form> + + <div id="attr-value-div5" data-attr-value="中文"></div> + </div> + + <div id="attr-whitespace"> + <div id="attr-whitespace-div1" class="foo div1 bar"></div> + <div id="attr-whitespace-div2" class=""></div> + <div id="attr-whitespace-div3" class="foo div3 bar"></div> + + <div id="attr-whitespace-div4" data-attr-whitespace="foo é bar"></div> + <div id="attr-whitespace-div5" data-attr-whitespace_foo="é foo"></div> + + <a id="attr-whitespace-a1" rel="next bookmark"></a> + <a id="attr-whitespace-a2" rel="tag nofollow"></a> + <a id="attr-whitespace-a3" rel="tag bookmark"></a> + <a id="attr-whitespace-a4" rel="book mark"></a> <!-- Intentional space in "book mark" --> + <a id="attr-whitespace-a5" rel="nofollow"></a> + <a id="attr-whitespace-a6" rev="bookmark nofollow"></a> + <a id="attr-whitespace-a7" rel="prev next tag alternate nofollow author help icon noreferrer prefetch search stylesheet tag"></a> + + <p id="attr-whitespace-p1" title="Chinese 中文 characters"></p> + </div> + + <div id="attr-hyphen"> + <div id="attr-hyphen-div1"></div> + <div id="attr-hyphen-div2" lang="fr"></div> + <div id="attr-hyphen-div3" lang="en-AU"></div> + <div id="attr-hyphen-div4" lang="es"></div> + </div> + + <div id="attr-begins"> + <a id="attr-begins-a1" href="http://www.example.org"></a> + <a id="attr-begins-a2" href="http://example.org/"></a> + <a id="attr-begins-a3" href="http://www.example.com/"></a> + + <div id="attr-begins-div1" lang="fr"></div> + <div id="attr-begins-div2" lang="en-AU"></div> + <div id="attr-begins-div3" lang="es"></div> + <div id="attr-begins-div4" lang="en-US"></div> + <div id="attr-begins-div5" lang="en"></div> + + <p id="attr-begins-p1" class=" apple"></p> <!-- Intentional space in class value " apple". --> + </div> + + <div id="attr-ends"> + <a id="attr-ends-a1" href="http://www.example.org"></a> + <a id="attr-ends-a2" href="http://example.org/"></a> + <a id="attr-ends-a3" href="http://www.example.org"></a> + + <div id="attr-ends-div1" lang="fr"></div> + <div id="attr-ends-div2" lang="de-CH"></div> + <div id="attr-ends-div3" lang="es"></div> + <div id="attr-ends-div4" lang="fr-CH"></div> + + <p id="attr-ends-p1" class="apple "></p> <!-- Intentional space in class value "apple ". --> + </div> + + <div id="attr-contains"> + <a id="attr-contains-a1" href="http://www.example.org"></a> + <a id="attr-contains-a2" href="http://example.org/"></a> + <a id="attr-contains-a3" href="http://www.example.com/"></a> + + <div id="attr-contains-div1" lang="fr"></div> + <div id="attr-contains-div2" lang="en-AU"></div> + <div id="attr-contains-div3" lang="de-CH"></div> + <div id="attr-contains-div4" lang="es"></div> + <div id="attr-contains-div5" lang="fr-CH"></div> + <div id="attr-contains-div6" lang="en-US"></div> + + <p id="attr-contains-p1" class=" apple banana orange "></p> + </div> + + <div id="pseudo-nth"> + <table id="pseudo-nth-table1"> + <tr id="pseudo-nth-tr1"><td id="pseudo-nth-td1"></td><td id="pseudo-nth-td2"></td><td id="pseudo-nth-td3"></td><td id="pseudo-nth-td4"></td><td id="pseudo-nth--td5"></td><td id="pseudo-nth-td6"></td></tr> + <tr id="pseudo-nth-tr2"><td id="pseudo-nth-td7"></td><td id="pseudo-nth-td8"></td><td id="pseudo-nth-td9"></td><td id="pseudo-nth-td10"></td><td id="pseudo-nth-td11"></td><td id="pseudo-nth-td12"></td></tr> + <tr id="pseudo-nth-tr3"><td id="pseudo-nth-td13"></td><td id="pseudo-nth-td14"></td><td id="pseudo-nth-td15"></td><td id="pseudo-nth-td16"></td><td id="pseudo-nth-td17"></td><td id="pseudo-nth-td18"></td></tr> + </table> + + <ol id="pseudo-nth-ol1"> + <li id="pseudo-nth-li1"></li> + <li id="pseudo-nth-li2"></li> + <li id="pseudo-nth-li3"></li> + <li id="pseudo-nth-li4"></li> + <li id="pseudo-nth-li5"></li> + <li id="pseudo-nth-li6"></li> + <li id="pseudo-nth-li7"></li> + <li id="pseudo-nth-li8"></li> + <li id="pseudo-nth-li9"></li> + <li id="pseudo-nth-li10"></li> + <li id="pseudo-nth-li11"></li> + <li id="pseudo-nth-li12"></li> + </ol> + + <p id="pseudo-nth-p1"> + <span id="pseudo-nth-span1">span1</span> + <em id="pseudo-nth-em1">em1</em> + <!-- comment node--> + <em id="pseudo-nth-em2">em2</em> + <span id="pseudo-nth-span2">span2</span> + <strong id="pseudo-nth-strong1">strong1</strong> + <em id="pseudo-nth-em3">em3</em> + <span id="pseudo-nth-span3">span3</span> + <span id="pseudo-nth-span4">span4</span> + <strong id="pseudo-nth-strong2">strong2</strong> + <em id="pseudo-nth-em4">em4</em> + </p> + </div> + + <div id="pseudo-first-child"> + <div id="pseudo-first-child-div1"></div> + <div id="pseudo-first-child-div2"></div> + <div id="pseudo-first-child-div3"></div> + + <p id="pseudo-first-child-p1"><span id="pseudo-first-child-span1"></span><span id="pseudo-first-child-span2"></span></p> + <p id="pseudo-first-child-p2"><span id="pseudo-first-child-span3"></span><span id="pseudo-first-child-span4"></span></p> + <p id="pseudo-first-child-p3"><span id="pseudo-first-child-span5"></span><span id="pseudo-first-child-span6"></span></p> + </div> + + <div id="pseudo-last-child"> + <p id="pseudo-last-child-p1"><span id="pseudo-last-child-span1"></span><span id="pseudo-last-child-span2"></span></p> + <p id="pseudo-last-child-p2"><span id="pseudo-last-child-span3"></span><span id="pseudo-last-child-span4"></span></p> + <p id="pseudo-last-child-p3"><span id="pseudo-last-child-span5"></span><span id="pseudo-last-child-span6"></span></p> + + <div id="pseudo-last-child-div1"></div> + <div id="pseudo-last-child-div2"></div> + <div id="pseudo-last-child-div3"></div> + </div> + + <div id="pseudo-only"> + <p id="pseudo-only-p1"> + <span id="pseudo-only-span1"></span> + </p> + <p id="pseudo-only-p2"> + <span id="pseudo-only-span2"></span> + <span id="pseudo-only-span3"></span> + </p> + <p id="pseudo-only-p3"> + <span id="pseudo-only-span4"></span> + <em id="pseudo-only-em1"></em> + <span id="pseudo-only-span5"></span> + </p> + </div>> + + <div id="pseudo-empty"> + <p id="pseudo-empty-p1"></p> + <p id="pseudo-empty-p2"><!-- comment node --></p> + <p id="pseudo-empty-p3"> </p> + <p id="pseudo-empty-p4">Text node</p> + <p id="pseudo-empty-p5"><span id="pseudo-empty-span1"></span></p> + </div> + + <div id="pseudo-link"> + <a id="pseudo-link-a1" href="">with href</a> + <a id="pseudo-link-a2" href="http://example.org/">with href</a> + <a id="pseudo-link-a3">without href</a> + <map name="pseudo-link-map1" id="pseudo-link-map1"> + <area id="pseudo-link-area1" href=""/> + <area id="pseudo-link-area2"/> + </map> + </div> + + <div id="pseudo-lang"> + <div id="pseudo-lang-div1"></div> + <div id="pseudo-lang-div2" lang="fr"></div> + <div id="pseudo-lang-div3" lang="en-AU"></div> + <div id="pseudo-lang-div4" lang="es"></div> + </div> + + <div id="pseudo-ui"> + <input id="pseudo-ui-input1" type="text"/> + <input id="pseudo-ui-input2" type="password"/> + <input id="pseudo-ui-input3" type="radio"/> + <input id="pseudo-ui-input4" type="radio" checked="checked"/> + <input id="pseudo-ui-input5" type="checkbox"/> + <input id="pseudo-ui-input6" type="checkbox" checked="checked"/> + <input id="pseudo-ui-input7" type="submit"/> + <input id="pseudo-ui-input8" type="button"/> + <input id="pseudo-ui-input9" type="hidden"/> + <textarea id="pseudo-ui-textarea1"></textarea> + <button id="pseudo-ui-button1">Enabled</button> + + <input id="pseudo-ui-input10" disabled="disabled" type="text"/> + <input id="pseudo-ui-input11" disabled="disabled" type="password"/> + <input id="pseudo-ui-input12" disabled="disabled" type="radio"/> + <input id="pseudo-ui-input13" disabled="disabled" type="radio" checked="checked"/> + <input id="pseudo-ui-input14" disabled="disabled" type="checkbox"/> + <input id="pseudo-ui-input15" disabled="disabled" type="checkbox" checked="checked"/> + <input id="pseudo-ui-input16" disabled="disabled" type="submit"/> + <input id="pseudo-ui-input17" disabled="disabled" type="button"/> + <input id="pseudo-ui-input18" disabled="disabled" type="hidden"/> + <textarea id="pseudo-ui-textarea2" disabled="disabled"></textarea> + <button id="pseudo-ui-button2" disabled="disabled">Disabled</button> + </div> + + <div id="not"> + <div id="not-div1"></div> + <div id="not-div2"></div> + <div id="not-div3"></div> + + <p id="not-p1"><span id="not-span1"></span><em id="not-em1"></em></p> + <p id="not-p2"><span id="not-span2"></span><em id="not-em2"></em></p> + <p id="not-p3"><span id="not-span3"></span><em id="not-em3"></em></p> + </div> + + <div id="pseudo-element">All pseudo-element tests</div> + + <div id="class"> + <p id="class-p1" class="foo class-p bar"></p> + <p id="class-p2" class="class-p foo bar"></p> + <p id="class-p3" class="foo bar class-p"></p> + + <!-- All permutations of the classes should match --> + <div id="class-div1" class="apple orange banana"></div> + <div id="class-div2" class="apple banana orange"></div> + <p id="class-p4" class="orange apple banana"></p> + <div id="class-div3" class="orange banana apple"></div> + <p id="class-p6" class="banana apple orange"></p> + <div id="class-div4" class="banana orange apple"></div> + <div id="class-div5" class="apple orange"></div> + <div id="class-div6" class="apple banana"></div> + <div id="class-div7" class="orange banana"></div> + + <span id="class-span1" class="台北Táiběi 台北"></span> + <span id="class-span2" class="台北"></span> + + <span id="class-span3" class="foo:bar"></span> + <span id="class-span4" class="test.foo[5]bar"></span> + </div> + + <div id="id"> + <div id="id-div1"></div> + <div id="id-div2"></div> + + <ul id="id-ul1"> + <li id="id-li-duplicate"></li> + <li id="id-li-duplicate"></li> + <li id="id-li-duplicate"></li> + <li id="id-li-duplicate"></li> + </ul> + + <span id="台北Táiběi"></span> + <span id="台北"></span> + + <span id="#foo:bar"></span> + <span id="test.foo[5]bar"></span> + </div> + + <div id="descendant"> + <div id="descendant-div1" class="descendant-div1"> + <div id="descendant-div2" class="descendant-div2"> + <div id="descendant-div3" class="descendant-div3"> + </div> + </div> + </div> + <div id="descendant-div4" class="descendant-div4"></div> + </div> + + <div id="child"> + <div id="child-div1" class="child-div1"> + <div id="child-div2" class="child-div2"> + <div id="child-div3" class="child-div3"> + </div> + </div> + </div> + <div id="child-div4" class="child-div4"></div> + </div> + + <div id="adjacent"> + <div id="adjacent-div1" class="adjacent-div1"></div> + <div id="adjacent-div2" class="adjacent-div2"> + <div id="adjacent-div3" class="adjacent-div3"></div> + </div> + <div id="adjacent-div4" class="adjacent-div4"> + <p id="adjacent-p1" class="adjacent-p1"></p> + <div id="adjacent-div5" class="adjacent-div5"></div> + </div> + <div id="adjacent-div6" class="adjacent-div6"></div> + <p id="adjacent-p2" class="adjacent-p2"></p> + <p id="adjacent-p3" class="adjacent-p3"></p> + </div> + + <div id="sibling"> + <div id="sibling-div1" class="sibling-div"></div> + <div id="sibling-div2" class="sibling-div"> + <div id="sibling-div3" class="sibling-div"></div> + </div> + <div id="sibling-div4" class="sibling-div"> + <p id="sibling-p1" class="sibling-p"></p> + <div id="sibling-div5" class="sibling-div"></div> + </div> + <div id="sibling-div6" class="sibling-div"></div> + <p id="sibling-p2" class="sibling-p"></p> + <p id="sibling-p3" class="sibling-p"></p> + </div> + + <div id="group"> + <em id="group-em1"></em> + <strong id="group-strong1"></strong> + </div> +</div> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All-xht.xht b/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All-xht.xht new file mode 100644 index 000000000..7a673202b --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All-xht.xht @@ -0,0 +1,114 @@ +<!DOCTYPE html> +<html id="html" lang="en" xmlns="http://www.w3.org/1999/xhtml"> +<head id="head"> +<title>Selectors-API Test Suite: XHTML</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="selectors.js"></script> +<script src="ParentNode-querySelector-All.js"></script> +<style>iframe { visibility: hidden; position: absolute; }</style> +</head> +<body> +<div id="log">This test requires JavaScript.</div> + +<script><![CDATA[ +async_test(function() { + var frame = document.createElement("iframe"); + frame.onload = this.step_func_done(init); + frame.src = "ParentNode-querySelector-All-content.xht#target"; + document.body.appendChild(frame); +}) + +function init(e) { + /* + * This test suite tests Selectors API methods in 4 different contexts: + * 1. Document node + * 2. In-document Element node + * 3. Detached Element node (an element with no parent, not in the document) + * 4. Document Fragment node + * + * For each context, the following tests are run: + * + * The interface check tests ensure that each type of node exposes the Selectors API methods + * + * The special selector tests verify the result of passing special values for the selector parameter, + * to ensure that the correct WebIDL processing is performed, such as stringification of null and + * undefined and missing parameter. The universal selector is also tested here, rather than with the + * rest of ordinary selectors for practical reasons. + * + * The static list verification tests ensure that the node lists returned by the method remain unchanged + * due to subsequent document modication, and that a new list is generated each time the method is + * invoked based on the current state of the document. + * + * The invalid selector tests ensure that SyntaxError is thrown for invalid forms of selectors + * + * The valid selector tests check the result from querying many different types of selectors, with a + * list of expected elements. This checks that querySelector() always returns the first result from + * querySelectorAll(), and that all matching elements are correctly returned in tree-order. The tests + * can be limited by specifying the test types to run, using the testType variable. The constants for this + * can be found in selectors.js. + * + * All the selectors tested for both the valid and invalid selector tests are found in selectors.js. + * See comments in that file for documentation of the format used. + * + * The ParentNode-querySelector-All.js file contains all the common test functions for running each of the aforementioned tests + */ + + var testType = TEST_QSA; + var docType = "xhtml"; // Only run tests suitable for XHTML + + // Prepare the nodes for testing + var doc = e.target.contentDocument; // Document Node tests + + var element = doc.getElementById("root"); // In-document Element Node tests + + //Setup the namespace tests + setupSpecialElements(doc, element); + + var outOfScope = element.cloneNode(true); // Append this to the body before running the in-document + // Element tests, but after running the Document tests. This + // tests that no elements that are not descendants of element + // are selected. + + traverse(outOfScope, function(elem) { // Annotate each element as being a clone; used for verifying + elem.setAttribute("data-clone", ""); // that none of these elements ever match. + }); + + + var detached = element.cloneNode(true); // Detached Element Node tests + + var fragment = doc.createDocumentFragment(); // Fragment Node tests + fragment.appendChild(element.cloneNode(true)); + + // Setup Tests + interfaceCheck("Document", doc); + interfaceCheck("Detached Element", detached); + interfaceCheck("Fragment", fragment); + interfaceCheck("In-document Element", element); + + runSpecialSelectorTests("Document", doc); + runSpecialSelectorTests("Detached Element", detached); + runSpecialSelectorTests("Fragment", fragment); + runSpecialSelectorTests("In-document Element", element); + + verifyStaticList("Document", doc, doc); + verifyStaticList("Detached Element", doc, detached); + verifyStaticList("Fragment", doc, fragment); + verifyStaticList("In-document Element", doc, element); + + runInvalidSelectorTest("Document", doc, invalidSelectors); + runInvalidSelectorTest("Detached Element", detached, invalidSelectors); + runInvalidSelectorTest("Fragment", fragment, invalidSelectors); + runInvalidSelectorTest("In-document Element", element, invalidSelectors); + + runValidSelectorTest("Document", doc, validSelectors, testType, docType); + runValidSelectorTest("Detached Element", detached, validSelectors, testType, docType); + runValidSelectorTest("Fragment", fragment, validSelectors, testType, docType); + + doc.body.appendChild(outOfScope); // Append before in-document Element tests. + // None of these elements should match + runValidSelectorTest("In-document Element", element, validSelectors, testType, docType); +} +]]></script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All.html b/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All.html new file mode 100644 index 000000000..159b0b967 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All.html @@ -0,0 +1,110 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>Selectors-API Test Suite: HTML</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="selectors.js"></script> +<script src="ParentNode-querySelector-All.js"></script> +<style>iframe { visibility: hidden; position: absolute; }</style> + +<div id="log">This test requires JavaScript.</div> + +<script> +async_test(function() { + var frame = document.createElement("iframe"); + frame.onload = this.step_func_done(init); + frame.src = "ParentNode-querySelector-All-content.html#target"; + document.body.appendChild(frame); +}); + +function init(e) { + /* + * This test suite tests Selectors API methods in 4 different contexts: + * 1. Document node + * 2. In-document Element node + * 3. Detached Element node (an element with no parent, not in the document) + * 4. Document Fragment node + * + * For each context, the following tests are run: + * + * The interface check tests ensure that each type of node exposes the Selectors API methods + * + * The special selector tests verify the result of passing special values for the selector parameter, + * to ensure that the correct WebIDL processing is performed, such as stringification of null and + * undefined and missing parameter. The universal selector is also tested here, rather than with the + * rest of ordinary selectors for practical reasons. + * + * The static list verification tests ensure that the node lists returned by the method remain unchanged + * due to subsequent document modication, and that a new list is generated each time the method is + * invoked based on the current state of the document. + * + * The invalid selector tests ensure that SyntaxError is thrown for invalid forms of selectors + * + * The valid selector tests check the result from querying many different types of selectors, with a + * list of expected elements. This checks that querySelector() always returns the first result from + * querySelectorAll(), and that all matching elements are correctly returned in tree-order. The tests + * can be limited by specifying the test types to run, using the testType variable. The constants for this + * can be found in selectors.js. + * + * All the selectors tested for both the valid and invalid selector tests are found in selectors.js. + * See comments in that file for documentation of the format used. + * + * The ParentNode-querySelector-All.js file contains all the common test functions for running each of the aforementioned tests + */ + + var testType = TEST_QSA; + var docType = "html"; // Only run tests suitable for HTML + + // Prepare the nodes for testing + var doc = e.target.contentDocument; // Document Node tests + + var element = doc.getElementById("root"); // In-document Element Node tests + + //Setup the namespace tests + setupSpecialElements(doc, element); + + var outOfScope = element.cloneNode(true); // Append this to the body before running the in-document + // Element tests, but after running the Document tests. This + // tests that no elements that are not descendants of element + // are selected. + + traverse(outOfScope, function(elem) { // Annotate each element as being a clone; used for verifying + elem.setAttribute("data-clone", ""); // that none of these elements ever match. + }); + + + var detached = element.cloneNode(true); // Detached Element Node tests + + var fragment = doc.createDocumentFragment(); // Fragment Node tests + fragment.appendChild(element.cloneNode(true)); + + // Setup Tests + interfaceCheck("Document", doc); + interfaceCheck("Detached Element", detached); + interfaceCheck("Fragment", fragment); + interfaceCheck("In-document Element", element); + + runSpecialSelectorTests("Document", doc); + runSpecialSelectorTests("Detached Element", detached); + runSpecialSelectorTests("Fragment", fragment); + runSpecialSelectorTests("In-document Element", element); + + verifyStaticList("Document", doc, doc); + verifyStaticList("Detached Element", doc, detached); + verifyStaticList("Fragment", doc, fragment); + verifyStaticList("In-document Element", doc, element); + + runInvalidSelectorTest("Document", doc, invalidSelectors); + runInvalidSelectorTest("Detached Element", detached, invalidSelectors); + runInvalidSelectorTest("Fragment", fragment, invalidSelectors); + runInvalidSelectorTest("In-document Element", element, invalidSelectors); + + runValidSelectorTest("Document", doc, validSelectors, testType, docType); + runValidSelectorTest("Detached Element", detached, validSelectors, testType, docType); + runValidSelectorTest("Fragment", fragment, validSelectors, testType, docType); + + doc.body.appendChild(outOfScope); // Append before in-document Element tests. + // None of these elements should match + runValidSelectorTest("In-document Element", element, validSelectors, testType, docType); +} +</script> diff --git a/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All.js b/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All.js new file mode 100644 index 000000000..4e6bef6d5 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All.js @@ -0,0 +1,252 @@ +// Require selectors.js to be included before this. + +/* + * Create and append special elements that cannot be created correctly with HTML markup alone. + */ +function setupSpecialElements(doc, parent) { + // Setup null and undefined tests + parent.appendChild(doc.createElement("null")); + parent.appendChild(doc.createElement("undefined")); + + // Setup namespace tests + var anyNS = doc.createElement("div"); + var noNS = doc.createElement("div"); + anyNS.id = "any-namespace"; + noNS.id = "no-namespace"; + + var divs; + div = [doc.createElement("div"), + doc.createElementNS("http://www.w3.org/1999/xhtml", "div"), + doc.createElementNS("", "div"), + doc.createElementNS("http://www.example.org/ns", "div")]; + + div[0].id = "any-namespace-div1"; + div[1].id = "any-namespace-div2"; + div[2].setAttribute("id", "any-namespace-div3"); // Non-HTML elements can't use .id property + div[3].setAttribute("id", "any-namespace-div4"); + + for (var i = 0; i < div.length; i++) { + anyNS.appendChild(div[i]) + } + + div = [doc.createElement("div"), + doc.createElementNS("http://www.w3.org/1999/xhtml", "div"), + doc.createElementNS("", "div"), + doc.createElementNS("http://www.example.org/ns", "div")]; + + div[0].id = "no-namespace-div1"; + div[1].id = "no-namespace-div2"; + div[2].setAttribute("id", "no-namespace-div3"); // Non-HTML elements can't use .id property + div[3].setAttribute("id", "no-namespace-div4"); + + for (i = 0; i < div.length; i++) { + noNS.appendChild(div[i]) + } + + parent.appendChild(anyNS); + parent.appendChild(noNS); +} + +/* + * Check that the querySelector and querySelectorAll methods exist on the given Node + */ +function interfaceCheck(type, obj) { + test(function() { + var q = typeof obj.querySelector === "function"; + assert_true(q, type + " supports querySelector."); + }, type + " supports querySelector") + + test(function() { + var qa = typeof obj.querySelectorAll === "function"; + assert_true( qa, type + " supports querySelectorAll."); + }, type + " supports querySelectorAll") + + test(function() { + var list = obj.querySelectorAll("div"); + if (obj.ownerDocument) { // The object is not a Document + assert_true(list instanceof obj.ownerDocument.defaultView.NodeList, "The result should be an instance of a NodeList") + } else { // The object is a Document + assert_true(list instanceof obj.defaultView.NodeList, "The result should be an instance of a NodeList") + } + }, type + ".querySelectorAll returns NodeList instance") +} + +/* + * Verify that the NodeList returned by querySelectorAll is static and and that a new list is created after + * each call. A static list should not be affected by subsequent changes to the DOM. + */ +function verifyStaticList(type, doc, root) { + var pre, post, preLength; + + test(function() { + pre = root.querySelectorAll("div"); + preLength = pre.length; + + var div = doc.createElement("div"); + (root.body || root).appendChild(div); + + assert_equals(pre.length, preLength, "The length of the NodeList should not change.") + }, type + ": static NodeList") + + test(function() { + post = root.querySelectorAll("div"), + assert_equals(post.length, preLength + 1, "The length of the new NodeList should be 1 more than the previous list.") + }, type + ": new NodeList") +} + +/* + * Verify handling of special values for the selector parameter, including stringification of + * null and undefined, and the handling of the empty string. + */ +function runSpecialSelectorTests(type, root) { + test(function() { // 1 + assert_equals(root.querySelectorAll(null).length, 1, "This should find one element with the tag name 'NULL'."); + }, type + ".querySelectorAll null") + + test(function() { // 2 + assert_equals(root.querySelectorAll(undefined).length, 1, "This should find one element with the tag name 'UNDEFINED'."); + }, type + ".querySelectorAll undefined") + + test(function() { // 3 + assert_throws(TypeError(), function() { + root.querySelectorAll(); + }, "This should throw a TypeError.") + }, type + ".querySelectorAll no parameter") + + test(function() { // 4 + var elm = root.querySelector(null) + assert_not_equals(elm, null, "This should find an element."); + assert_equals(elm.tagName.toUpperCase(), "NULL", "The tag name should be 'NULL'.") + }, type + ".querySelector null") + + test(function() { // 5 + var elm = root.querySelector(undefined) + assert_not_equals(elm, undefined, "This should find an element."); + assert_equals(elm.tagName.toUpperCase(), "UNDEFINED", "The tag name should be 'UNDEFINED'.") + }, type + ".querySelector undefined") + + test(function() { // 6 + assert_throws(TypeError(), function() { + root.querySelector(); + }, "This should throw a TypeError.") + }, type + ".querySelector no parameter") + + test(function() { // 7 + result = root.querySelectorAll("*"); + var i = 0; + traverse(root, function(elem) { + if (elem !== root) { + assert_equals(elem, result[i], "The result in index " + i + " should be in tree order."); + i++; + } + }) + }, type + ".querySelectorAll tree order"); +} + +/* + * Execute queries with the specified valid selectors for both querySelector() and querySelectorAll() + * Only run these tests when results are expected. Don't run for syntax error tests. + */ +function runValidSelectorTest(type, root, selectors, testType, docType) { + var nodeType = ""; + switch (root.nodeType) { + case Node.DOCUMENT_NODE: + nodeType = "document"; + break; + case Node.ELEMENT_NODE: + nodeType = root.parentNode ? "element" : "detached"; + break; + case Node.DOCUMENT_FRAGMENT_NODE: + nodeType = "fragment"; + break; + default: + assert_unreached(); + nodeType = "unknown"; // This should never happen. + } + + for (var i = 0; i < selectors.length; i++) { + var s = selectors[i]; + var n = s["name"]; + var q = s["selector"]; + var e = s["expect"]; + + if ((!s["exclude"] || (s["exclude"].indexOf(nodeType) === -1 && s["exclude"].indexOf(docType) === -1)) + && (s["testType"] & testType) ) { + var foundall, found; + + test(function() { + foundall = root.querySelectorAll(q); + assert_not_equals(foundall, null, "The method should not return null.") + assert_equals(foundall.length, e.length, "The method should return the expected number of matches.") + + for (var i = 0; i < e.length; i++) { + assert_not_equals(foundall[i], null, "The item in index " + i + " should not be null.") + assert_equals(foundall[i].getAttribute("id"), e[i], "The item in index " + i + " should have the expected ID."); + assert_false(foundall[i].hasAttribute("data-clone"), "This should not be a cloned element."); + } + }, type + ".querySelectorAll: " + n + ": " + q); + + test(function() { + found = root.querySelector(q); + + if (e.length > 0) { + assert_not_equals(found, null, "The method should return a match.") + assert_equals(found.getAttribute("id"), e[0], "The method should return the first match."); + assert_equals(found, foundall[0], "The result should match the first item from querySelectorAll."); + assert_false(found.hasAttribute("data-clone"), "This should not be annotated as a cloned element."); + } else { + assert_equals(found, null, "The method should not match anything."); + } + }, type + ".querySelector: " + n + ": " + q); + } + } +} + +/* + * Execute queries with the specified invalid selectors for both querySelector() and querySelectorAll() + * Only run these tests when errors are expected. Don't run for valid selector tests. + */ +function runInvalidSelectorTest(type, root, selectors) { + for (var i = 0; i < selectors.length; i++) { + var s = selectors[i]; + var n = s["name"]; + var q = s["selector"]; + + test(function() { + assert_throws("SyntaxError", function() { + root.querySelector(q) + }) + }, type + ".querySelector: " + n + ": " + q); + + test(function() { + assert_throws("SyntaxError", function() { + root.querySelectorAll(q) + }) + }, type + ".querySelectorAll: " + n + ": " + q); + } +} + +function traverse(elem, fn) { + if (elem.nodeType === elem.ELEMENT_NODE) { + fn(elem); + } + elem = elem.firstChild; + while (elem) { + traverse(elem, fn); + elem = elem.nextSibling; + } +} + +function getNodeType(node) { + switch (node.nodeType) { + case Node.DOCUMENT_NODE: + return "document"; + case Node.ELEMENT_NODE: + return node.parentNode ? "element" : "detached"; + case Node.DOCUMENT_FRAGMENT_NODE: + return "fragment"; + default: + assert_unreached(); + return "unknown"; // This should never happen. + } +} diff --git a/testing/web-platform/tests/dom/nodes/ProcessingInstruction-escapes-1.xhtml b/testing/web-platform/tests/dom/nodes/ProcessingInstruction-escapes-1.xhtml new file mode 100644 index 000000000..d629a8464 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/ProcessingInstruction-escapes-1.xhtml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?xml-stylesheet href="support/style.css" type="text/css"?> +<?xml-stylesheet href="data:text/css,A&'" type="text/css"?> +<?xml-stylesheet href="data:text/css,A&'" type="text/css"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>ProcessingInstruction numeric escapes</title> +<link rel="help" href="https://dom.spec.whatwg.org/#dom-processinginstruction-target"/> +<link rel="help" href="https://dom.spec.whatwg.org/#dom-characterdata-data"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="log"/> +<script> +<![CDATA[ +test(function() { + var pienc = document.firstChild.nextSibling; + assert_true(pienc instanceof ProcessingInstruction) + assert_equals(pienc.target, "xml-stylesheet") + assert_equals(pienc.data, 'href="data:text/css,A&'" type="text/css"') + assert_equals(pienc.sheet.href, "data:text/css,A&'"); + + pienc = pienc.nextSibling; + assert_true(pienc instanceof ProcessingInstruction) + assert_equals(pienc.target, "xml-stylesheet") + assert_equals(pienc.data, 'href="data:text/css,A&'" type="text/css"') + assert_equals(pienc.sheet.href, "data:text/css,A&'"); +}) +]]> +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/ProcessingInstruction-literal-1.xhtml b/testing/web-platform/tests/dom/nodes/ProcessingInstruction-literal-1.xhtml new file mode 100644 index 000000000..4eaf86cbd --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/ProcessingInstruction-literal-1.xhtml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title><?xml?> is not a ProcessingInstruction</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="log"/> +<script> +test(function() { + assert_equals(document.firstChild, document.documentElement) +}) +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/ProcessingInstruction-literal-2.xhtml b/testing/web-platform/tests/dom/nodes/ProcessingInstruction-literal-2.xhtml new file mode 100644 index 000000000..d878c697c --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/ProcessingInstruction-literal-2.xhtml @@ -0,0 +1,21 @@ +<?xml-stylesheet href="support/style.css" type="text/css"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>ProcessingInstruction literals</title> +<link rel="help" href="https://dom.spec.whatwg.org/#dom-processinginstruction-target"/> +<link rel="help" href="https://dom.spec.whatwg.org/#dom-characterdata-data"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="log"/> +<script> +test(function() { + var pienc = document.firstChild; + assert_true(pienc instanceof ProcessingInstruction) + assert_equals(pienc.target, "xml-stylesheet") + assert_equals(pienc.data, 'href="support/style.css" type="text/css"') +}) +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/Text-constructor.html b/testing/web-platform/tests/dom/nodes/Text-constructor.html new file mode 100644 index 000000000..dbd9a0be0 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Text-constructor.html @@ -0,0 +1,11 @@ +<!doctype html> +<meta charset=utf-8> +<title>Text constructor</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-text"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="Comment-Text-constructor.js"></script> +<div id="log"></div> +<script> +test_constructor("Text"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/Text-splitText.html b/testing/web-platform/tests/dom/nodes/Text-splitText.html new file mode 100644 index 000000000..aec1cee52 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/Text-splitText.html @@ -0,0 +1,53 @@ +<!doctype html> +<meta charset=utf-8> +<title>Text.splitText()</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-text-splittextoffset"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + var text = document.createTextNode("camembert"); + assert_throws("INDEX_SIZE_ERR", function () { text.splitText(10) }); +}, "Split text after end of data"); + +test(function() { + var text = document.createTextNode(""); + var new_text = text.splitText(0); + assert_equals(text.data, ""); + assert_equals(new_text.data, ""); +}, "Split empty text"); + +test(function() { + var text = document.createTextNode("comté"); + var new_text = text.splitText(0); + assert_equals(text.data, ""); + assert_equals(new_text.data, "comté"); +}, "Split text at beginning"); + +test(function() { + var text = document.createTextNode("comté"); + var new_text = text.splitText(5); + assert_equals(text.data, "comté"); + assert_equals(new_text.data, ""); +}, "Split text at end"); + +test(function() { + var text = document.createTextNode("comté"); + var new_text = text.splitText(3); + assert_equals(text.data, "com"); + assert_equals(new_text.data, "té"); + assert_equals(new_text.parentNode, null); +}, "Split root"); + +test(function() { + var parent = document.createElement('div'); + var text = document.createTextNode("bleu"); + parent.appendChild(text); + var new_text = text.splitText(2); + assert_equals(text.data, "bl"); + assert_equals(new_text.data, "eu"); + assert_equals(text.nextSibling, new_text); + assert_equals(new_text.parentNode, parent); +}, "Split child"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/append-on-Document.html b/testing/web-platform/tests/dom/nodes/append-on-Document.html new file mode 100644 index 000000000..8d9ce2e3f --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/append-on-Document.html @@ -0,0 +1,53 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>DocumentType.append</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-parentnode-append"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + +function test_append_on_Document() { + + var node = document.implementation.createDocument(null, null); + test(function() { + var parent = node.cloneNode(); + parent.append(); + assert_array_equals(parent.childNodes, []); + }, 'Document.append() without any argument, on a Document having no child.'); + + test(function() { + var parent = node.cloneNode(); + var x = document.createElement('x'); + parent.append(x); + assert_array_equals(parent.childNodes, [x]); + }, 'Document.append() with only one element as an argument, on a Document having no child.'); + + test(function() { + var parent = node.cloneNode(); + var x = document.createElement('x'); + var y = document.createElement('y'); + parent.appendChild(x); + assert_throws('HierarchyRequestError', function() { parent.append(y); }); + assert_array_equals(parent.childNodes, [x]); + }, 'Document.append() with only one element as an argument, on a Document having one child.'); + + test(function() { + var parent = node.cloneNode(); + assert_throws('HierarchyRequestError', function() { parent.append('text'); }); + assert_array_equals(parent.childNodes, []); + }, 'Document.append() with text as an argument, on a Document having no child.'); + + test(function() { + var parent = node.cloneNode(); + var x = document.createElement('x'); + var y = document.createElement('y'); + assert_throws('HierarchyRequestError', function() { parent.append(x, y); }); + assert_array_equals(parent.childNodes, []); + }, 'Document.append() with two elements as the argument, on a Document having no child.'); + +} + +test_append_on_Document(); + +</script> +</html> diff --git a/testing/web-platform/tests/dom/nodes/attributes.html b/testing/web-platform/tests/dom/nodes/attributes.html new file mode 100644 index 000000000..8d983350d --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/attributes.html @@ -0,0 +1,712 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Attributes tests</title> +<link rel=help href="https://dom.spec.whatwg.org/#attr"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-element-setattribute"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-element-setattributens"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="attributes.js"></script> +<script src="productions.js"></script> +<div id="log"></div> +<span id="test1"></span> +<span class="&<>foo"></span> +<span id="test2"> + <span ~=""></span> + <span ~></span> + <span></span> +</span> +<script> +var XML = "http://www.w3.org/XML/1998/namespace" +var XMLNS = "http://www.w3.org/2000/xmlns/" + +// setAttribute exhaustive tests +// Step 1 +test(function() { + var el = document.createElement("foo") + for (var i = 0; i < invalid_names.length; i++) { + assert_throws("INVALID_CHARACTER_ERR", function() { el.setAttribute(invalid_names[i], "test") }) + } +}, "When qualifiedName does not match the Name production, an " + + "INVALID_CHARACTER_ERR exception is to be thrown. (setAttribute)") +test(function() { + var el = document.getElementById("test2") + for (var i = 0; i < el.children.length; i++) { + assert_throws("INVALID_CHARACTER_ERR", function() { + el.children[i].setAttribute("~", "test") + }) + } +}, "When qualifiedName does not match the Name production, an " + + "INVALID_CHARACTER_ERR exception is to be thrown, even if the attribute " + + "is already present. (setAttribute)") + +// Step 2 +test(function() { + var el = document.createElement("div") + el.setAttribute("ALIGN", "left") + assert_equals(el.getAttributeNS("", "ALIGN"), null) + assert_equals(el.getAttributeNS("", "align"), "left") + assert_equals(el.getAttribute("align"), "left") +}, "setAttribute should lowercase its name argument (upper case attribute)") +test(function() { + var el = document.createElement("div") + el.setAttribute("CHEEseCaKe", "tasty") + assert_equals(el.getAttributeNS("", "CHEEseCaKe"), null) + assert_equals(el.getAttributeNS("", "cheesecake"), "tasty") + assert_equals(el.getAttribute("cheesecake"), "tasty") +}, "setAttribute should lowercase its name argument (mixed case attribute)") + +// Step 3 +test(function() { + var el = document.createElement("foo") + var tests = ["xmlns", "xmlns:a", "xmlnsx", "xmlns0"] + for (var i = 0; i < tests.length; i++) { + el.setAttribute(tests[i], "success"); + } +}, "setAttribute should not throw even when qualifiedName starts with 'xmlns'") + +// Step 4 +test(function() { + var el = document.createElement("foo") + for (var i = 0; i < valid_names.length; i++) { + el.setAttribute(valid_names[i], "test") + assert_equals(el.getAttribute(valid_names[i]), "test") + } +}, "Basic functionality should be intact.") + +// Step 5 +test(function() { + var el = document.createElement("foo") + el.setAttribute("a", "1") + el.setAttribute("b", "2") + el.setAttribute("a", "3") + el.setAttribute("c", "4") + attributes_are(el, [["a", "3"], + ["b", "2"], + ["c", "4"]]) +}, "setAttribute should not change the order of previously set attributes.") +test(function() { + var el = document.createElement("baz") + el.setAttributeNS("ab", "attr", "fail") + el.setAttributeNS("kl", "attr", "pass") + el.setAttribute("attr", "pass") + attributes_are(el, [["attr", "pass", "ab"], + ["attr", "pass", "kl"]]) +}, "setAttribute should set the first attribute with the given name") +test(function() { + // Based on a test by David Flanagan. + var el = document.createElement("baz") + el.setAttributeNS("foo", "foo:bar", "1"); + assert_equals(el.getAttribute("foo:bar"), "1") + attr_is(el.attributes[0], "1", "bar", "foo", "foo", "foo:bar") + el.setAttribute("foo:bar", "2"); + assert_equals(el.getAttribute("foo:bar"), "2") + attr_is(el.attributes[0], "2", "bar", "foo", "foo", "foo:bar") +}, "setAttribute should set the attribute with the given qualified name") + +// setAttributeNS exhaustive tests +// Step 1 +test(function() { + var el = document.createElement("foo") + for (var i = 0, il = invalid_names.length; i < il; ++i) { + assert_throws("INVALID_CHARACTER_ERR", + function() { el.setAttributeNS("a", invalid_names[i], "fail") }) + } +}, "When qualifiedName does not match the Name production, an " + + "INVALID_CHARACTER_ERR exception is to be thrown. (setAttributeNS)") + +test(function() { + var el = document.getElementById("test2") + for (var i = 0; i < el.children.length; i++) { + assert_throws("INVALID_CHARACTER_ERR", function() { + el.children[i].setAttributeNS(null, "~", "test") + }) + } +}, "When qualifiedName does not match the Name production, an " + + "INVALID_CHARACTER_ERR exception is to be thrown, even if the attribute " + + "is already present. (setAttributeNS)") + +// Step 2 +test(function() { + var el = document.createElement("foo") + for (var i = 0, il = invalid_qnames.length; i < il; ++i) { + assert_throws("NAMESPACE_ERR", + function() { el.setAttributeNS("a", invalid_qnames[i], "fail") }, + "Expected exception for " + invalid_qnames[i] + ".") + } +}, "When qualifiedName does not match the QName production, an " + + "NAMESPACE_ERR exception is to be thrown.") + +// Step 3 +test(function() { + var el = document.createElement("foo") + el.setAttributeNS(null, "aa", "bb") + el.setAttributeNS("", "xx", "bb") + attributes_are(el, [["aa", "bb"], + ["xx", "bb"]]) +}, "null and the empty string should result in a null namespace.") + +// Step 4 +test(function() { + var el = document.createElement("foo") + assert_throws("NAMESPACE_ERR", + function() { el.setAttributeNS("", "aa:bb", "fail") }) + assert_throws("NAMESPACE_ERR", + function() { el.setAttributeNS(null, "aa:bb", "fail") }) +}, "A namespace is required to use a prefix.") + +// Step 5 +test(function() { + var el = document.createElement("foo") + assert_throws("NAMESPACE_ERR", + function() { el.setAttributeNS("a", "xml:bb", "fail") }) +}, "The xml prefix should not be allowed for arbitrary namespaces") +test(function() { + var el = document.createElement("foo") + el.setAttributeNS(XML, "a:bb", "pass") + assert_equals(el.attributes.length, 1) + attr_is(el.attributes[0], "pass", "bb", XML, "a", "a:bb") +}, "XML-namespaced attributes don't need an xml prefix") + +// Step 6 +test(function() { + var el = document.createElement("foo") + assert_throws("NAMESPACE_ERR", + function() { el.setAttributeNS("a", "xmlns:bb", "fail") }) +}, "The xmlns prefix should not be allowed for arbitrary namespaces") +test(function() { + var el = document.createElement("foo") + assert_throws("NAMESPACE_ERR", + function() { el.setAttributeNS("a", "xmlns", "fail") }) +}, "The xmlns qualified name should not be allowed for arbitrary namespaces") +test(function() { + var el = document.createElement("foo") + el.setAttributeNS("ns", "a:xmlns", "pass") + assert_equals(el.attributes.length, 1) + attr_is(el.attributes[0], "pass", "xmlns", "ns", "a", "a:xmlns") +}, "xmlns should be allowed as local name") + +// Step 7 +test(function() { + var el = document.createElement("foo") + assert_throws("NAMESPACE_ERR", + function() { el.setAttributeNS(XMLNS, "a:xmlns", "fail") }) + assert_throws("NAMESPACE_ERR", + function() { el.setAttributeNS(XMLNS, "b:foo", "fail") }) +}, "The XMLNS namespace should require xmlns as prefix or qualified name") +test(function() { + var el = document.createElement("foo") + el.setAttributeNS(XMLNS, "xmlns:a", "pass") + assert_equals(el.attributes.length, 1) + attr_is(el.attributes[0], "pass", "a", XMLNS, "xmlns", "xmlns:a") +}, "xmlns should be allowed as prefix in the XMLNS namespace") +test(function() { + var el = document.createElement("foo") + el.setAttributeNS(XMLNS, "xmlns", "pass") + assert_equals(el.attributes.length, 1) + attr_is(el.attributes[0], "pass", "xmlns", XMLNS, null, "xmlns") +}, "xmlns should be allowed as qualified name in the XMLNS namespace") + +// Step 8-9 +test(function() { + var el = document.createElement("foo") + el.setAttributeNS("a", "foo:bar", "X") + assert_equals(el.attributes.length, 1) + attr_is(el.attributes[0], "X", "bar", "a", "foo", "foo:bar") + + el.setAttributeNS("a", "quux:bar", "Y") + assert_equals(el.attributes.length, 1) + attr_is(el.attributes[0], "Y", "bar", "a", "foo", "foo:bar") + el.removeAttributeNS("a", "bar") +}, "Setting the same attribute with another prefix should not change the prefix") + +// Miscellaneous tests +test(function() { + var el = document.createElement("iframe") + el.setAttribute("src", "file:///home") + assert_equals(el.getAttribute("src"), "file:///home") +}, "setAttribute should not throw even if a load is not allowed") +test(function() { + var docFragment = document.createDocumentFragment() + var newOne = document.createElement("newElement") + newOne.setAttribute("newdomestic", "Yes") + docFragment.appendChild(newOne) + var domesticNode = docFragment.firstChild + var attr = domesticNode.attributes.item(0) + attr_is(attr, "Yes", "newdomestic", null, null, "newdomestic") +}, "Attributes should work in document fragments.") +test(function() { + var el = document.createElement("foo") + el.setAttribute("x", "y") + var attr = el.attributes[0] + attr.value = "Y<" + attr_is(attr, "Y<", "x", null, null, "x") + assert_equals(el.getAttribute("x"), "Y<") +}, "Attribute values should not be parsed.") +test(function() { + var el = document.getElementsByTagName("span")[0] + attr_is(el.attributes[0], "test1", "id", null, null, "id") +}, "Specified attributes should be accessible.") +test(function() { + var el = document.getElementsByTagName("span")[1] + attr_is(el.attributes[0], "&<>foo", "class", null, null, "class") +}, "Entities in attributes should have been expanded while parsing.") + +test(function() { + var el = document.createElement("div") + assert_equals(el.hasAttribute("bar"), false) + assert_equals(el.hasAttributeNS(null, "bar"), false) + assert_equals(el.hasAttributeNS("", "bar"), false) + assert_equals(el.getAttribute("bar"), null) + assert_equals(el.getAttributeNS(null, "bar"), null) + assert_equals(el.getAttributeNS("", "bar"), null) +}, "Unset attributes return null") +test(function() { + var el = document.createElement("div") + el.setAttributeNS("ab", "attr", "t1") + el.setAttributeNS("kl", "attr", "t2") + assert_equals(el.hasAttribute("attr"), true) + assert_equals(el.hasAttributeNS("ab", "attr"), true) + assert_equals(el.hasAttributeNS("kl", "attr"), true) + assert_equals(el.getAttribute("attr"), "t1") + assert_equals(el.getAttributeNS("ab", "attr"), "t1") + assert_equals(el.getAttributeNS("kl", "attr"), "t2") + assert_equals(el.getAttributeNS(null, "attr"), null) + assert_equals(el.getAttributeNS("", "attr"), null) +}, "First set attribute is returned by getAttribute") +test(function() { + var el = document.createElement("div") + el.setAttribute("style", "color:#fff;") + assert_equals(el.hasAttribute("style"), true) + assert_equals(el.hasAttributeNS(null, "style"), true) + assert_equals(el.hasAttributeNS("", "style"), true) + assert_equals(el.getAttribute("style"), "color:#fff;") + assert_equals(el.getAttributeNS(null, "style"), "color:#fff;") + assert_equals(el.getAttributeNS("", "style"), "color:#fff;") +}, "Style attributes are not normalized") +test(function() { + var el = document.createElement("div") + el.setAttributeNS("", "ALIGN", "left") + assert_equals(el.hasAttribute("ALIGN"), false) + assert_equals(el.hasAttribute("align"), false) + assert_equals(el.hasAttributeNS(null, "ALIGN"), true) + assert_equals(el.hasAttributeNS(null, "align"), false) + assert_equals(el.hasAttributeNS("", "ALIGN"), true) + assert_equals(el.hasAttributeNS("", "align"), false) + assert_equals(el.getAttribute("ALIGN"), null) + assert_equals(el.getAttribute("align"), null) + assert_equals(el.getAttributeNS(null, "ALIGN"), "left") + assert_equals(el.getAttributeNS("", "ALIGN"), "left") + assert_equals(el.getAttributeNS(null, "align"), null) + assert_equals(el.getAttributeNS("", "align"), null) + el.removeAttributeNS("", "ALIGN") +}, "Only lowercase attributes are returned on HTML elements (upper case attribute)") +test(function() { + var el = document.createElement("div") + el.setAttributeNS("", "CHEEseCaKe", "tasty") + assert_equals(el.hasAttribute("CHEESECAKE"), false) + assert_equals(el.hasAttribute("CHEEseCaKe"), false) + assert_equals(el.hasAttribute("cheesecake"), false) + assert_equals(el.hasAttributeNS("", "CHEESECAKE"), false) + assert_equals(el.hasAttributeNS("", "CHEEseCaKe"), true) + assert_equals(el.hasAttributeNS("", "cheesecake"), false) + assert_equals(el.hasAttributeNS(null, "CHEESECAKE"), false) + assert_equals(el.hasAttributeNS(null, "CHEEseCaKe"), true) + assert_equals(el.hasAttributeNS(null, "cheesecake"), false) + assert_equals(el.getAttribute("CHEESECAKE"), null) + assert_equals(el.getAttribute("CHEEseCaKe"), null) + assert_equals(el.getAttribute("cheesecake"), null) + assert_equals(el.getAttributeNS(null, "CHEESECAKE"), null) + assert_equals(el.getAttributeNS("", "CHEESECAKE"), null) + assert_equals(el.getAttributeNS(null, "CHEEseCaKe"), "tasty") + assert_equals(el.getAttributeNS("", "CHEEseCaKe"), "tasty") + assert_equals(el.getAttributeNS(null, "cheesecake"), null) + assert_equals(el.getAttributeNS("", "cheesecake"), null) + el.removeAttributeNS("", "CHEEseCaKe") +}, "Only lowercase attributes are returned on HTML elements (mixed case attribute)") +test(function() { + var el = document.createElement("div") + document.body.appendChild(el) + el.setAttributeNS("", "align", "left") + el.setAttributeNS("xx", "align", "right") + el.setAttributeNS("", "foo", "left") + el.setAttributeNS("xx", "foo", "right") + assert_equals(el.hasAttribute("align"), true) + assert_equals(el.hasAttribute("foo"), true) + assert_equals(el.hasAttributeNS("xx", "align"), true) + assert_equals(el.hasAttributeNS(null, "foo"), true) + assert_equals(el.getAttribute("align"), "left") + assert_equals(el.getAttribute("foo"), "left") + assert_equals(el.getAttributeNS("xx", "align"), "right") + assert_equals(el.getAttributeNS(null, "foo"), "left") + assert_equals(el.getAttributeNS("", "foo"), "left") + el.removeAttributeNS("", "align") + el.removeAttributeNS("xx", "align") + el.removeAttributeNS("", "foo") + el.removeAttributeNS("xx", "foo") + document.body.removeChild(el) +}, "First set attribute is returned with mapped attribute set first") +test(function() { + var el = document.createElement("div") + el.setAttributeNS("xx", "align", "right") + el.setAttributeNS("", "align", "left") + el.setAttributeNS("xx", "foo", "right") + el.setAttributeNS("", "foo", "left") + assert_equals(el.hasAttribute("align"), true) + assert_equals(el.hasAttribute("foo"), true) + assert_equals(el.hasAttributeNS("xx", "align"), true) + assert_equals(el.hasAttributeNS(null, "foo"), true) + assert_equals(el.getAttribute("align"), "right") + assert_equals(el.getAttribute("foo"), "right") + assert_equals(el.getAttributeNS("xx", "align"), "right") + assert_equals(el.getAttributeNS(null, "foo"), "left") + assert_equals(el.getAttributeNS("", "foo"), "left") + el.removeAttributeNS("", "align") + el.removeAttributeNS("xx", "align") + el.removeAttributeNS("", "foo") + el.removeAttributeNS("xx", "foo") +}, "First set attribute is returned with mapped attribute set later") + +test(function() { + var el = document.createElementNS("http://www.example.com", "foo") + el.setAttribute("A", "test") + assert_equals(el.hasAttribute("A"), true, "hasAttribute()") + assert_equals(el.hasAttributeNS("", "A"), true, "el.hasAttributeNS(\"\")") + assert_equals(el.hasAttributeNS(null, "A"), true, "el.hasAttributeNS(null)") + assert_equals(el.hasAttributeNS(undefined, "A"), true, "el.hasAttributeNS(undefined)") + assert_equals(el.hasAttributeNS("foo", "A"), false, "el.hasAttributeNS(\"foo\")") + + assert_equals(el.getAttribute("A"), "test", "getAttribute()") + assert_equals(el.getAttributeNS("", "A"), "test", "el.getAttributeNS(\"\")") + assert_equals(el.getAttributeNS(null, "A"), "test", "el.getAttributeNS(null)") + assert_equals(el.getAttributeNS(undefined, "A"), "test", "el.getAttributeNS(undefined)") + assert_equals(el.getAttributeNS("foo", "A"), null, "el.getAttributeNS(\"foo\")") +}, "Non-HTML element with upper-case attribute") + +test(function() { + var el = document.createElement("div") + el.setAttribute("pre:fix", "value 1") + el.setAttribute("fix", "value 2") + + var prefixed = el.attributes[0] + assert_equals(prefixed.localName, "pre:fix", "prefixed local name") + assert_equals(prefixed.namespaceURI, null, "prefixed namespace") + + var unprefixed = el.attributes[1] + assert_equals(unprefixed.localName, "fix", "unprefixed local name") + assert_equals(unprefixed.namespaceURI, null, "unprefixed namespace") + + el.removeAttributeNS(null, "pre:fix") + assert_equals(el.attributes[0], unprefixed) +}, "Attribute with prefix in local name") + +test(function() { + var el = document.createElement("div") + el.setAttribute("foo", "bar") + var attr = el.attributes[0] + assert_equals(attr.ownerElement, el) + el.removeAttribute("foo") + assert_equals(attr.ownerElement, null) +}, "Attribute loses its owner when removed") + +test(function() { + var el = document.createElement("div") + el.setAttribute("foo", "bar") + var attr = el.attributes[0] + var attrNode = el.getAttributeNode("foo"); + var attrNodeNS = el.getAttributeNodeNS("", "foo"); + assert_equals(attr, attrNode); + assert_equals(attr, attrNodeNS); + el.setAttributeNS("x", "foo2", "bar2"); + var attr2 = el.attributes[1]; + var attrNodeNS2 = el.getAttributeNodeNS("x", "foo2"); + assert_equals(attr2, attrNodeNS2); +}, "Basic functionality of getAttributeNode/getAttributeNodeNS") + +test(function() { + var el = document.createElement("div") + el.setAttribute("foo", "bar") + var attrNode = el.getAttributeNode("foo"); + var attrNodeNS = el.getAttributeNodeNS("", "foo"); + assert_equals(attrNode, attrNodeNS); + el.removeAttribute("foo"); + var el2 = document.createElement("div"); + el2.setAttributeNode(attrNode); + assert_equals(attrNode, el2.getAttributeNode("foo")); + assert_equals(attrNode, el2.attributes[0]); + assert_equals(attrNode.ownerElement, el2); + assert_equals(attrNode.value, "bar"); + + var el3 = document.createElement("div"); + el2.removeAttribute("foo"); + el3.setAttribute("foo", "baz"); + el3.setAttributeNode(attrNode); + assert_equals(el3.getAttribute("foo"), "bar"); +}, "Basic functionality of setAttributeNode") + +test(function() { + var el = document.createElement("div") + el.setAttributeNS("x", "foo", "bar") + var attrNode = el.getAttributeNodeNS("x", "foo"); + el.removeAttribute("foo"); + var el2 = document.createElement("div"); + el2.setAttributeNS("x", "foo", "baz"); + el2.setAttributeNodeNS(attrNode); + assert_equals(el2.getAttributeNS("x", "foo"), "bar"); +}, "Basic functionality of setAttributeNodeNS") + +test(function() { + var el = document.createElement("div"); + var other = document.createElement("div"); + attr = document.createAttribute("foo"); + assert_equals(el.setAttributeNode(attr), null); + assert_equals(attr.ownerElement, el); + assert_throws("INUSE_ATTRIBUTE_ERR", + function() { other.setAttributeNode(attr) }, + "Attribute already associated with el") +}, "If attr’s element is neither null nor element, throw an InUseAttributeError."); + +test(function() { + var el = document.createElement("div"); + attr = document.createAttribute("foo"); + assert_equals(el.setAttributeNode(attr), null); + el.setAttribute("bar", "qux"); + assert_equals(el.setAttributeNode(attr), attr); + assert_equals(el.attributes[0], attr); +}, "Replacing an attr by itself"); + +test(function() { + var el = document.createElement("div") + el.setAttribute("foo", "bar") + var attrNode = el.getAttributeNode("foo"); + el.removeAttributeNode(attrNode); + var el2 = document.createElement("div"); + el2.setAttributeNode(attrNode); + assert_equals(el2.attributes[0], attrNode); + assert_equals(el.attributes.length, 0); +}, "Basic functionality of removeAttributeNode") + +test(function() { + var el = document.createElement("div") + el.setAttribute("foo", "bar") + var attrNode = el.getAttributeNode("foo"); + var el2 = document.createElement("div"); + assert_throws("INUSE_ATTRIBUTE_ERR", function(){el2.setAttributeNode(attrNode)}); +}, "setAttributeNode on bound attribute should throw InUseAttributeError") + +// Have to use an async_test to see what a DOMAttrModified listener sees, +// because otherwise the event dispatch code will swallow our exceptions. And +// we want to make sure this test always happens, even when no mutation events +// run. +var setAttributeNode_mutation_test = async_test("setAttributeNode, if it fires mutation events, should fire one with the new node when resetting an existing attribute"); + +test(function(){ + var el = document.createElement("div") + var attrNode1 = document.createAttribute("foo"); + attrNode1.value = "bar"; + el.setAttributeNode(attrNode1); + var attrNode2 = document.createAttribute("foo"); + attrNode2.value = "baz"; + + el.addEventListener("DOMAttrModified", function(e) { + // If this never gets called, that's OK, I guess. But if it gets called, it + // better represent a single modification with attrNode2 as the relatedNode. + // We have to do an inner test() call here, because otherwise the exceptions + // our asserts trigger will get swallowed by the event dispatch code. + setAttributeNode_mutation_test.step(function() { + assert_equals(e.attrName, "foo"); + assert_equals(e.attrChange, MutationEvent.MODIFICATION); + assert_equals(e.prevValue, "bar"); + assert_equals(e.newValue, "baz"); + assert_equals(e.relatedNode, attrNode2); + }); + }); + + var oldNode = el.setAttributeNode(attrNode2); + assert_equals(oldNode, attrNode1, + "Must return the old attr node from a setAttributeNode call"); +}, "setAttributeNode, if it fires mutation events, should fire one with the new node when resetting an existing attribute (outer shell)"); +setAttributeNode_mutation_test.done(); + +test(function(){ + var el = document.createElement("div") + el.setAttribute("a", "b"); + el.setAttribute("c", "d"); + + assert_array_equals(Array.prototype.map.call(el.attributes, function(a) { return a.name }), + ["a", "c"]); + assert_array_equals(Array.prototype.map.call(el.attributes, function(a) { return a.value }), + ["b", "d"]); + + var attrNode = document.createAttribute("a"); + attrNode.value = "e"; + el.setAttributeNode(attrNode); + + assert_array_equals(Array.prototype.map.call(el.attributes, function(a) { return a.name }), + ["a", "c"]); + assert_array_equals(Array.prototype.map.call(el.attributes, function(a) { return a.value }), + ["e", "d"]); +}, "setAttributeNode called with an Attr that has the same name as an existing one should not change attribute order"); + +test(function() { + var el = document.createElement("div"); + el.setAttribute("foo", "bar"); + assert_equals(el.getAttributeNames().length, 1); + assert_equals(el.getAttributeNames()[0], el.attributes[0].name); + assert_equals(el.getAttributeNames()[0], "foo"); + + el.removeAttribute("foo"); + assert_equals(el.getAttributeNames().length, 0); + + el.setAttribute("foo", "bar"); + el.setAttributeNS("", "FOO", "bar"); + el.setAttributeNS("dummy1", "foo", "bar"); + el.setAttributeNS("dummy2", "dummy:foo", "bar"); + assert_equals(el.getAttributeNames().length, 4); + assert_equals(el.getAttributeNames()[0], "foo"); + assert_equals(el.getAttributeNames()[1], "FOO"); + assert_equals(el.getAttributeNames()[2], "foo"); + assert_equals(el.getAttributeNames()[3], "dummy:foo"); + assert_equals(el.getAttributeNames()[0], el.attributes[0].name); + assert_equals(el.getAttributeNames()[1], el.attributes[1].name); + assert_equals(el.getAttributeNames()[2], el.attributes[2].name); + assert_equals(el.getAttributeNames()[3], el.attributes[3].name); + + el.removeAttributeNS("", "FOO"); + assert_equals(el.getAttributeNames().length, 3); + assert_equals(el.getAttributeNames()[0], "foo"); + assert_equals(el.getAttributeNames()[1], "foo"); + assert_equals(el.getAttributeNames()[2], "dummy:foo"); + assert_equals(el.getAttributeNames()[0], el.attributes[0].name); + assert_equals(el.getAttributeNames()[1], el.attributes[1].name); + assert_equals(el.getAttributeNames()[2], el.attributes[2].name); +}, "getAttributeNames tests"); + +function getEnumerableOwnProps1(obj) { + var arr = []; + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + arr.push(prop); + } + } + return arr; +} + +function getEnumerableOwnProps2(obj) { + return Object.getOwnPropertyNames(obj).filter( + function (name) { return Object.getOwnPropertyDescriptor(obj, name).enumerable; }) +} + +test(function() { + var el = document.createElement("div"); + el.setAttribute("a", ""); + el.setAttribute("b", ""); + assert_array_equals(getEnumerableOwnProps1(el.attributes), + ["0", "1"]) + assert_array_equals(getEnumerableOwnProps2(el.attributes), + ["0", "1"]) + assert_array_equals(Object.getOwnPropertyNames(el.attributes), + ["0", "1", "a", "b"]) +}, "Own property correctness with basic attributes"); + +test(function() { + var el = document.createElement("div"); + el.setAttributeNS("", "a", ""); + el.setAttribute("b", ""); + el.setAttributeNS("foo", "a", ""); + assert_array_equals(getEnumerableOwnProps1(el.attributes), + ["0", "1", "2"]) + assert_array_equals(getEnumerableOwnProps2(el.attributes), + ["0", "1", "2"]) + assert_array_equals(Object.getOwnPropertyNames(el.attributes), + ["0", "1", "2", "a", "b"]) + for (var propName of Object.getOwnPropertyNames(el.attributes)) { + assert_true(el.attributes[propName] instanceof Attr, + "el.attributes has an Attr for property name " + propName); + } +}, "Own property correctness with non-namespaced attribute before same-name namespaced one"); + +test(function() { + var el = document.createElement("div"); + el.setAttributeNS("foo", "a", ""); + el.setAttribute("b", ""); + el.setAttributeNS("", "a", ""); + assert_array_equals(getEnumerableOwnProps1(el.attributes), + ["0", "1", "2"]) + assert_array_equals(getEnumerableOwnProps2(el.attributes), + ["0", "1", "2"]) + assert_array_equals(Object.getOwnPropertyNames(el.attributes), + ["0", "1", "2", "a", "b"]) + for (var propName of Object.getOwnPropertyNames(el.attributes)) { + assert_true(el.attributes[propName] instanceof Attr, + "el.attributes has an Attr for property name " + propName); + } +}, "Own property correctness with namespaced attribute before same-name non-namespaced one"); + +test(function() { + var el = document.createElement("div"); + el.setAttributeNS("foo", "a:b", ""); + el.setAttributeNS("foo", "c:d", ""); + el.setAttributeNS("bar", "a:b", ""); + assert_array_equals(getEnumerableOwnProps1(el.attributes), + ["0", "1", "2"]) + assert_array_equals(getEnumerableOwnProps2(el.attributes), + ["0", "1", "2"]) + assert_array_equals(Object.getOwnPropertyNames(el.attributes), + ["0", "1", "2", "a:b", "c:d"]) + for (var propName of Object.getOwnPropertyNames(el.attributes)) { + assert_true(el.attributes[propName] instanceof Attr, + "el.attributes has an Attr for property name " + propName); + } +}, "Own property correctness with two namespaced attributes with the same name-with-prefix"); + +test(function() { + var el = document.createElement("div"); + el.setAttributeNS("foo", "A:B", ""); + el.setAttributeNS("bar", "c:D", ""); + el.setAttributeNS("baz", "e:F", ""); + el.setAttributeNS("qux", "g:h", ""); + el.setAttributeNS("", "I", ""); + el.setAttributeNS("", "j", ""); + assert_array_equals(Object.getOwnPropertyNames(el.attributes), + ["0", "1", "2", "3", "4", "5", "g:h", "j"]) + for (var propName of Object.getOwnPropertyNames(el.attributes)) { + assert_true(el.attributes[propName] instanceof Attr, + "el.attributes has an Attr for property name " + propName); + } +}, "Own property names should only include all-lowercase qualified names for an HTML element in an HTML document"); + +test(function() { + var el = document.createElementNS("", "div"); + el.setAttributeNS("foo", "A:B", ""); + el.setAttributeNS("bar", "c:D", ""); + el.setAttributeNS("baz", "e:F", ""); + el.setAttributeNS("qux", "g:h", ""); + el.setAttributeNS("", "I", ""); + el.setAttributeNS("", "j", ""); + assert_array_equals(Object.getOwnPropertyNames(el.attributes), + ["0", "1", "2", "3", "4", "5", "A:B", "c:D", "e:F", "g:h", "I", "j"]) + for (var propName of Object.getOwnPropertyNames(el.attributes)) { + assert_true(el.attributes[propName] instanceof Attr, + "el.attributes has an Attr for property name " + propName); + } +}, "Own property names should include all qualified names for a non-HTML element in an HTML document"); + +test(function() { + var doc = document.implementation.createDocument(null, ""); + assert_equals(doc.contentType, "application/xml"); + var el = doc.createElementNS("http://www.w3.org/1999/xhtml", "div"); + el.setAttributeNS("foo", "A:B", ""); + el.setAttributeNS("bar", "c:D", ""); + el.setAttributeNS("baz", "e:F", ""); + el.setAttributeNS("qux", "g:h", ""); + el.setAttributeNS("", "I", ""); + el.setAttributeNS("", "j", ""); + assert_array_equals(Object.getOwnPropertyNames(el.attributes), + ["0", "1", "2", "3", "4", "5", "A:B", "c:D", "e:F", "g:h", "I", "j"]) + for (var propName of Object.getOwnPropertyNames(el.attributes)) { + assert_true(el.attributes[propName] instanceof Attr, + "el.attributes has an Attr for property name " + propName); + } +}, "Own property names should include all qualified names for an HTML element in a non-HTML document"); +</script> diff --git a/testing/web-platform/tests/dom/nodes/attributes.js b/testing/web-platform/tests/dom/nodes/attributes.js new file mode 100644 index 000000000..ef32bf6a6 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/attributes.js @@ -0,0 +1,18 @@ +function attr_is(attr, v, ln, ns, p, n) { + assert_equals(attr.value, v) + assert_equals(attr.nodeValue, v) + assert_equals(attr.textContent, v) + assert_equals(attr.localName, ln) + assert_equals(attr.namespaceURI, ns) + assert_equals(attr.prefix, p) + assert_equals(attr.name, n) + assert_equals(attr.nodeName, n); + assert_equals(attr.specified, true) +} + +function attributes_are(el, l) { + for (var i = 0, il = l.length; i < il; i++) { + attr_is(el.attributes[i], l[i][1], l[i][0], (l[i].length < 3) ? null : l[i][2], null, l[i][0]) + assert_equals(el.attributes[i].ownerElement, el) + } +} diff --git a/testing/web-platform/tests/dom/nodes/case.html b/testing/web-platform/tests/dom/nodes/case.html new file mode 100644 index 000000000..c3c195141 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/case.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Tests for case-sensitivity in APIs</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createelement"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createelementns"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-getelementsbytagname"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-getelementsbytagnamens"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-element-setattribute"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-element-setattributens"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-element-hasattribute"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-element-hasattributens"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-element-getelementsbytagname"> +<link rel=help href="https://dom.spec.whatwg.org/#dom-element-getelementsbytagnamens"> +<script>var is_html = true;</script> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="case.js"></script> +<div id="log"></div> diff --git a/testing/web-platform/tests/dom/nodes/case.js b/testing/web-platform/tests/dom/nodes/case.js new file mode 100644 index 000000000..8c2da4a44 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/case.js @@ -0,0 +1,186 @@ +/* + * document.createElement(NS) + * + * document.getElementsByTagName(NS) + * + * Element.setAttribute(NS) + * + * Element.getAttribute(NS) + * Element.hasAttribute(NS) + * Element.getElementsByTagName(NS) + */ + +var tests = []; +setup(function() { + var name_inputs = ["abc", "Abc", "ABC", "ä", "Ä"]; + var namespaces = ["http://www.w3.org/1999/xhtml", "http://www.w3.org/2000/svg", "http://FOO"]; + name_inputs.forEach(function(x) { + tests.push(["createElement " + x, test_create_element, [x]]); + tests.push(["setAttribute " +x, test_set_attribute, [x]]); + tests.push(["getAttribute " +x, test_get_attribute, [x]]); + tests.push(["getElementsByTagName a:" +x, test_get_elements_tag_name, + [outer_product(namespaces, ["a"], name_inputs), + x]]); + tests.push(["getElementsByTagName " +x, test_get_elements_tag_name, + [outer_product(namespaces, [null], name_inputs), + x]]); + }); + outer_product(namespaces, name_inputs, name_inputs).forEach(function(x) { + tests.push(["createElementNS " + x, test_create_element_ns, x]); + tests.push(["setAttributeNS " + x, test_set_attribute_ns, x]); + tests.push(["getAttributeNS " + x, test_get_attribute_ns, x]); + }); + outer_product([null].concat(namespaces), name_inputs).forEach(function(x) { + tests.push(["getElementsByTagNameNS " + x, test_get_elements_tag_name_ns, + outer_product(namespaces, name_inputs), x]); + }); + name_inputs.forEach(function(x) { + tests.push(["createElementNS " + x, test_create_element_ns, [null, null, x]]); + tests.push(["setAttributeNS " + x, test_set_attribute_ns, [null, null, x]]); + tests.push(["getAttributeNS " + x, test_get_attribute_ns, [null, null, x]]); + }); + + }); +function outer_product() { + var rv = []; + function compute_outer_product() { + var args = Array.prototype.slice.call(arguments); + var index = args[0]; + if (index < args.length) { + args[index].forEach(function(x) { + compute_outer_product.apply(this, [index+1].concat(args.slice(1, index), x, args.slice(index+1))); + }); + } else { + rv.push(args.slice(1)); + } + } + compute_outer_product.apply(this, [1].concat(Array.prototype.slice.call(arguments))); + return rv; +} + +function expected_case(input) { + //is_html gets set by a global on the page loading the tests + if (is_html) { + return ascii_lowercase(input); + } else { + return input; + } +} + +function ascii_lowercase(input) { + return input.replace(/[A-Z]/g, function(x) { + return x.toLowerCase(); + }); +} + +function get_qualified_name(el) { + if (el.prefix) { + return el.prefix + ":" + el.localName; + } + return el.localName; +} + +function test_create_element(name) { + var node = document.createElement(name); + assert_equals(node.localName, expected_case(name)); +} + +function test_create_element_ns(namespace, prefix, local_name) { + var qualified_name = prefix ? prefix + ":" + local_name : local_name; + var node = document.createElementNS(namespace, qualified_name); + assert_equals(node.prefix, prefix, "prefix"); + assert_equals(node.localName, local_name, "localName"); +} + +function test_set_attribute(name) { + var node = document.createElement("div"); + node.setAttribute(name, "test"); + assert_equals(node.attributes[0].localName, expected_case(name)); +} + +function test_set_attribute_ns(namespace, prefix, local_name) { + var qualified_name = prefix ? prefix + ":" + local_name : local_name; + var node = document.createElement("div"); + node.setAttributeNS(namespace, qualified_name, "test"); + var attr = node.attributes[0]; + assert_equals(attr.prefix, prefix, "prefix"); + assert_equals(attr.localName, local_name, "localName"); +} + +function test_get_attribute(name) { + var node = document.createElement("div"); + node.setAttribute(name, "test"); + var expected_name = expected_case(name); + assert_equals(node.getAttribute(expected_name), "test"); + if (expected_name != name) { + assert_equals(node.getAttribute(expected_name), "test"); + } else if (name !== ascii_lowercase(name)) { + assert_equals(node.getAttribute(ascii_lowercase(name)), null); + } +} + +function test_get_attribute_ns(namespace, prefix, local_name) { + var qualified_name = prefix ? prefix + ":" + local_name : local_name; + var node = document.createElement("div"); + node.setAttributeNS(namespace, qualified_name, "test"); + var expected_name = local_name; + assert_equals(node.getAttributeNS(namespace, expected_name), "test"); + if (local_name !== ascii_lowercase(local_name)) { + assert_equals(node.getAttributeNS(namespace, ascii_lowercase(local_name)), null); + } +} + +function test_get_elements_tag_name(elements_to_create, search_string) { + var container = document.createElement("div"); + elements_to_create.forEach(function(x) { + var qualified_name = x[1] ? x[1] + ":" + x[2] : x[2]; + var element = document.createElementNS(x[0], qualified_name); + container.appendChild(element); + }); + var expected = Array.prototype.filter.call(container.childNodes, + function(node) { + if (is_html && node.namespaceURI === "http://www.w3.org/1999/xhtml") { + return get_qualified_name(node) === expected_case(search_string); + } else { + return get_qualified_name(node) === search_string; + } + }); + document.documentElement.appendChild(container); + try { + assert_array_equals(document.getElementsByTagName(search_string), expected); + } finally { + document.documentElement.removeChild(container); + } +} + +function test_get_elements_tag_name_ns(elements_to_create, search_input) { + var search_uri = search_input[0]; + var search_name = search_input[1]; + var container = document.createElement("div"); + elements_to_create.forEach(function(x) { + var qualified_name = x[1] ? x[1] + ":" + x[2] : x[2]; + var element = document.createElementNS(x[0], qualified_name); + container.appendChild(element); + }); + var expected = Array.prototype.filter.call(container.childNodes, + function(node) { + return node.namespaceURI === search_uri; + return node.localName === search_name; + }); + document.documentElement.appendChild(container); + try { + assert_array_equals(document.getElementsByTagNameNS(search_uri, search_name), expected); + } catch(e) { + throw e; + } finally { + document.documentElement.removeChild(container); + } +} + +function test_func() { + var func = arguments[0]; + var rest = arguments[1]; + func.apply(this, rest); +} + +generate_tests(test_func, tests); diff --git a/testing/web-platform/tests/dom/nodes/creators.js b/testing/web-platform/tests/dom/nodes/creators.js new file mode 100644 index 000000000..8b7415d13 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/creators.js @@ -0,0 +1,5 @@ +var creators = { + "element": "createElement", + "text": "createTextNode", + "comment": "createComment" +}; diff --git a/testing/web-platform/tests/dom/nodes/encoding.py b/testing/web-platform/tests/dom/nodes/encoding.py new file mode 100644 index 000000000..5f889e8db --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/encoding.py @@ -0,0 +1,5 @@ +from cgi import escape + +def main(request, response): + label = request.GET.first('label') + return """<!doctype html><meta charset="%s">""" % escape(label) diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-01.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-01.htm new file mode 100644 index 000000000..457d6c400 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-01.htm @@ -0,0 +1,13 @@ +<!doctype html> +<html class="a"> + <head> + <title>document.getElementsByClassName(): simple</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body class="a"> + <div id="log"></div> + <script> test(function() {assert_array_equals(document.getElementsByClassName("\ta\n"), + [document.documentElement, document.body])}) </script> + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-02.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-02.htm new file mode 100644 index 000000000..d5e513fa8 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-02.htm @@ -0,0 +1,14 @@ +<!doctype html> +<html class="a +b"> + <head> + <title>document.getElementsByClassName(): also simple</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body class="a +"> + <div id="log"></div> + <script> test(function() {assert_array_equals(document.getElementsByClassName("a\n"), [document.documentElement, document.body])}) </script> + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-03.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-03.htm new file mode 100644 index 000000000..a9e2d3af1 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-03.htm @@ -0,0 +1,18 @@ +<!doctype html> +<html class="a"> + <head> + <title>document.getElementsByClassName(): changing classes</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body class="a"> + <div id="log"></div> + <script> + test(function() { + var collection = document.getElementsByClassName("a") + document.body.className = "b" + assert_array_equals(collection, [document.documentElement]) + }) + </script> + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-04.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-04.htm new file mode 100644 index 000000000..0c62fed2c --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-04.htm @@ -0,0 +1,18 @@ +<!doctype html> +<html class="a"> + <head> + <title>document.getElementsByClassName(): changing classes</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body class="a"> + <div id="log"></div> + <script> + test(function() { + var collection = document.getElementsByClassName("a"); + document.body.className += "\tb"; + assert_array_equals(collection, [document.documentElement, document.body]); + }) + </script> + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-05.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-05.htm new file mode 100644 index 000000000..98245f642 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-05.htm @@ -0,0 +1,18 @@ +<!doctype html> +<html class="a"> + <head> + <title>document.getElementsByClassName(): changing classes</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body class="a"> + <div id="log"></div> + <script> + test(function() { + var collection = document.getElementsByClassName("a"); + document.body.removeAttribute("class"); + assert_array_equals(collection, [document.documentElement]); + }) + </script> + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-06.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-06.htm new file mode 100644 index 000000000..4975a89e0 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-06.htm @@ -0,0 +1,20 @@ +<!doctype html> +<html> + <head> + <title>document.getElementsByClassName(): adding element with class</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body class="a"> + <div id="log"></div> + <script> + test(function() { + var collection = document.getElementsByClassName("a"); + var ele = document.createElement("foo"); + ele.setAttribute("class", "a"); + document.body.appendChild(ele); + assert_array_equals(collection, [document.body, ele]); + }) + </script> + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-07.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-07.htm new file mode 100644 index 000000000..b0102fb2e --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-07.htm @@ -0,0 +1,15 @@ +<!doctype html> +<html> + <head> + <title>document.getElementsByClassName(): multiple classes</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body class="a b"> + <div id="log"></div> + <script> test(function() { + assert_array_equals(document.getElementsByClassName("b\t\f\n\na\rb"), [document.body]); + }) + </script> + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-08.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-08.htm new file mode 100644 index 000000000..a248af492 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-08.htm @@ -0,0 +1,15 @@ +<!doctype html> +<html> + <head> + <title>document.getElementsByClassName(): multiple classes</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body class="a"> + <div id="log"></div> + <script> test(function() { + document.getElementsByClassName("a\fa"), [document.body] + }) + </script> + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-09.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-09.htm new file mode 100644 index 000000000..9011f3068 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-09.htm @@ -0,0 +1,15 @@ +<!doctype html> +<html class="a A"> + <head> + <title>document.getElementsByClassName(): case sensitive</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body class="a a"> + <div id="log"></div> + <script>test(function() { + assert_array_equals(document.getElementsByClassName("A a"), [document.documentElement]) + }) + </script> + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-10.xml b/testing/web-platform/tests/dom/nodes/getElementsByClassName-10.xml new file mode 100644 index 000000000..b3e3122cb --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-10.xml @@ -0,0 +1,19 @@ +<html xmlns="http://www.w3.org/1999/xhtml" xmlns:g="http://www.w3.org/2000/svg"> + <head> + <title>document.getElementsByClassName(): compound</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"/> + <div id="tests"> + <x class="a"/> + <g:x class="a"/> + </div> + <script>test(function() { + assert_array_equals(document.getElementsByClassName("a"), + document.getElementById("tests").children); + }) + </script> + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-11.xml b/testing/web-platform/tests/dom/nodes/getElementsByClassName-11.xml new file mode 100644 index 000000000..8593fa7a0 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-11.xml @@ -0,0 +1,24 @@ +<html xmlns="http://www.w3.org/1999/xhtml" xmlns:g="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:t="http://tc.labs.opera.com/#test"> + <head> + <title>document.getElementsByClassName(): "tricky" compound</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log" /> + <div id="tests"> + <x class="a"/> + <g:x class="a"/> + <x t:class="a" h:class="a" g:class="a"/> + <g:x t:class="a" h:class="a" g:class="a"/> + <t:x class="a" t:class="a" h:class="a" g:class="a"/> + </div> + <script> + test(function() { + var collection = document.getElementsByClassName("a"); + var test = document.getElementById("tests").children; + assert_array_equals(collection, [test[0], test[1], test[4]]); + }) + </script> + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-12.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-12.htm new file mode 100644 index 000000000..3b7f328b4 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-12.htm @@ -0,0 +1,15 @@ +<!doctype html> +<html class="a"> + <head> + <title>element.getElementsByClassName(): simple</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body class="a"> + <div id="log"></div> + <script>test(function() { + assert_array_equals(document.body.getElementsByClassName("a"), []) + }) + </script> + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-13.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-13.htm new file mode 100644 index 000000000..f3af106ae --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-13.htm @@ -0,0 +1,19 @@ +<!doctype html> +<html class="a"> + <head> + <title>element.getElementsByClassName(): adding an element</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body class="a"> + <div id="log"></div> + <script>test(function() { + var collection = document.body.getElementsByClassName("a"); + var ele = document.createElement("x-y-z"); + ele.className = "a"; + document.body.appendChild(ele); + assert_array_equals(collection, [ele]); + }) + </script> + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-14.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-14.htm new file mode 100644 index 000000000..77de16298 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-14.htm @@ -0,0 +1,16 @@ +<!-- quirks mode --> +<html class="a A"> + <head> + <title>document.getElementsByClassName(): case-insensitive (quirks mode)</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body class="a a"> + <div id="log"></div> + <script>test(function() { + assert_array_equals(document.getElementsByClassName("A a"), + [document.documentElement, document.body]); + }) + </script> + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-15.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-15.htm new file mode 100644 index 000000000..89614de30 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-15.htm @@ -0,0 +1,18 @@ +<!doctype html> +<html class="a +b"> + <head> + <title>document.getElementsByClassName(array): "a\n"</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body class="a +"> + <div id="log"></div> + <script>test(function () { + assert_array_equals(document.getElementsByClassName(["a\n"]), + [document.documentElement, document.body]); + }) + </script> + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-16.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-16.htm new file mode 100644 index 000000000..3f987a7ae --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-16.htm @@ -0,0 +1,16 @@ +<!doctype html> +<html class="a +b"> + <head> + <title>document.getElementsByClassName(array): "b","a"</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body class="b,a"> + <div id="log"></div> + <script>test(function() { + assert_array_equals(document.getElementsByClassName(["b", "a"]), [document.body]); + }) + </script> + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-17.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-17.htm new file mode 100644 index 000000000..ae5ebda6e --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-17.htm @@ -0,0 +1,15 @@ +<!doctype html> +<html> + <head> + <title>document.getElementsByClassName(array): "b a"</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body class="a b"> + <div id="log"></div> + <script>test(function() { + assert_array_equals(document.getElementsByClassName(["b a"]), [document.body]); + }) + </script> + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-18.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-18.htm new file mode 100644 index 000000000..9f6cf75a5 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-18.htm @@ -0,0 +1,17 @@ +<!doctype html> +<html class="a,b"> + <head> + <title>element.getElementsByClassName(array): "a", "b"</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body class="a,b x"> + <div id="log"></div> + <p id="r" class="a,bx"></p> + <script class="xa,b">test(function() { + assert_array_equals(document.documentElement.getElementsByClassName(["\fa","b\n"]), + [document.body]) + }) + </script> + </body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-19.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-19.htm new file mode 100644 index 000000000..da233c743 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-19.htm @@ -0,0 +1,54 @@ +<!DOCTYPE html> +<html><head> + <title>getElementsByClassName</title> + <meta content="get elements in document" name="description"> + <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> + <body> + <div id="log"></div> + <div> + <div> + <a class="text link" href="#foo">test link #foo</a> + </div> + <b class="text">text</b> + </div> + <table> + <caption class="text caption">text caption</caption> + <thead> + <tr> + <td class="TEXT head">TEXT head</td> + </tr> + </thead> + <tbody> + <tr> + <td class="td text1">td text1</td> + </tr> + <tr> + <td class="td text">td text</td> + </tr> + <tr> + <td class="td te xt">td te xt</td> + </tr> + </tbody> + <tfoot> + <tr> + <td class="TEXT foot">TEXT foot</td> + </tr> + </tfoot> + </table> + <div class="xt te">xt te</div> + + <script type="text/javascript"> + test(function () + { + var collection = document.getElementsByClassName("text"); + assert_equals(collection.length, 4); + assert_equals(collection[0].parentNode.nodeName, "DIV"); + assert_equals(collection[1].parentNode.nodeName, "DIV"); + assert_equals(collection[2].parentNode.nodeName, "TABLE"); + assert_equals(collection[3].parentNode.nodeName, "TR"); + }, "get elements in document"); + </script> +</body></html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-20.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-20.htm new file mode 100644 index 000000000..6429e37bb --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-20.htm @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<html><head> + <title>getElementsByClassName</title> + <meta content="get elements in document then add element to collection" name="description"> + <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> + <body> + <div id="log"></div> + <div> + <div> + <a class="text link" href="#foo">test link #foo</a> + </div> + <b class="text">text</b> + </div> + <table> + <caption class="text caption">text caption</caption> + <thead> + <tr> + <td class="TEXT head">TEXT head</td> + </tr> + </thead> + <tbody> + <tr> + <td class="td text1">td text1</td> + </tr> + <tr> + <td class="td text">td text</td> + </tr> + <tr> + <td class="td te xt">td te xt</td> + </tr> + </tbody> + <tfoot> + <tr> + <td class="TEXT foot">TEXT foot</td> + </tr> + </tfoot> + </table> + <div class="xt te">xt te</div> + + <script type="text/javascript"> + test(function() + { + var collection = document.getElementsByClassName("text"); + assert_equals(collection.length, 4); + var newDiv = document.createElement("div"); + newDiv.setAttribute("class", "text"); + newDiv.innerHTML = "text newDiv"; + document.getElementsByTagName("table")[0].tBodies[0].rows[0].cells[0].appendChild(newDiv); + + assert_equals(collection.length, 5); + assert_equals(collection[0].parentNode.nodeName, "DIV"); + assert_equals(collection[1].parentNode.nodeName, "DIV"); + assert_equals(collection[2].parentNode.nodeName, "TABLE"); + assert_equals(collection[3].parentNode.nodeName, "TD"); + assert_equals(collection[4].parentNode.nodeName, "TR"); + }, "get elements in document then add element to collection"); + </script> +</body></html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-21.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-21.htm new file mode 100644 index 000000000..339ff2d3e --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-21.htm @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<html><head> + <title>getElementsByClassName</title> + <meta content="delete element from collection" name="description"> + <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> + <body> + <div id="log"></div> + <div> + <div> + <a class="text link" href="#foo">test link #foo</a> + </div> + <b class="text">text</b> + </div> + <table> + <caption class="text caption">text caption</caption> + <thead> + <tr> + <td class="TEXT head">TEXT head</td> + </tr> + </thead> + <tbody> + <tr> + <td class="td text1">td text1</td> + </tr> + <tr> + <td class="td text">td text</td> + </tr> + <tr> + <td class="td te xt">td te xt</td> + </tr> + </tbody> + <tfoot> + <tr> + <td class="TEXT foot">TEXT foot</td> + </tr> + </tfoot> + </table> + <div class="xt te">xt te</div> + + <script type="text/javascript"> + test(function() + { + var collection = document.getElementsByClassName("text1"); + assert_equals(collection.length, 1) + document.getElementsByTagName("table")[0].deleteRow(1); + assert_equals(collection.length, 0); + }, "delete element from collection"); + </script> +</body></html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-22.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-22.htm new file mode 100644 index 000000000..c20396700 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-22.htm @@ -0,0 +1,58 @@ +<!DOCTYPE html> +<html><head> + <title>getElementsByClassName</title> + <meta content="move item in collection order" name="description"> + <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> + <body> + <div id="log"></div> + <div> + <div> + <a class="text link" href="#foo">test link #foo</a> + </div> + <b class="text">text</b> + </div> + <table> + <caption class="text caption">text caption</caption> + <thead> + <tr> + <td class="TEXT head">TEXT head</td> + </tr> + </thead> + <tbody> + <tr> + <td class="td text1">td text1</td> + </tr> + <tr> + <td class="td text">td text</td> + </tr> + <tr> + <td class="td te xt">td te xt</td> + </tr> + </tbody> + <tfoot> + <tr> + <td class="TEXT foot">TEXT foot</td> + </tr> + </tfoot> + </table> + <div class="xt te">xt te</div> + + <script type="text/javascript"> + test(function() + { + var collection = document.getElementsByClassName("text"); + assert_equals(collection.length, 4); + var boldText = document.getElementsByTagName("b")[0]; + document.getElementsByTagName("table")[0].tBodies[0].rows[0].cells[0].appendChild(boldText); + + assert_equals(collection.length, 4); + assert_equals(collection[0].parentNode.nodeName, "DIV"); + assert_equals(collection[1].parentNode.nodeName, "TABLE"); + assert_equals(collection[2].parentNode.nodeName, "TD"); + assert_equals(collection[3].parentNode.nodeName, "TR"); + }, "move item in collection order"); + </script> +</body></html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-23.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-23.htm new file mode 100644 index 000000000..0af8a0995 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-23.htm @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<html><head> + <title>getElementsByClassName</title> + <meta content="multiple defined classes" name="description"> + <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> + <body> + <div id="log"></div> + <div> + <div> + <a class="text link" href="#foo">test link #foo</a> + </div> + <b class="text">text</b> + </div> + <table> + <caption class="text caption">text caption</caption> + <thead> + <tr> + <td class="TEXT head">TEXT head</td> + </tr> + </thead> + <tbody> + <tr> + <td class="td text1">td text1</td> + </tr> + <tr> + <td class="td text">td text</td> + </tr> + <tr> + <td class="td te xt">td te xt</td> + </tr> + </tbody> + <tfoot> + <tr> + <td class="TEXT foot">TEXT foot</td> + </tr> + </tfoot> + </table> + <div class="xt te">xt te</div> + + <script type="text/javascript"> + test(function() + { + var collection = document.getElementsByClassName("te xt"); + assert_equals(collection.length, 2); + assert_equals(collection[0].parentNode.nodeName, "TR"); + assert_equals(collection[1].parentNode.nodeName, "BODY"); + }, "multiple defined classes"); + </script> +</body></html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-24.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-24.htm new file mode 100644 index 000000000..838987ad0 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-24.htm @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <meta charset='utf-8'> + <title>getElementsByClassName</title> + <meta content="handle unicode chars" name="description"> + <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> + <body> + <div id="log"></div> + <div> + <div> + <a class="ΔЙあ叶葉 말 link" href="#foo">ΔЙあ叶葉 말 link</a> + </div> + <b class="text">text</b> + </div> + <div class="ΔЙあ叶葉 קم">ΔЙあ叶葉 קم</div> + + <script type="text/javascript"> + test(function() + { + var collection = document.getElementsByClassName("ΔЙあ叶葉"); + assert_equals(collection.length, 2); + assert_equals(collection[0].parentNode.nodeName, "DIV"); + assert_equals(collection[1].parentNode.nodeName, "BODY"); + }, "handle unicode chars"); + </script> + +</body></html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-25.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-25.htm new file mode 100644 index 000000000..21f2a9ff7 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-25.htm @@ -0,0 +1,57 @@ +<!DOCTYPE html> +<html><head> + <title>getElementsByClassName</title> + <meta content="verify spacing is handled correctly" name="description"> + <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> + <body> + <div id="log"></div> + <div> + <div> + <a class="text link" href="#foo">test link #foo</a> + </div> + <b class="text">text</b> + </div> + <table> + <caption class="text caption">text caption</caption> + <thead> + <tr> + <td class="TEXT head">TEXT head</td> + </tr> + </thead> + <tbody> + <tr> + <td class="td text1">td text1</td> + </tr> + <tr> + <td class="td text">td text</td> + </tr> + <tr> + <td class="td te xt">td te xt</td> + </tr> + </tbody> + <tfoot> + <tr> + <td class="TEXT foot">TEXT foot</td> + </tr> + </tfoot> + </table> + <div class="xt te">xt te</div> + + <script type="text/javascript"> + test(function() + { + var collection = document.getElementsByClassName("text "); + assert_equals(collection.length, 4); + var boldText = document.getElementsByTagName("b")[0]; + document.getElementsByTagName("table")[0].tBodies[0].rows[0].cells[0].appendChild(boldText); + assert_equals(collection.length, 4); + assert_equals(collection[0].parentNode.nodeName, "DIV"); + assert_equals(collection[1].parentNode.nodeName, "TABLE"); + assert_equals(collection[2].parentNode.nodeName, "TD"); + assert_equals(collection[3].parentNode.nodeName, "TR"); + }, "verify spacing is handled correctly"); + </script> +</body></html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-26.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-26.htm new file mode 100644 index 000000000..0d7ff1ba1 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-26.htm @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <title>getElementsByClassName</title> + <meta content="multiple class attributes" name="description"> + <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> + <body> + <div id="log"></div> + <div class="te xt"> + te xt + <div class="te"> + te; xt + <a class="text link" href="#foo">test link #foo</a> + </div> + <b class="text">text</b> + </div> + <div class="xt te">xt te</div> + <script type="text/javascript"> + test(function() + { + var collection = document.getElementsByClassName("te xt"); + + assert_equals(collection.length, 2); + assert_equals(collection[0].parentNode.nodeName, "BODY"); + assert_equals(collection[1].parentNode.nodeName, "BODY"); + }, "multiple class attributes"); + </script> +</body></html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-27.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-27.htm new file mode 100644 index 000000000..95fc67442 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-27.htm @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html><head> + <title>getElementsByClassName</title> + <meta content="generic element listed" name="description"> + <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> + <body> + <div id="log"></div> + <div class="te xt"> + te xt + <div class="te"> + te; xt + <a class="text link" href="#foo">test link #foo</a> + <foo class="te xt">dummy tag</foo> + </div> + <b class="text">text</b> + </div> + <div class="xt te">xt te</div> + <script type="text/javascript"> + test(function() + { + var collection = document.getElementsByClassName("te xt"); + + assert_equals(collection.length, 3); + assert_equals(collection[0].parentNode.nodeName, "BODY"); + assert_equals(collection[1].parentNode.nodeName, "DIV"); + assert_equals(collection[2].parentNode.nodeName, "BODY"); + }, "generic element listed"); + </script> +</body></html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-28.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-28.htm new file mode 100644 index 000000000..1fc94d807 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-28.htm @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html><head> + <title>getElementsByClassName</title> + <meta content="generic element listed" name="description"> + <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> + <body> + <div id="log"></div> + <div class="te xt"> + te xt + <div class="te"> + te; xt + <a class="text link" href="#foo">test link #foo</a> + <fooU00003Abar class="te xt namespace">te xt namespace + </fooU00003Abar></div> + <b class="text">text</b> + </div> + <div class="xt te">xt te</div> + <script type="text/javascript"> + test(function() + { + var collection = document.getElementsByClassName("te xt"); + assert_equals(collection.length, 3); + assert_equals(collection[0].parentNode.nodeName, "BODY"); + assert_equals(collection[1].parentNode.nodeName, "DIV"); + assert_equals(collection[2].parentNode.nodeName, "BODY"); + }, "generic element listed"); + </script> +</body></html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-29.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-29.htm new file mode 100644 index 000000000..ad489752c --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-29.htm @@ -0,0 +1,51 @@ +<!DOCTYPE html> +<html><head> + <title>getElementsByClassName</title> + <meta content="get class from children of element" name="description"> + <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> + <body> + <div id='log'></div> + <div> + <div> + <a class="text link" href="#foo">test link #foo</a> + </div> + <b class="text">text</b> + </div> + <table> + <caption class="text caption">text caption</caption> + <thead> + <tr> + <td class="TEXT head">TEXT head</td> + </tr> + </thead> + <tbody> + <tr> + <td class="td text1">td text1</td> + </tr> + <tr> + <td class="td text">td text</td> + </tr> + <tr> + <td class="td te xt">td te xt</td> + </tr> + </tbody> + <tfoot> + <tr> + <td class="TEXT foot">TEXT foot</td> + </tr> + </tfoot> + </table> + <div class="xt te">xt te</div> + + <script type="text/javascript"> + test(function() + { + var collection = document.getElementsByTagName("table")[0].getElementsByClassName("te xt"); + assert_equals(collection.length, 1); + assert_equals(collection[0].parentNode.nodeName, "TR"); + }, "get class from children of element"); + </script> +</body></html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-30.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-30.htm new file mode 100644 index 000000000..c0b4faf2d --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-30.htm @@ -0,0 +1,190 @@ +<!DOCTYPE html> +<html><head class="foo"> + <title class="foo">getElementsByClassName</title> + <meta class="foo" content="big element listing" name="description"> + <link class="foo"> + <base class="foo"> + <script class="foo"></script> + <style class="foo"></style> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help"> +</head> + <body class="foo"> + <div id='log'></div> + <a class="foo">a</a> + <abbr class="foo">abbr</abbr> + <acronym class="foo">acronym</acronym> + <address class="foo">address</address> + <applet class="foo">applet</applet> + <b class="foo">b</b> + <bdo class="foo">bdo</bdo> + <big class="foo">big</big> + <blockquote class="foo">blockquote</blockquote> + <br class="foo"> + <button class="foo">button</button> + <center class="foo">center</center> + <cite class="foo">cite</cite> + <code class="foo">code</code> + <del class="foo">del</del> + <dfn class="foo">dfn</dfn> + <dir class="foo">dir + <li class="foo">li</li> + </dir> + <div class="foo">div</div> + <dl class="foo"> + <dt class="foo"> + </dt><dd class="foo">dd</dd> + </dl> + <em class="foo">em</em> + <font class="foo">font</font> + <form class="foo"> + <label class="foo">label</label> + <fieldset class="foo"> + <legend class="foo">legend</legend> + </fieldset> + </form> + <h1 class="foo">h1</h1> + <hr class="foo"> + <i class="foo">i</i> + <iframe class="foo">iframe</iframe> + <img class="foo"> + <input class="foo"> + <ins class="foo">ins</ins> + <kbd class="foo">kbd</kbd> + <map class="foo"> + <area class="foo"></area> + </map> + <menu class="foo">menu</menu> + <noscript class="foo">noscript</noscript> + <object class="foo"> + <param class="foo"> + </object> + <ol class="foo">ol</ol> + <p class="foo">p</p> + <pre class="foo">pre</pre> + <q class="foo">q</q> + <s class="foo">s</s> + <samp class="foo">samp</samp> + <select class="foo"> + <optgroup class="foo">optgroup</optgroup> + <option class="foo">option</option> + </select> + <small class="foo">small</small> + <span class="foo">span</span> + <strike class="foo">strike</strike> + <strong class="foo">strong</strong> + <sub class="foo">sub</sub> + <sup class="foo">sup</sup> + colgroup<table class="foo"> + <caption class="foo">caption</caption> + <colgroup><col class="foo"> + </colgroup><colgroup class="foo"></colgroup> + <thead class="foo"> + <tr><th class="foo">th</th> + </tr></thead> + <tbody class="foo"> + <tr class="foo"> + <td class="foo">td</td> + </tr> + </tbody> + <tfoot class="foo"></tfoot> + </table> + <textarea class="foo">textarea</textarea> + <tt class="foo">tt</tt> + <u class="foo">u</u> + <ul class="foo">ul</ul> + <var class="foo">var</var> + <script type="text/javascript"> + test(function () + { + var arrElements = [ + "HEAD", + "TITLE", + "META", + "LINK", + "BASE", + "SCRIPT", + "STYLE", + "BODY", + "A", + "ABBR", + "ACRONYM", + "ADDRESS", + "APPLET", + "B", + "BDO", + "BIG", + "BLOCKQUOTE", + "BR", + "BUTTON", + "CENTER", + "CITE", + "CODE", + "DEL", + "DFN", + "DIR", + "LI", + "DIV", + "DL", + "DT", + "DD", + "EM", + "FONT", + "FORM", + "LABEL", + "FIELDSET", + "LEGEND", + "H1", + "HR", + "I", + "IFRAME", + "IMG", + "INPUT", + "INS", + "KBD", + "MAP", + "AREA", + "MENU", + "NOSCRIPT", + "OBJECT", + "PARAM", + "OL", + "P", + "PRE", + "Q", + "S", + "SAMP", + "SELECT", + "OPTGROUP", + "OPTION", + "SMALL", + "SPAN", + "STRIKE", + "STRONG", + "SUB", + "SUP", + "TABLE", + "CAPTION", + "COL", + "COLGROUP", + "THEAD", + "TH", + "TBODY", + "TR", + "TD", + "TFOOT", + "TEXTAREA", + "TT", + "U", + "UL", + "VAR"]; + + var collection = document.getElementsByClassName("foo"); + for (var x = 0; x < collection.length; x++) + { + assert_equals(collection[x].nodeName, arrElements[x]); + } +}, "big element listing"); + </script> +</body></html> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassName-31.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassName-31.htm new file mode 100644 index 000000000..0e1ac014a --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassName-31.htm @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<html class=foo> +<meta charset=utf-8> +<title>getElementsByClassName across documents</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script class=foo> +async_test(function() { + var iframe = document.createElement("iframe"); + iframe.onload = this.step_func_done(function() { + var collection = iframe.contentDocument.getElementsByClassName("foo"); + assert_equals(collection.length, 3); + assert_equals(collection[0].localName, "html"); + assert_equals(collection[1].localName, "head"); + assert_equals(collection[2].localName, "body"); + }); + iframe.src = "getElementsByClassNameFrame.htm"; + document.body.appendChild(iframe); +}); +</script> diff --git a/testing/web-platform/tests/dom/nodes/getElementsByClassNameFrame.htm b/testing/web-platform/tests/dom/nodes/getElementsByClassNameFrame.htm new file mode 100644 index 000000000..544df60a9 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/getElementsByClassNameFrame.htm @@ -0,0 +1,6 @@ +<!DOCTYPE html> +<html class=foo> +<head class=foo> +<meta charset=utf-8> +<title>getElementsByClassName</title> +<body class=foo> diff --git a/testing/web-platform/tests/dom/nodes/insert-adjacent.html b/testing/web-platform/tests/dom/nodes/insert-adjacent.html new file mode 100644 index 000000000..247b7d174 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/insert-adjacent.html @@ -0,0 +1,79 @@ +<!doctype html> +<meta charset="utf-8"> +<title></title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> +#element { + display: none; +} +</style> + +<div id="element"></div> +<div id="log"></div> + +<script> +var possiblePositions = { + 'beforebegin': 'previousSibling' + , 'afterbegin': 'firstChild' + , 'beforeend': 'lastChild' + , 'afterend': 'nextSibling' +} +var texts = { + 'beforebegin': 'raclette' + , 'afterbegin': 'tartiflette' + , 'beforeend': 'lasagne' + , 'afterend': 'gateau aux pommes' +} + +var el = document.querySelector('#element'); + +Object.keys(possiblePositions).forEach(function(position) { + var div = document.createElement('h3'); + test(function() { + div.id = texts[position]; + el.insertAdjacentElement(position, div); + assert_equals(el[possiblePositions[position]].id, texts[position]); + }, 'insertAdjacentElement(' + position + ', ' + div + ' )'); + + test(function() { + el.insertAdjacentText(position, texts[position]); + assert_equals(el[possiblePositions[position]].textContent, texts[position]); + }, 'insertAdjacentText(' + position + ', ' + texts[position] + ' )'); +}); + +test(function() { + assert_throws(new TypeError(), function() { + el.insertAdjacentElement('afterbegin', + document.implementation.createDocumentType("html")) + }) +}, 'invalid object argument insertAdjacentElement') +test(function() { + var el = document.implementation.createHTMLDocument().documentElement; + assert_throws("HIERARCHY_REQUEST_ERR", function() { + el.insertAdjacentElement('beforebegin', document.createElement('banane')) + }) +}, 'invalid caller object insertAdjacentElement') +test(function() { + var el = document.implementation.createHTMLDocument().documentElement; + assert_throws("HIERARCHY_REQUEST_ERR", function() { + el.insertAdjacentText('beforebegin', 'tomate farcie') + }) +}, 'invalid caller object insertAdjacentText') +test(function() { + var div = document.createElement('h3'); + assert_throws("SYNTAX_ERR", function() { + el.insertAdjacentElement('heeeee', div) + }) +}, "invalid syntax for insertAdjacentElement") +test(function() { + assert_throws("SYNTAX_ERR", function() { + el.insertAdjacentText('hoooo', 'magret de canard') + }) +}, "invalid syntax for insertAdjacentText") +test(function() { + var div = document.createElement('div'); + assert_equals(div.insertAdjacentElement("beforebegin", el), null); +}, 'insertAdjacentText should return null'); + +</script> diff --git a/testing/web-platform/tests/dom/nodes/mutationobservers.js b/testing/web-platform/tests/dom/nodes/mutationobservers.js new file mode 100644 index 000000000..772f280be --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/mutationobservers.js @@ -0,0 +1,76 @@ +// Compares a mutation record to a predefined one +// mutationToCheck is a mutation record from the user agent +// expectedRecord is a mutation record minted by the test +// for expectedRecord, if properties are ommitted, they get default ones +function checkRecords(target, mutationToCheck, expectedRecord) { + var mr1; + var mr2; + + + function checkField(property, isArray) { + var field = mr2[property]; + if (isArray === undefined) { + isArray = false; + } + if (field instanceof Function) { + field = field(); + } else if (field === undefined) { + if (isArray) { + field = new Array(); + } else { + field = null; + } + } + if (isArray) { + assert_array_equals(mr1[property], field, property + " didn't match"); + } else { + assert_equals(mr1[property], field, property + " didn't match"); + } + } + + assert_equals(mutationToCheck.length, expectedRecord.length, "mutation records must match"); + for (var item = 0; item < mutationToCheck.length; item++) { + mr1 = mutationToCheck[item]; + mr2 = expectedRecord[item]; + + if (mr2.target instanceof Function) { + assert_equals(mr1.target, mr2.target(), "target node must match"); + } else if (mr2.target !== undefined) { + assert_equals(mr1.target, mr2.target, "target node must match"); + } else { + assert_equals(mr1.target, target, "target node must match"); + } + + checkField("type"); + checkField("addedNodes", true); + checkField("removedNodes", true); + checkField("previousSibling"); + checkField("nextSibling"); + checkField("attributeName"); + checkField("attributeNamespace"); + checkField("oldValue"); + }; +} + +function runMutationTest(node, mutationObserverOptions, mutationRecordSequence, mutationFunction, description, target) { + var test = async_test(description); + + + function moc(mrl, obs) { + test.step( + function () { + if (target === undefined) target = node; + checkRecords(target, mrl, mutationRecordSequence); + test.done(); + } + ); + } + + test.step( + function () { + (new MutationObserver(moc)).observe(node, mutationObserverOptions); + mutationFunction(); + } + ); + return mutationRecordSequence.length +} diff --git a/testing/web-platform/tests/dom/nodes/prepend-on-Document.html b/testing/web-platform/tests/dom/nodes/prepend-on-Document.html new file mode 100644 index 000000000..ccc56894d --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/prepend-on-Document.html @@ -0,0 +1,53 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>DocumentType.prepend</title> +<link rel=help href="https://dom.spec.whatwg.org/#dom-parentnode-prepend"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + +function test_prepend_on_Document() { + + var node = document.implementation.createDocument(null, null); + test(function() { + var parent = node.cloneNode(); + parent.prepend(); + assert_array_equals(parent.childNodes, []); + }, 'Document.prepend() without any argument, on a Document having no child.'); + + test(function() { + var parent = node.cloneNode(); + var x = document.createElement('x'); + parent.prepend(x); + assert_array_equals(parent.childNodes, [x]); + }, 'Document.prepend() with only one element as an argument, on a Document having no child.'); + + test(function() { + var parent = node.cloneNode(); + var x = document.createElement('x'); + var y = document.createElement('y'); + parent.appendChild(x); + assert_throws('HierarchyRequestError', function() { parent.prepend(y); }); + assert_array_equals(parent.childNodes, [x]); + }, 'Document.append() with only one element as an argument, on a Document having one child.'); + + test(function() { + var parent = node.cloneNode(); + assert_throws('HierarchyRequestError', function() { parent.prepend('text'); }); + assert_array_equals(parent.childNodes, []); + }, 'Document.prepend() with text as an argument, on a Document having no child.'); + + test(function() { + var parent = node.cloneNode(); + var x = document.createElement('x'); + var y = document.createElement('y'); + assert_throws('HierarchyRequestError', function() { parent.prepend(x, y); }); + assert_array_equals(parent.childNodes, []); + }, 'Document.prepend() with two elements as the argument, on a Document having no child.'); + +} + +test_prepend_on_Document(); + +</script> +</html> diff --git a/testing/web-platform/tests/dom/nodes/productions.js b/testing/web-platform/tests/dom/nodes/productions.js new file mode 100644 index 000000000..2b9959041 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/productions.js @@ -0,0 +1,3 @@ +var invalid_names = ["", "invalid^Name", "\\", "'", '"', "0", "0:a"] // XXX +var valid_names = ["x", ":", "a:0"] +var invalid_qnames = [":a", "b:", "x:y:z"] // XXX diff --git a/testing/web-platform/tests/dom/nodes/remove-unscopable.html b/testing/web-platform/tests/dom/nodes/remove-unscopable.html new file mode 100644 index 000000000..0238b0fa9 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/remove-unscopable.html @@ -0,0 +1,32 @@ +<!doctype html> +<meta charset=utf-8> +<title></title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id="testDiv" onclick="result1 = remove; result2 = this.remove;"></div> +<script> +var result1; +var result2; +var unscopables = [ + "before", + "after", + "replaceWith", + "remove", + "prepend", + "append" +]; +for (var i in unscopables) { + var name = unscopables[i]; + window[name] = "Hello there"; + result1 = result2 = undefined; + test(function () { + assert_true(Element.prototype[Symbol.unscopables][name]); + var div = document.querySelector('#testDiv'); + div.setAttribute( + "onclick", "result1 = " + name + "; result2 = this." + name + ";"); + div.dispatchEvent(new Event("click")); + assert_equals(typeof result1, "string"); + assert_equals(typeof result2, "function"); + }, name + "() should be unscopable"); +} +</script> diff --git a/testing/web-platform/tests/dom/nodes/rootNode.html b/testing/web-platform/tests/dom/nodes/rootNode.html new file mode 100644 index 000000000..66343e7e2 --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/rootNode.html @@ -0,0 +1,82 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset=utf-8> +<title>Node.prototype.getRootNode()</title> +<link rel="help" href="https://dom.spec.whatwg.org/#dom-node-getrootnode"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> + +test(function () { + var element = document.createElement('div'); + assert_equals(element.getRootNode(), element, 'getRootNode() on an element without a parent must return the element itself'); + + var text = document.createTextNode(''); + assert_equals(text.getRootNode(), text, 'getRootNode() on a text node without a parent must return the text node itself'); + + var processingInstruction = document.createProcessingInstruction('target', 'data'); + assert_equals(processingInstruction.getRootNode(), processingInstruction, 'getRootNode() on a processing instruction node without a parent must return the processing instruction node itself'); + + assert_equals(document.getRootNode(), document, 'getRootNode() on a document node must return the document itself'); + +}, 'getRootNode() must return the context object when it does not have any parent'); + +test(function () { + var parent = document.createElement('div'); + + var element = document.createElement('div'); + parent.appendChild(element); + assert_equals(element.getRootNode(), parent, 'getRootNode() on an element with a single ancestor must return the parent node'); + + var text = document.createTextNode(''); + parent.appendChild(text); + assert_equals(text.getRootNode(), parent, 'getRootNode() on a text node with a single ancestor must return the parent node'); + + var processingInstruction = document.createProcessingInstruction('target', 'data'); + parent.appendChild(processingInstruction) + assert_equals(processingInstruction.getRootNode(), parent, 'getRootNode() on a processing instruction node with a single ancestor must return the parent node'); + +}, 'getRootNode() must return the parent node of the context object when the context object has a single ancestor not in a document'); + +test(function () { + var parent = document.createElement('div'); + document.body.appendChild(parent); + + var element = document.createElement('div'); + parent.appendChild(element); + assert_equals(element.getRootNode(), document, 'getRootNode() on an element inside a document must return the document'); + + var text = document.createTextNode(''); + parent.appendChild(text); + assert_equals(text.getRootNode(), document, 'getRootNode() on a text node inside a document must return the document'); + + var processingInstruction = document.createProcessingInstruction('target', 'data'); + parent.appendChild(processingInstruction) + assert_equals(processingInstruction.getRootNode(), document, 'getRootNode() on a processing instruction node inside a document must return the document'); +}, 'getRootNode() must return the document when a node is in document'); + +test(function () { + var fragment = document.createDocumentFragment(); + var parent = document.createElement('div'); + fragment.appendChild(parent); + + var element = document.createElement('div'); + parent.appendChild(element); + assert_equals(element.getRootNode(), fragment, 'getRootNode() on an element inside a document fragment must return the fragment'); + + var text = document.createTextNode(''); + parent.appendChild(text); + assert_equals(text.getRootNode(), fragment, 'getRootNode() on a text node inside a document fragment must return the fragment'); + + var processingInstruction = document.createProcessingInstruction('target', 'data'); + parent.appendChild(processingInstruction) + assert_equals(processingInstruction.getRootNode(), fragment, + 'getRootNode() on a processing instruction node inside a document fragment must return the fragment'); +}, 'getRootNode() must return a document fragment when a node is in the fragment'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/dom/nodes/selectors.js b/testing/web-platform/tests/dom/nodes/selectors.js new file mode 100644 index 000000000..ac722a6fe --- /dev/null +++ b/testing/web-platform/tests/dom/nodes/selectors.js @@ -0,0 +1,734 @@ +// Bit-mapped flags to indicate which tests the selector is suitable for +var TEST_QSA = 0x01; // querySelector() and querySelectorAll() tests +var TEST_FIND = 0x04; // find() and findAll() tests, may be unsuitable for querySelector[All] +var TEST_MATCH = 0x10; // matches() tests + +/* + * All of these invalid selectors should result in a SyntaxError being thrown by the APIs. + * + * name: A descriptive name of the selector being tested + * selector: The selector to test + */ +var invalidSelectors = [ + {name: "Empty String", selector: ""}, + {name: "Invalid character", selector: "["}, + {name: "Invalid character", selector: "]"}, + {name: "Invalid character", selector: "("}, + {name: "Invalid character", selector: ")"}, + {name: "Invalid character", selector: "{"}, + {name: "Invalid character", selector: "}"}, + {name: "Invalid character", selector: "<"}, + {name: "Invalid character", selector: ">"}, + {name: "Invalid ID", selector: "#"}, + {name: "Invalid group of selectors", selector: "div,"}, + {name: "Invalid class", selector: "."}, + {name: "Invalid class", selector: ".5cm"}, + {name: "Invalid class", selector: "..test"}, + {name: "Invalid class", selector: ".foo..quux"}, + {name: "Invalid class", selector: ".bar."}, + {name: "Invalid combinator", selector: "div & address, p"}, + {name: "Invalid combinator", selector: "div ++ address, p"}, + {name: "Invalid combinator", selector: "div ~~ address, p"}, + {name: "Invalid [att=value] selector", selector: "[*=test]"}, + {name: "Invalid [att=value] selector", selector: "[*|*=test]"}, + {name: "Invalid [att=value] selector", selector: "[class= space unquoted ]"}, + {name: "Unknown pseudo-class", selector: "div:example"}, + {name: "Unknown pseudo-class", selector: ":example"}, + {name: "Unknown pseudo-element", selector: "div::example"}, + {name: "Unknown pseudo-element", selector: "::example"}, + {name: "Invalid pseudo-element", selector: ":::before"}, + {name: "Undeclared namespace", selector: "ns|div"}, + {name: "Undeclared namespace", selector: ":not(ns|div)"}, + {name: "Invalid namespace", selector: "^|div"}, + {name: "Invalid namespace", selector: "$|div"} +]; + +/* + * All of these should be valid selectors, expected to match zero or more elements in the document. + * None should throw any errors. + * + * name: A descriptive name of the selector being tested + * selector: The selector to test + * expect: A list of IDs of the elements expected to be matched. List must be given in tree order. + * exclude: An array of contexts to exclude from testing. The valid values are: + * ["document", "element", "fragment", "detached", "html", "xhtml"] + * The "html" and "xhtml" values represent the type of document being queried. These are useful + * for tests that are affected by differences between HTML and XML, such as case sensitivity. + * level: An integer indicating the CSS or Selectors level in which the selector being tested was introduced. + * testType: A bit-mapped flag indicating the type of test. + * + * Note: Interactive pseudo-classes (:active :hover and :focus) have not been tested in this test suite. + */ +var validSelectors = [ + // Type Selector + {name: "Type selector, matching html element", selector: "html", expect: ["html"], exclude: ["element", "fragment", "detached"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Type selector, matching html element", selector: "html", expect: [] /*no matches*/, exclude: ["document"], level: 1, testType: TEST_QSA}, + {name: "Type selector, matching body element", selector: "body", expect: ["body"], exclude: ["element", "fragment", "detached"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Type selector, matching body element", selector: "body", expect: [] /*no matches*/, exclude: ["document"], level: 1, testType: TEST_QSA}, + + // Universal Selector + // Testing "*" for entire an entire context node is handled separately. + {name: "Universal selector, matching all children of element with specified ID", selector: "#universal>*", expect: ["universal-p1", "universal-hr1", "universal-pre1", "universal-p2", "universal-address1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Universal selector, matching all grandchildren of element with specified ID", selector: "#universal>*>*", expect: ["universal-code1", "universal-span1", "universal-a1", "universal-code2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Universal selector, matching all children of empty element with specified ID", selector: "#empty>*", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "Universal selector, matching all descendants of element with specified ID", selector: "#universal *", expect: ["universal-p1", "universal-code1", "universal-hr1", "universal-pre1", "universal-span1", "universal-p2", "universal-a1", "universal-address1", "universal-code2", "universal-a2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + + // Attribute Selectors + // - presence [att] + {name: "Attribute presence selector, matching align attribute with value", selector: ".attr-presence-div1[align]", expect: ["attr-presence-div1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute presence selector, matching align attribute with empty value", selector: ".attr-presence-div2[align]", expect: ["attr-presence-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute presence selector, matching title attribute, case insensitivity", selector: "#attr-presence [TiTlE]", expect: ["attr-presence-a1", "attr-presence-span1"], exclude: ["xhtml"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute presence selector, not matching title attribute, case sensitivity", selector: "#attr-presence [TiTlE]", expect: [], exclude: ["html"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute presence selector, matching custom data-* attribute", selector: "[data-attr-presence]", expect: ["attr-presence-pre1", "attr-presence-blockquote1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute presence selector, not matching attribute with similar name", selector: ".attr-presence-div3[align], .attr-presence-div4[align]", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "Attribute presence selector, matching attribute with non-ASCII characters", selector: "ul[data-中文]", expect: ["attr-presence-ul1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute presence selector, not matching default option without selected attribute", selector: "#attr-presence-select1 option[selected]", expect: [] /* no matches */, level: 2, testType: TEST_QSA}, + {name: "Attribute presence selector, matching option with selected attribute", selector: "#attr-presence-select2 option[selected]", expect: ["attr-presence-select2-option4"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute presence selector, matching multiple options with selected attributes", selector: "#attr-presence-select3 option[selected]", expect: ["attr-presence-select3-option2", "attr-presence-select3-option3"], level: 2, testType: TEST_QSA | TEST_MATCH}, + + // - value [att=val] + {name: "Attribute value selector, matching align attribute with value", selector: "#attr-value [align=\"center\"]", expect: ["attr-value-div1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute value selector, matching align attribute with empty value", selector: "#attr-value [align=\"\"]", expect: ["attr-value-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute value selector, not matching align attribute with partial value", selector: "#attr-value [align=\"c\"]", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "Attribute value selector, not matching align attribute with incorrect value", selector: "#attr-value [align=\"centera\"]", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "Attribute value selector, matching custom data-* attribute with unicode escaped value", selector: "[data-attr-value=\"\\e9\"]", expect: ["attr-value-div3"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute value selector, matching custom data-* attribute with escaped character", selector: "[data-attr-value\_foo=\"\\e9\"]", expect: ["attr-value-div4"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute value selector with single-quoted value, matching multiple inputs with type attributes", selector: "#attr-value input[type='hidden'],#attr-value input[type='radio']", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute value selector with double-quoted value, matching multiple inputs with type attributes", selector: "#attr-value input[type=\"hidden\"],#attr-value input[type='radio']", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute value selector with unquoted value, matching multiple inputs with type attributes", selector: "#attr-value input[type=hidden],#attr-value input[type=radio]", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute value selector, matching attribute with value using non-ASCII characters", selector: "[data-attr-value=中文]", expect: ["attr-value-div5"], level: 2, testType: TEST_QSA | TEST_MATCH}, + + // - whitespace-separated list [att~=val] + {name: "Attribute whitespace-separated list selector, matching class attribute with value", selector: "#attr-whitespace [class~=\"div1\"]", expect: ["attr-whitespace-div1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector, not matching class attribute with empty value", selector: "#attr-whitespace [class~=\"\"]", expect: [] /*no matches*/ , level: 2, testType: TEST_QSA}, + {name: "Attribute whitespace-separated list selector, not matching class attribute with partial value", selector: "[data-attr-whitespace~=\"div\"]", expect: [] /*no matches*/ , level: 2, testType: TEST_QSA}, + {name: "Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value", selector: "[data-attr-whitespace~=\"\\0000e9\"]", expect: ["attr-whitespace-div4"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character", selector: "[data-attr-whitespace\_foo~=\"\\e9\"]", expect: ["attr-whitespace-div5"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes", selector: "#attr-whitespace a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow']", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes", selector: "#attr-whitespace a[rel~=\"bookmark\"],#attr-whitespace a[rel~='nofollow']", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes", selector: "#attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow]", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector with double-quoted value, not matching value with space", selector: "#attr-whitespace a[rel~=\"book mark\"]", expect: [] /* no matches */, level: 2, testType: TEST_QSA}, + {name: "Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters", selector: "#attr-whitespace [title~=中文]", expect: ["attr-whitespace-p1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + + // - hyphen-separated list [att|=val] + {name: "Attribute hyphen-separated list selector, not matching unspecified lang attribute", selector: "#attr-hyphen-div1[lang|=\"en\"]", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "Attribute hyphen-separated list selector, matching lang attribute with exact value", selector: "#attr-hyphen-div2[lang|=\"fr\"]", expect: ["attr-hyphen-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute hyphen-separated list selector, matching lang attribute with partial value", selector: "#attr-hyphen-div3[lang|=\"en\"]", expect: ["attr-hyphen-div3"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute hyphen-separated list selector, not matching incorrect value", selector: "#attr-hyphen-div4[lang|=\"es-AR\"]", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + + // - substring begins-with [att^=val] (Level 3) + {name: "Attribute begins with selector, matching href attributes beginning with specified substring", selector: "#attr-begins a[href^=\"http://www\"]", expect: ["attr-begins-a1", "attr-begins-a3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute begins with selector, matching lang attributes beginning with specified substring, ", selector: "#attr-begins [lang^=\"en-\"]", expect: ["attr-begins-div2", "attr-begins-div4"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute begins with selector, not matching class attribute not beginning with specified substring", selector: "#attr-begins [class^=apple]", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + {name: "Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring", selector: "#attr-begins [class^=' apple']", expect: ["attr-begins-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring", selector: "#attr-begins [class^=\" apple\"]", expect: ["attr-begins-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring", selector: "#attr-begins [class^= apple]", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + + // - substring ends-with [att$=val] (Level 3) + {name: "Attribute ends with selector, matching href attributes ending with specified substring", selector: "#attr-ends a[href$=\".org\"]", expect: ["attr-ends-a1", "attr-ends-a3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute ends with selector, matching lang attributes ending with specified substring, ", selector: "#attr-ends [lang$=\"-CH\"]", expect: ["attr-ends-div2", "attr-ends-div4"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute ends with selector, not matching class attribute not ending with specified substring", selector: "#attr-ends [class$=apple]", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + {name: "Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring", selector: "#attr-ends [class$='apple ']", expect: ["attr-ends-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring", selector: "#attr-ends [class$=\"apple \"]", expect: ["attr-ends-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring", selector: "#attr-ends [class$=apple ]", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + + // - substring contains [att*=val] (Level 3) + {name: "Attribute contains selector, matching href attributes beginning with specified substring", selector: "#attr-contains a[href*=\"http://www\"]", expect: ["attr-contains-a1", "attr-contains-a3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector, matching href attributes ending with specified substring", selector: "#attr-contains a[href*=\".org\"]", expect: ["attr-contains-a1", "attr-contains-a2"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector, matching href attributes containing specified substring", selector: "#attr-contains a[href*=\".example.\"]", expect: ["attr-contains-a1", "attr-contains-a3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector, matching lang attributes beginning with specified substring, ", selector: "#attr-contains [lang*=\"en-\"]", expect: ["attr-contains-div2", "attr-contains-div6"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector, matching lang attributes ending with specified substring, ", selector: "#attr-contains [lang*=\"-CH\"]", expect: ["attr-contains-div3", "attr-contains-div5"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring", selector: "#attr-contains [class*=' apple']", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector with single-quoted value, matching class attribute ending with specified substring", selector: "#attr-contains [class*='orange ']", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector with single-quoted value, matching class attribute containing specified substring", selector: "#attr-contains [class*='ple banana ora']", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring", selector: "#attr-contains [class*=\" apple\"]", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector with double-quoted value, matching class attribute ending with specified substring", selector: "#attr-contains [class*=\"orange \"]", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector with double-quoted value, matching class attribute containing specified substring", selector: "#attr-contains [class*=\"ple banana ora\"]", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector with unquoted value, matching class attribute beginning with specified substring", selector: "#attr-contains [class*= apple]", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector with unquoted value, matching class attribute ending with specified substring", selector: "#attr-contains [class*=orange ]", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "Attribute contains selector with unquoted value, matching class attribute containing specified substring", selector: "#attr-contains [class*= banana ]", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // Pseudo-classes + // - :root (Level 3) + {name: ":root pseudo-class selector, matching document root element", selector: ":root", expect: ["html"], exclude: ["element", "fragment", "detached"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":root pseudo-class selector, not matching document root element", selector: ":root", expect: [] /*no matches*/, exclude: ["document"], level: 3, testType: TEST_QSA}, + + // - :nth-child(n) (Level 3) + // XXX write descriptions + {name: ":nth-child selector, matching the third child element", selector: "#pseudo-nth-table1 :nth-child(3)", expect: ["pseudo-nth-td3", "pseudo-nth-td9", "pseudo-nth-tr3", "pseudo-nth-td15"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-child selector, matching every third child element", selector: "#pseudo-nth li:nth-child(3n)", expect: ["pseudo-nth-li3", "pseudo-nth-li6", "pseudo-nth-li9", "pseudo-nth-li12"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-child selector, matching every second child element, starting from the fourth", selector: "#pseudo-nth li:nth-child(2n+4)", expect: ["pseudo-nth-li4", "pseudo-nth-li6", "pseudo-nth-li8", "pseudo-nth-li10", "pseudo-nth-li12"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-child selector, matching every fourth child element, starting from the third", selector: "#pseudo-nth-p1 :nth-child(4n-1)", expect: ["pseudo-nth-em2", "pseudo-nth-span3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :nth-last-child (Level 3) + {name: ":nth-last-child selector, matching the third last child element", selector: "#pseudo-nth-table1 :nth-last-child(3)", expect: ["pseudo-nth-tr1", "pseudo-nth-td4", "pseudo-nth-td10", "pseudo-nth-td16"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-last-child selector, matching every third child element from the end", selector: "#pseudo-nth li:nth-last-child(3n)", expect: ["pseudo-nth-li1", "pseudo-nth-li4", "pseudo-nth-li7", "pseudo-nth-li10"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-last-child selector, matching every second child element from the end, starting from the fourth last", selector: "#pseudo-nth li:nth-last-child(2n+4)", expect: ["pseudo-nth-li1", "pseudo-nth-li3", "pseudo-nth-li5", "pseudo-nth-li7", "pseudo-nth-li9"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-last-child selector, matching every fourth element from the end, starting from the third last", selector: "#pseudo-nth-p1 :nth-last-child(4n-1)", expect: ["pseudo-nth-span2", "pseudo-nth-span4"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :nth-of-type(n) (Level 3) + {name: ":nth-of-type selector, matching the third em element", selector: "#pseudo-nth-p1 em:nth-of-type(3)", expect: ["pseudo-nth-em3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-of-type selector, matching every second element of their type", selector: "#pseudo-nth-p1 :nth-of-type(2n)", expect: ["pseudo-nth-em2", "pseudo-nth-span2", "pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-of-type selector, matching every second elemetn of their type, starting from the first", selector: "#pseudo-nth-p1 span:nth-of-type(2n-1)", expect: ["pseudo-nth-span1", "pseudo-nth-span3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :nth-last-of-type(n) (Level 3) + {name: ":nth-last-of-type selector, matching the thrid last em element", selector: "#pseudo-nth-p1 em:nth-last-of-type(3)", expect: ["pseudo-nth-em2"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-last-of-type selector, matching every second last element of their type", selector: "#pseudo-nth-p1 :nth-last-of-type(2n)", expect: ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1", "pseudo-nth-em3", "pseudo-nth-span3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":nth-last-of-type selector, matching every second last element of their type, starting from the last", selector: "#pseudo-nth-p1 span:nth-last-of-type(2n-1)", expect: ["pseudo-nth-span2", "pseudo-nth-span4"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :first-of-type (Level 3) + {name: ":first-of-type selector, matching the first em element", selector: "#pseudo-nth-p1 em:first-of-type", expect: ["pseudo-nth-em1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":first-of-type selector, matching the first of every type of element", selector: "#pseudo-nth-p1 :first-of-type", expect: ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":first-of-type selector, matching the first td element in each table row", selector: "#pseudo-nth-table1 tr :first-of-type", expect: ["pseudo-nth-td1", "pseudo-nth-td7", "pseudo-nth-td13"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :last-of-type (Level 3) + {name: ":last-of-type selector, matching the last em elemnet", selector: "#pseudo-nth-p1 em:last-of-type", expect: ["pseudo-nth-em4"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":last-of-type selector, matching the last of every type of element", selector: "#pseudo-nth-p1 :last-of-type", expect: ["pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":last-of-type selector, matching the last td element in each table row", selector: "#pseudo-nth-table1 tr :last-of-type", expect: ["pseudo-nth-td6", "pseudo-nth-td12", "pseudo-nth-td18"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :first-child + {name: ":first-child pseudo-class selector, matching first child div element", selector: "#pseudo-first-child div:first-child", expect: ["pseudo-first-child-div1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: ":first-child pseudo-class selector, doesn't match non-first-child elements", selector: ".pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: ":first-child pseudo-class selector, matching first-child of multiple elements", selector: "#pseudo-first-child span:first-child", expect: ["pseudo-first-child-span1", "pseudo-first-child-span3", "pseudo-first-child-span5"], level: 2, testType: TEST_QSA | TEST_MATCH}, + + // - :last-child (Level 3) + {name: ":last-child pseudo-class selector, matching last child div element", selector: "#pseudo-last-child div:last-child", expect: ["pseudo-last-child-div3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":last-child pseudo-class selector, doesn't match non-last-child elements", selector: ".pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + {name: ":last-child pseudo-class selector, matching first-child of multiple elements", selector: "#pseudo-last-child span:last-child", expect: ["pseudo-last-child-span2", "pseudo-last-child-span4", "pseudo-last-child-span6"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :only-child (Level 3) + {name: ":pseudo-only-child pseudo-class selector, matching all only-child elements", selector: "#pseudo-only :only-child", expect: ["pseudo-only-span1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":pseudo-only-child pseudo-class selector, matching only-child em elements", selector: "#pseudo-only em:only-child", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + + // - :only-of-type (Level 3) + {name: ":pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type", selector: "#pseudo-only :only-of-type", expect: ["pseudo-only-span1", "pseudo-only-em1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type", selector: "#pseudo-only em:only-of-type", expect: ["pseudo-only-em1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :empty (Level 3) + {name: ":empty pseudo-class selector, matching empty p elements", selector: "#pseudo-empty p:empty", expect: ["pseudo-empty-p1", "pseudo-empty-p2"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":empty pseudo-class selector, matching all empty elements", selector: "#pseudo-empty :empty", expect: ["pseudo-empty-p1", "pseudo-empty-p2", "pseudo-empty-span1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :link and :visited + // Implementations may treat all visited links as unvisited, so these cannot be tested separately. + // The only guarantee is that ":link,:visited" matches the set of all visited and unvisited links and that they are individually mutually exclusive sets. + {name: ":link and :visited pseudo-class selectors, matching a and area elements with href attributes", selector: "#pseudo-link :link, #pseudo-link :visited", expect: ["pseudo-link-a1", "pseudo-link-a2", "pseudo-link-area1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: ":link and :visited pseudo-class selectors, matching link elements with href attributes", selector: "#head :link, #head :visited", expect: ["pseudo-link-link1", "pseudo-link-link2"], exclude: ["element", "fragment", "detached"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: ":link and :visited pseudo-class selectors, not matching link elements with href attributes", selector: "#head :link, #head :visited", expect: [] /*no matches*/, exclude: ["document"], level: 1, testType: TEST_QSA}, + {name: ":link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing", selector: ":link:visited", expect: [] /*no matches*/, exclude: ["document"], level: 1, testType: TEST_QSA}, + + // - :target (Level 3) + {name: ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", selector: ":target", expect: [] /*no matches*/, exclude: ["document", "element"], level: 3, testType: TEST_QSA}, + {name: ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", selector: ":target", expect: ["target"], exclude: ["fragment", "detached"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :lang() + {name: ":lang pseudo-class selector, matching inherited language", selector: "#pseudo-lang-div1:lang(en)", expect: ["pseudo-lang-div1"], exclude: ["detached", "fragment"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: ":lang pseudo-class selector, not matching element with no inherited language", selector: "#pseudo-lang-div1:lang(en)", expect: [] /*no matches*/, exclude: ["document", "element"], level: 2, testType: TEST_QSA}, + {name: ":lang pseudo-class selector, matching specified language with exact value", selector: "#pseudo-lang-div2:lang(fr)", expect: ["pseudo-lang-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: ":lang pseudo-class selector, matching specified language with partial value", selector: "#pseudo-lang-div3:lang(en)", expect: ["pseudo-lang-div3"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: ":lang pseudo-class selector, not matching incorrect language", selector: "#pseudo-lang-div4:lang(es-AR)", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + + // - :enabled (Level 3) + {name: ":enabled pseudo-class selector, matching all enabled form controls", selector: "#pseudo-ui :enabled", expect: ["pseudo-ui-input1", "pseudo-ui-input2", "pseudo-ui-input3", "pseudo-ui-input4", "pseudo-ui-input5", "pseudo-ui-input6", + "pseudo-ui-input7", "pseudo-ui-input8", "pseudo-ui-input9", "pseudo-ui-textarea1", "pseudo-ui-button1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :disabled (Level 3) + {name: ":enabled pseudo-class selector, matching all disabled form controls", selector: "#pseudo-ui :disabled", expect: ["pseudo-ui-input10", "pseudo-ui-input11", "pseudo-ui-input12", "pseudo-ui-input13", "pseudo-ui-input14", "pseudo-ui-input15", + "pseudo-ui-input16", "pseudo-ui-input17", "pseudo-ui-input18", "pseudo-ui-textarea2", "pseudo-ui-button2"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :checked (Level 3) + {name: ":checked pseudo-class selector, matching checked radio buttons and checkboxes", selector: "#pseudo-ui :checked", expect: ["pseudo-ui-input4", "pseudo-ui-input6", "pseudo-ui-input13", "pseudo-ui-input15"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // - :not(s) (Level 3) + {name: ":not pseudo-class selector, matching ", selector: "#not>:not(div)", expect: ["not-p1", "not-p2", "not-p3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":not pseudo-class selector, matching ", selector: "#not * :not(:first-child)", expect: ["not-em1", "not-em2", "not-em3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":not pseudo-class selector, matching nothing", selector: ":not(*)", expect: [] /* no matches */, level: 3, testType: TEST_QSA}, + {name: ":not pseudo-class selector, matching nothing", selector: ":not(*|*)", expect: [] /* no matches */, level: 3, testType: TEST_QSA}, + + // Pseudo-elements + // - ::first-line + {name: ":first-line pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:first-line", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "::first-line pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::first-line", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + + // - ::first-letter + {name: ":first-letter pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:first-letter", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "::first-letter pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::first-letter", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + + // - ::before + {name: ":before pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:before", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "::before pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::before", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + + // - ::after + {name: ":after pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:after", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "::after pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::after", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + + // Class Selectors + {name: "Class selector, matching element with specified class", selector: ".class-p", expect: ["class-p1","class-p2", "class-p3"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Class selector, chained, matching only elements with all specified classes", selector: "#class .apple.orange.banana", expect: ["class-div1", "class-div2", "class-p4", "class-div3", "class-p6", "class-div4"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Class Selector, chained, with type selector", selector: "div.apple.banana.orange", expect: ["class-div1", "class-div2", "class-div3", "class-div4"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Class selector, matching element with class value using non-ASCII characters (1)", selector: ".\u53F0\u5317Ta\u0301ibe\u030Ci", expect: ["class-span1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Class selector, matching multiple elements with class value using non-ASCII characters", selector: ".\u53F0\u5317", expect: ["class-span1","class-span2"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Class selector, chained, matching element with multiple class values using non-ASCII characters (1)", selector: ".\u53F0\u5317Ta\u0301ibe\u030Ci.\u53F0\u5317", expect: ["class-span1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Class selector, matching element with class with escaped character", selector: ".foo\\:bar", expect: ["class-span3"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Class selector, matching element with class with escaped character", selector: ".test\\.foo\\[5\\]bar", expect: ["class-span4"], level: 1, testType: TEST_QSA | TEST_MATCH}, + + // ID Selectors + {name: "ID selector, matching element with specified id", selector: "#id #id-div1", expect: ["id-div1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "ID selector, chained, matching element with specified id", selector: "#id-div1, #id-div1", expect: ["id-div1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "ID selector, chained, matching element with specified id", selector: "#id-div1, #id-div2", expect: ["id-div1", "id-div2"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "ID Selector, chained, with type selector", selector: "div#id-div1, div#id-div2", expect: ["id-div1", "id-div2"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "ID selector, not matching non-existent descendant", selector: "#id #none", expect: [] /*no matches*/, level: 1, testType: TEST_QSA}, + {name: "ID selector, not matching non-existent ancestor", selector: "#none #id-div1", expect: [] /*no matches*/, level: 1, testType: TEST_QSA}, + {name: "ID selector, matching multiple elements with duplicate id", selector: "#id-li-duplicate", expect: ["id-li-duplicate", "id-li-duplicate", "id-li-duplicate", "id-li-duplicate"], level: 1, testType: TEST_QSA | TEST_MATCH}, + + {name: "ID selector, matching id value using non-ASCII characters (1)", selector: "#\u53F0\u5317Ta\u0301ibe\u030Ci", expect: ["\u53F0\u5317Ta\u0301ibe\u030Ci"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "ID selector, matching id value using non-ASCII characters (2)", selector: "#\u53F0\u5317", expect: ["\u53F0\u5317"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "ID selector, matching id values using non-ASCII characters (1)", selector: "#\u53F0\u5317Ta\u0301ibe\u030Ci, #\u53F0\u5317", expect: ["\u53F0\u5317Ta\u0301ibe\u030Ci", "\u53F0\u5317"], level: 1, testType: TEST_QSA | TEST_MATCH}, + + // XXX runMatchesTest() in level2-lib.js can't handle this because obtaining the expected nodes requires escaping characters when generating the selector from 'expect' values + {name: "ID selector, matching element with id with escaped character", selector: "#\\#foo\\:bar", expect: ["#foo:bar"], level: 1, testType: TEST_QSA}, + {name: "ID selector, matching element with id with escaped character", selector: "#test\\.foo\\[5\\]bar", expect: ["test.foo[5]bar"], level: 1, testType: TEST_QSA}, + + // Namespaces + // XXX runMatchesTest() in level2-lib.js can't handle these because non-HTML elements don't have a recognised id + {name: "Namespace selector, matching element with any namespace", selector: "#any-namespace *|div", expect: ["any-namespace-div1", "any-namespace-div2", "any-namespace-div3", "any-namespace-div4"], level: 3, testType: TEST_QSA}, + {name: "Namespace selector, matching div elements in no namespace only", selector: "#no-namespace |div", expect: ["no-namespace-div3"], level: 3, testType: TEST_QSA}, + {name: "Namespace selector, matching any elements in no namespace only", selector: "#no-namespace |*", expect: ["no-namespace-div3"], level: 3, testType: TEST_QSA}, + + // Combinators + // - Descendant combinator ' ' + {name: "Descendant combinator, matching element that is a descendant of an element with id", selector: "#descendant div", expect: ["descendant-div1", "descendant-div2", "descendant-div3", "descendant-div4"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Descendant combinator, matching element with id that is a descendant of an element", selector: "body #descendant-div1", expect: ["descendant-div1"], exclude: ["detached", "fragment"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Descendant combinator, matching element with id that is a descendant of an element", selector: "div #descendant-div1", expect: ["descendant-div1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Descendant combinator, matching element with id that is a descendant of an element with id", selector: "#descendant #descendant-div2", expect: ["descendant-div2"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Descendant combinator, matching element with class that is a descendant of an element with id", selector: "#descendant .descendant-div2", expect: ["descendant-div2"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Descendant combinator, matching element with class that is a descendant of an element with class", selector: ".descendant-div1 .descendant-div3", expect: ["descendant-div3"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Descendant combinator, not matching element with id that is not a descendant of an element with id", selector: "#descendant-div1 #descendant-div4", expect: [] /*no matches*/, level: 1, testType: TEST_QSA}, + {name: "Descendant combinator, whitespace characters", selector: "#descendant\t\r\n#descendant-div2", expect: ["descendant-div2"], level: 1, testType: TEST_QSA | TEST_MATCH}, + + // - Descendant combinator '>>' + {name: "Descendant combinator '>>', matching element that is a descendant of an element with id", selector: "#descendant>>div", expect: ["descendant-div1", "descendant-div2", "descendant-div3", "descendant-div4"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Descendant combinator '>>', matching element with id that is a descendant of an element", selector: "body>>#descendant-div1", expect: ["descendant-div1"], exclude: ["detached", "fragment"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Descendant combinator '>>', matching element with id that is a descendant of an element", selector: "div>>#descendant-div1", expect: ["descendant-div1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Descendant combinator '>>', matching element with id that is a descendant of an element with id", selector: "#descendant>>#descendant-div2", expect: ["descendant-div2"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Descendant combinator '>>', matching element with class that is a descendant of an element with id", selector: "#descendant>>.descendant-div2", expect: ["descendant-div2"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Descendant combinator '>>', matching element with class that is a descendant of an element with class", selector: ".descendant-div1>>.descendant-div3", expect: ["descendant-div3"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Descendant combinator '>>', not matching element with id that is not a descendant of an element with id", selector: "#descendant-div1>>#descendant-div4", expect: [] /*no matches*/, level: 1, testType: TEST_QSA}, + + // - Child combinator '>' + {name: "Child combinator, matching element that is a child of an element with id", selector: "#child>div", expect: ["child-div1", "child-div4"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Child combinator, matching element with id that is a child of an element", selector: "div>#child-div1", expect: ["child-div1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Child combinator, matching element with id that is a child of an element with id", selector: "#child>#child-div1", expect: ["child-div1"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Child combinator, matching element with id that is a child of an element with class", selector: "#child-div1>.child-div2", expect: ["child-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Child combinator, matching element with class that is a child of an element with class", selector: ".child-div1>.child-div2", expect: ["child-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Child combinator, not matching element with id that is not a child of an element with id", selector: "#child>#child-div3", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "Child combinator, not matching element with id that is not a child of an element with class", selector: "#child-div1>.child-div3", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "Child combinator, not matching element with class that is not a child of an element with class", selector: ".child-div1>.child-div3", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "Child combinator, surrounded by whitespace", selector: "#child-div1\t\r\n>\t\r\n#child-div2", expect: ["child-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Child combinator, whitespace after", selector: "#child-div1>\t\r\n#child-div2", expect: ["child-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Child combinator, whitespace before", selector: "#child-div1\t\r\n>#child-div2", expect: ["child-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Child combinator, no whitespace", selector: "#child-div1>#child-div2", expect: ["child-div2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + + // - Adjacent sibling combinator '+' + {name: "Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id", selector: "#adjacent-div2+div", expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element", selector: "div+#adjacent-div4", expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id", selector: "#adjacent-div2+#adjacent-div4", expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id", selector: "#adjacent-div2+.adjacent-div4", expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class", selector: ".adjacent-div2+.adjacent-div4", expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element", selector: "#adjacent div+p", expect: ["adjacent-p2"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id", selector: "#adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1", expect: [] /*no matches*/, level: 2, testType: TEST_QSA}, + {name: "Adjacent sibling combinator, surrounded by whitespace", selector: "#adjacent-p2\t\r\n+\t\r\n#adjacent-p3", expect: ["adjacent-p3"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Adjacent sibling combinator, whitespace after", selector: "#adjacent-p2+\t\r\n#adjacent-p3", expect: ["adjacent-p3"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Adjacent sibling combinator, whitespace before", selector: "#adjacent-p2\t\r\n+#adjacent-p3", expect: ["adjacent-p3"], level: 2, testType: TEST_QSA | TEST_MATCH}, + {name: "Adjacent sibling combinator, no whitespace", selector: "#adjacent-p2+#adjacent-p3", expect: ["adjacent-p3"], level: 2, testType: TEST_QSA | TEST_MATCH}, + + // - General sibling combinator ~ (Level 3) + {name: "General sibling combinator, matching element that is a sibling of an element with id", selector: "#sibling-div2~div", expect: ["sibling-div4", "sibling-div6"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "General sibling combinator, matching element with id that is a sibling of an element", selector: "div~#sibling-div4", expect: ["sibling-div4"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "General sibling combinator, matching element with id that is a sibling of an element with id", selector: "#sibling-div2~#sibling-div4", expect: ["sibling-div4"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "General sibling combinator, matching element with class that is a sibling of an element with id", selector: "#sibling-div2~.sibling-div", expect: ["sibling-div4", "sibling-div6"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "General sibling combinator, matching p element that is a sibling of a div element", selector: "#sibling div~p", expect: ["sibling-p2", "sibling-p3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "General sibling combinator, not matching element with id that is not a sibling after a p element", selector: "#sibling>p~div", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + {name: "General sibling combinator, not matching element with id that is not a sibling after an element with id", selector: "#sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1", expect: [] /*no matches*/, level: 3, testType: TEST_QSA}, + {name: "General sibling combinator, surrounded by whitespace", selector: "#sibling-p2\t\r\n~\t\r\n#sibling-p3", expect: ["sibling-p3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "General sibling combinator, whitespace after", selector: "#sibling-p2~\t\r\n#sibling-p3", expect: ["sibling-p3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "General sibling combinator, whitespace before", selector: "#sibling-p2\t\r\n~#sibling-p3", expect: ["sibling-p3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: "General sibling combinator, no whitespace", selector: "#sibling-p2~#sibling-p3", expect: ["sibling-p3"], level: 3, testType: TEST_QSA | TEST_MATCH}, + + // Group of selectors (comma) + {name: "Syntax, group of selectors separator, surrounded by whitespace", selector: "#group em\t\r \n,\t\r \n#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Syntax, group of selectors separator, whitespace after", selector: "#group em,\t\r\n#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Syntax, group of selectors separator, whitespace before", selector: "#group em\t\r\n,#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH}, + {name: "Syntax, group of selectors separator, no whitespace", selector: "#group em,#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH}, +]; + + +/* + * These selectors are intended to be used with the find(), findAll() and matches() methods. Expected results + * should be determined under the assumption that :scope will be prepended to the selector where appropriate, + * in accordance with the specification. + * + * All of these should be valid relative selectors, expected to match zero or more elements in the document. + * None should throw any errors. + * + * name: A descriptive name of the selector being tested + * + * selector: The selector to test + * + * ctx: A selector to obtain the context object to use for tests invoking context.find(), + * and to use as a single reference node for tests invoking document.find(). + * Note: context = root.querySelector(ctx); + * + * ref: A selector to obtain the reference nodes to be used for the selector. + * Note: If root is the document or an in-document element: + * refNodes = document.querySelectorAll(ref); + * Otherwise, if root is a fragment or detached element: + * refNodes = root.querySelectorAll(ref); + * + * expect: A list of IDs of the elements expected to be matched. List must be given in tree order. + * + * unexpected: A list of IDs of some elements that are not expected to match the given selector. + * This is used to verify that unexpected.matches(selector, refNode) does not match. + * + * exclude: An array of contexts to exclude from testing. The valid values are: + * ["document", "element", "fragment", "detached", "html", "xhtml"] + * The "html" and "xhtml" values represent the type of document being queried. These are useful + * for tests that are affected by differences between HTML and XML, such as case sensitivity. + * + * level: An integer indicating the CSS or Selectors level in which the selector being tested was introduced. + * + * testType: A bit-mapped flag indicating the type of test. + * + * The test function for these tests accepts a specified root node, on which the methods will be invoked during the tests. + * + * Based on whether either 'context' or 'refNodes', or both, are specified the tests will execute the following methods: + * + * Where testType is TEST_FIND: + * + * context.findAll(selector, refNodes) + * context.findAll(selector) // Only if refNodes is not specified + * root.findAll(selector, context) // Only if refNodes is not specified + * root.findAll(selector, refNodes) // Only if context is not specified + * root.findAll(selector) // Only if neither context nor refNodes is specified + * + * Where testType is TEST_QSA + * + * context.querySelectorAll(selector) + * root.querySelectorAll(selector) // Only if neither context nor refNodes is specified + * + * Equivalent tests will be run for .find() as well. + * Note: Do not specify a testType of TEST_QSA where either implied :scope or explicit refNodes + * are required. + * + * Where testType is TEST_MATCH: + * For each expected result given, within the specified root: + * + * expect.matches(selector, context) // Only where refNodes is not specified + * expect.matches(selector, refNodes) + * expect.matches(selector) // Only if neither context nor refNodes is specified + * + * The tests involving refNodes for both find(), findAll() and matches() will each be run by passing the + * collection as a NodeList, an Array and, if there is only a single element, an Element node. + * + * Note: Interactive pseudo-classes (:active :hover and :focus) have not been tested in this test suite. + */ + +var scopedSelectors = [ + //{name: "", selector: "", ctx: "", ref: "", expect: [], level: 1, testType: TEST_FIND | TEST_MATCH}, + + // Universal Selector + {name: "Universal selector, matching all children of the specified reference element", selector: ">*", ctx: "#universal", expect: ["universal-p1", "universal-hr1", "universal-pre1", "universal-p2", "universal-address1"], unexpected: ["universal", "empty"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Universal selector, matching all grandchildren of the specified reference element", selector: ">*>*", ctx: "#universal", expect: ["universal-code1", "universal-span1", "universal-a1", "universal-code2"], unexpected: ["universal", "empty"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Universal selector, matching all children of the specified empty reference element", selector: ">*", ctx: "#empty", expect: [] /*no matches*/, unexpected: ["universal", "empty"], level: 2, testType: TEST_QSA}, + {name: "Universal selector, matching all descendants of the specified reference element", selector: "*", ctx: "#universal", expect: ["universal-p1", "universal-code1", "universal-hr1", "universal-pre1", "universal-span1", + "universal-p2", "universal-a1", "universal-address1", "universal-code2", "universal-a2"], unexpected: ["universal", "empty"], level: 2, testType: TEST_FIND | TEST_MATCH}, + + // Attribute Selectors + // - presence [att] + {name: "Attribute presence selector, matching align attribute with value", selector: ".attr-presence-div1[align]", ctx: "#attr-presence", expect: ["attr-presence-div1"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute presence selector, matching align attribute with empty value", selector: ".attr-presence-div2[align]", ctx: "#attr-presence", expect: ["attr-presence-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute presence selector, matching title attribute, case insensitivity", selector: "[TiTlE]", ctx: "#attr-presence", expect: ["attr-presence-a1", "attr-presence-span1"], exclude: ["xhtml"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute presence selector, not matching title attribute, case sensitivity", selector: "[TiTlE]", ctx: "#attr-presence", expect: [], exclude: ["html"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute presence selector, matching custom data-* attribute", selector: "[data-attr-presence]", ctx: "#attr-presence", expect: ["attr-presence-pre1", "attr-presence-blockquote1"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute presence selector, not matching attribute with similar name", selector: ".attr-presence-div3[align], .attr-presence-div4[align]", ctx: "#attr-presence", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "Attribute presence selector, matching attribute with non-ASCII characters", selector: "ul[data-中文]", ctx: "#attr-presence", expect: ["attr-presence-ul1"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute presence selector, not matching default option without selected attribute", selector: "#attr-presence-select1 option[selected]", ctx: "#attr-presence", expect: [] /* no matches */, level: 2, testType: TEST_FIND}, + {name: "Attribute presence selector, matching option with selected attribute", selector: "#attr-presence-select2 option[selected]", ctx: "#attr-presence", expect: ["attr-presence-select2-option4"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute presence selector, matching multiple options with selected attributes", selector: "#attr-presence-select3 option[selected]", ctx: "#attr-presence", expect: ["attr-presence-select3-option2", "attr-presence-select3-option3"], level: 2, testType: TEST_FIND | TEST_MATCH}, + + // - value [att=val] + {name: "Attribute value selector, matching align attribute with value", selector: "[align=\"center\"]", ctx: "#attr-value", expect: ["attr-value-div1"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute value selector, matching align attribute with empty value", selector: "[align=\"\"]", ctx: "#attr-value", expect: ["attr-value-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute value selector, not matching align attribute with partial value", selector: "[align=\"c\"]", ctx: "#attr-value", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "Attribute value selector, not matching align attribute with incorrect value", selector: "[align=\"centera\"]", ctx: "#attr-value", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "Attribute value selector, matching custom data-* attribute with unicode escaped value", selector: "[data-attr-value=\"\\e9\"]", ctx: "#attr-value", expect: ["attr-value-div3"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute value selector, matching custom data-* attribute with escaped character", selector: "[data-attr-value\_foo=\"\\e9\"]", ctx: "#attr-value", expect: ["attr-value-div4"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute value selector with single-quoted value, matching multiple inputs with type attributes", selector: "input[type='hidden'],#attr-value input[type='radio']", ctx: "#attr-value", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute value selector with double-quoted value, matching multiple inputs with type attributes", selector: "input[type=\"hidden\"],#attr-value input[type='radio']", ctx: "#attr-value", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute value selector with unquoted value, matching multiple inputs with type attributes", selector: "input[type=hidden],#attr-value input[type=radio]", ctx: "#attr-value", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute value selector, matching attribute with value using non-ASCII characters", selector: "[data-attr-value=中文]", ctx: "#attr-value", expect: ["attr-value-div5"], level: 2, testType: TEST_FIND | TEST_MATCH}, + + // - whitespace-separated list [att~=val] + {name: "Attribute whitespace-separated list selector, matching class attribute with value", selector: "[class~=\"div1\"]", ctx: "#attr-whitespace", expect: ["attr-whitespace-div1"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector, not matching class attribute with empty value", selector: "[class~=\"\"]", ctx: "#attr-whitespace", expect: [] /*no matches*/ , level: 2, testType: TEST_FIND}, + {name: "Attribute whitespace-separated list selector, not matching class attribute with partial value", selector: "[data-attr-whitespace~=\"div\"]", ctx: "#attr-whitespace", expect: [] /*no matches*/ , level: 2, testType: TEST_FIND}, + {name: "Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value", selector: "[data-attr-whitespace~=\"\\0000e9\"]", ctx: "#attr-whitespace", expect: ["attr-whitespace-div4"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character", selector: "[data-attr-whitespace\_foo~=\"\\e9\"]", ctx: "#attr-whitespace", expect: ["attr-whitespace-div5"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes", selector: "a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow']", ctx: "#attr-whitespace", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes", selector: "a[rel~=\"bookmark\"],#attr-whitespace a[rel~='nofollow']", ctx: "#attr-whitespace", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes", selector: "a[rel~=bookmark], #attr-whitespace a[rel~=nofollow]", ctx: "#attr-whitespace", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute whitespace-separated list selector with double-quoted value, not matching value with space", selector: "a[rel~=\"book mark\"]", ctx: "#attr-whitespace", expect: [] /* no matches */, level: 2, testType: TEST_FIND}, + {name: "Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters", selector: "[title~=中文]", ctx: "#attr-whitespace", expect: ["attr-whitespace-p1"], level: 2, testType: TEST_FIND | TEST_MATCH}, + + // - hyphen-separated list [att|=val] + {name: "Attribute hyphen-separated list selector, not matching unspecified lang attribute", selector: "#attr-hyphen-div1[lang|=\"en\"]", ctx: "#attr-hyphen", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "Attribute hyphen-separated list selector, matching lang attribute with exact value", selector: "#attr-hyphen-div2[lang|=\"fr\"]", ctx: "#attr-hyphen", expect: ["attr-hyphen-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute hyphen-separated list selector, matching lang attribute with partial value", selector: "#attr-hyphen-div3[lang|=\"en\"]", ctx: "#attr-hyphen", expect: ["attr-hyphen-div3"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute hyphen-separated list selector, not matching incorrect value", selector: "#attr-hyphen-div4[lang|=\"es-AR\"]", ctx: "#attr-hyphen", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + + // - substring begins-with [att^=val] (Level 3) + {name: "Attribute begins with selector, matching href attributes beginning with specified substring", selector: "a[href^=\"http://www\"]", ctx: "#attr-begins", expect: ["attr-begins-a1", "attr-begins-a3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute begins with selector, matching lang attributes beginning with specified substring, ", selector: "[lang^=\"en-\"]", ctx: "#attr-begins", expect: ["attr-begins-div2", "attr-begins-div4"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute begins with selector, not matching class attribute not beginning with specified substring", selector: "[class^=apple]", ctx: "#attr-begins", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + {name: "Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring", selector: "[class^=' apple']", ctx: "#attr-begins", expect: ["attr-begins-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring", selector: "[class^=\" apple\"]", ctx: "#attr-begins", expect: ["attr-begins-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring", selector: "[class^= apple]", ctx: "#attr-begins", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + + // - substring ends-with [att$=val] (Level 3) + {name: "Attribute ends with selector, matching href attributes ending with specified substring", selector: "a[href$=\".org\"]", ctx: "#attr-ends", expect: ["attr-ends-a1", "attr-ends-a3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute ends with selector, matching lang attributes ending with specified substring, ", selector: "[lang$=\"-CH\"]", ctx: "#attr-ends", expect: ["attr-ends-div2", "attr-ends-div4"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute ends with selector, not matching class attribute not ending with specified substring", selector: "[class$=apple]", ctx: "#attr-ends", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + {name: "Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring", selector: "[class$='apple ']", ctx: "#attr-ends", expect: ["attr-ends-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring", selector: "[class$=\"apple \"]", ctx: "#attr-ends", expect: ["attr-ends-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring", selector: "[class$=apple ]", ctx: "#attr-ends", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + + // - substring contains [att*=val] (Level 3) + {name: "Attribute contains selector, matching href attributes beginning with specified substring", selector: "a[href*=\"http://www\"]", ctx: "#attr-contains", expect: ["attr-contains-a1", "attr-contains-a3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector, matching href attributes ending with specified substring", selector: "a[href*=\".org\"]", ctx: "#attr-contains", expect: ["attr-contains-a1", "attr-contains-a2"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector, matching href attributes containing specified substring", selector: "a[href*=\".example.\"]", ctx: "#attr-contains", expect: ["attr-contains-a1", "attr-contains-a3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector, matching lang attributes beginning with specified substring, ", selector: "[lang*=\"en-\"]", ctx: "#attr-contains", expect: ["attr-contains-div2", "attr-contains-div6"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector, matching lang attributes ending with specified substring, ", selector: "[lang*=\"-CH\"]", ctx: "#attr-contains", expect: ["attr-contains-div3", "attr-contains-div5"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring", selector: "[class*=' apple']", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector with single-quoted value, matching class attribute ending with specified substring", selector: "[class*='orange ']", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector with single-quoted value, matching class attribute containing specified substring", selector: "[class*='ple banana ora']", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring", selector: "[class*=\" apple\"]", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector with double-quoted value, matching class attribute ending with specified substring", selector: "[class*=\"orange \"]", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector with double-quoted value, matching class attribute containing specified substring", selector: "[class*=\"ple banana ora\"]", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector with unquoted value, matching class attribute beginning with specified substring", selector: "[class*= apple]", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector with unquoted value, matching class attribute ending with specified substring", selector: "[class*=orange ]", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "Attribute contains selector with unquoted value, matching class attribute containing specified substring", selector: "[class*= banana ]", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // Pseudo-classes + // - :root (Level 3) + {name: ":root pseudo-class selector, matching document root element", selector: ":root", expect: ["html"], exclude: ["element", "fragment", "detached"], level: 3, testType: TEST_FIND}, + {name: ":root pseudo-class selector, not matching document root element", selector: ":root", expect: [] /*no matches*/, exclude: ["document"], level: 3, testType: TEST_FIND}, + {name: ":root pseudo-class selector, not matching document root element", selector: ":root", ctx: "#html", expect: [] /*no matches*/, exclude: ["fragment", "detached"], level: 3, testType: TEST_FIND}, + + // - :nth-child(n) (Level 3) + {name: ":nth-child selector, matching the third child element", selector: ":nth-child(3)", ctx: "#pseudo-nth-table1", expect: ["pseudo-nth-td3", "pseudo-nth-td9", "pseudo-nth-tr3", "pseudo-nth-td15"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-child selector, matching every third child element", selector: "li:nth-child(3n)", ctx: "#pseudo-nth", expect: ["pseudo-nth-li3", "pseudo-nth-li6", "pseudo-nth-li9", "pseudo-nth-li12"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-child selector, matching every second child element, starting from the fourth", selector: "li:nth-child(2n+4)", ctx: "#pseudo-nth", expect: ["pseudo-nth-li4", "pseudo-nth-li6", "pseudo-nth-li8", "pseudo-nth-li10", "pseudo-nth-li12"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-child selector, matching every fourth child element, starting from the third", selector: ":nth-child(4n-1)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em2", "pseudo-nth-span3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :nth-last-child (Level 3) + {name: ":nth-last-child selector, matching the third last child element", selector: ":nth-last-child(3)", ctx: "#pseudo-nth-table1", expect: ["pseudo-nth-tr1", "pseudo-nth-td4", "pseudo-nth-td10", "pseudo-nth-td16"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-last-child selector, matching every third child element from the end", selector: "li:nth-last-child(3n)", ctx: "pseudo-nth", expect: ["pseudo-nth-li1", "pseudo-nth-li4", "pseudo-nth-li7", "pseudo-nth-li10"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-last-child selector, matching every second child element from the end, starting from the fourth last", selector: "li:nth-last-child(2n+4)", ctx: "pseudo-nth", expect: ["pseudo-nth-li1", "pseudo-nth-li3", "pseudo-nth-li5", "pseudo-nth-li7", "pseudo-nth-li9"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-last-child selector, matching every fourth element from the end, starting from the third last", selector: ":nth-last-child(4n-1)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span2", "pseudo-nth-span4"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :nth-of-type(n) (Level 3) + {name: ":nth-of-type selector, matching the third em element", selector: "em:nth-of-type(3)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-of-type selector, matching every second element of their type", selector: ":nth-of-type(2n)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em2", "pseudo-nth-span2", "pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-of-type selector, matching every second elemetn of their type, starting from the first", selector: "span:nth-of-type(2n-1)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span1", "pseudo-nth-span3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :nth-last-of-type(n) (Level 3) + {name: ":nth-last-of-type selector, matching the thrid last em element", selector: "em:nth-last-of-type(3)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em2"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-last-of-type selector, matching every second last element of their type", selector: ":nth-last-of-type(2n)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1", "pseudo-nth-em3", "pseudo-nth-span3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":nth-last-of-type selector, matching every second last element of their type, starting from the last", selector: "span:nth-last-of-type(2n-1)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span2", "pseudo-nth-span4"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :first-of-type (Level 3) + {name: ":first-of-type selector, matching the first em element", selector: "em:first-of-type", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":first-of-type selector, matching the first of every type of element", selector: ":first-of-type", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":first-of-type selector, matching the first td element in each table row", selector: "tr :first-of-type", ctx: "#pseudo-nth-table1", expect: ["pseudo-nth-td1", "pseudo-nth-td7", "pseudo-nth-td13"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :last-of-type (Level 3) + {name: ":last-of-type selector, matching the last em elemnet", selector: "em:last-of-type", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em4"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":last-of-type selector, matching the last of every type of element", selector: ":last-of-type", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":last-of-type selector, matching the last td element in each table row", selector: "tr :last-of-type", ctx: "#pseudo-nth-table1", expect: ["pseudo-nth-td6", "pseudo-nth-td12", "pseudo-nth-td18"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :first-child + {name: ":first-child pseudo-class selector, matching first child div element", selector: "div:first-child", ctx: "#pseudo-first-child", expect: ["pseudo-first-child-div1"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: ":first-child pseudo-class selector, doesn't match non-first-child elements", selector: ".pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child", ctx: "#pseudo-first-child", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: ":first-child pseudo-class selector, matching first-child of multiple elements", selector: "span:first-child", ctx: "#pseudo-first-child", expect: ["pseudo-first-child-span1", "pseudo-first-child-span3", "pseudo-first-child-span5"], level: 2, testType: TEST_FIND | TEST_MATCH}, + + // - :last-child (Level 3) + {name: ":last-child pseudo-class selector, matching last child div element", selector: "div:last-child", ctx: "#pseudo-last-child", expect: ["pseudo-last-child-div3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":last-child pseudo-class selector, doesn't match non-last-child elements", selector: ".pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child", ctx: "#pseudo-last-child", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + {name: ":last-child pseudo-class selector, matching first-child of multiple elements", selector: "span:last-child", ctx: "#pseudo-last-child", expect: ["pseudo-last-child-span2", "pseudo-last-child-span4", "pseudo-last-child-span6"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :only-child (Level 3) + {name: ":pseudo-only-child pseudo-class selector, matching all only-child elements", selector: ":only-child", ctx: "#pseudo-only", expect: ["pseudo-only-span1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":pseudo-only-child pseudo-class selector, matching only-child em elements", selector: "em:only-child", ctx: "#pseudo-only", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + + // - :only-of-type (Level 3) + {name: ":pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type", selector: " :only-of-type", ctx: "#pseudo-only", expect: ["pseudo-only-span1", "pseudo-only-em1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type", selector: " em:only-of-type", ctx: "#pseudo-only", expect: ["pseudo-only-em1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :empty (Level 3) + {name: ":empty pseudo-class selector, matching empty p elements", selector: "p:empty", ctx: "#pseudo-empty", expect: ["pseudo-empty-p1", "pseudo-empty-p2"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":empty pseudo-class selector, matching all empty elements", selector: ":empty", ctx: "#pseudo-empty", expect: ["pseudo-empty-p1", "pseudo-empty-p2", "pseudo-empty-span1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :link and :visited + // Implementations may treat all visited links as unvisited, so these cannot be tested separately. + // The only guarantee is that ":link,:visited" matches the set of all visited and unvisited links and that they are individually mutually exclusive sets. + {name: ":link and :visited pseudo-class selectors, matching a and area elements with href attributes", selector: " :link, #pseudo-link :visited", ctx: "#pseudo-link", expect: ["pseudo-link-a1", "pseudo-link-a2", "pseudo-link-area1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: ":link and :visited pseudo-class selectors, matching link elements with href attributes", selector: " :link, #head :visited", ctx: "#head", expect: ["pseudo-link-link1", "pseudo-link-link2"], exclude: ["element", "fragment", "detached"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: ":link and :visited pseudo-class selectors, not matching link elements with href attributes", selector: " :link, #head :visited", ctx: "#head", expect: [] /*no matches*/, exclude: ["document"], level: 1, testType: TEST_FIND}, + {name: ":link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing", selector: ":link:visited", ctx: "#html", expect: [] /*no matches*/, exclude: ["document"], level: 1, testType: TEST_FIND}, + +// XXX Figure out context or refNodes for this + // - :target (Level 3) + {name: ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", selector: ":target", ctx: "", expect: [] /*no matches*/, exclude: ["document", "element"], level: 3, testType: TEST_FIND}, + {name: ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", selector: ":target", ctx: "", expect: ["target"], exclude: ["fragment", "detached"], level: 3, testType: TEST_FIND}, + +// XXX Fix ctx in tests below + + // - :lang() + {name: ":lang pseudo-class selector, matching inherited language (1)", selector: "#pseudo-lang-div1:lang(en)", ctx: "", expect: ["pseudo-lang-div1"], exclude: ["detached", "fragment"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: ":lang pseudo-class selector, not matching element with no inherited language", selector: "#pseudo-lang-div1:lang(en)", ctx: "", expect: [] /*no matches*/, exclude: ["document", "element"], level: 2, testType: TEST_FIND}, + {name: ":lang pseudo-class selector, matching specified language with exact value (1)", selector: "#pseudo-lang-div2:lang(fr)", ctx: "", expect: ["pseudo-lang-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: ":lang pseudo-class selector, matching specified language with partial value (1)", selector: "#pseudo-lang-div3:lang(en)", ctx: "", expect: ["pseudo-lang-div3"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: ":lang pseudo-class selector, not matching incorrect language", selector: "#pseudo-lang-div4:lang(es-AR)", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + + // - :enabled (Level 3) + {name: ":enabled pseudo-class selector, matching all enabled form controls (1)", selector: "#pseudo-ui :enabled", ctx: "", expect: ["pseudo-ui-input1", "pseudo-ui-input2", "pseudo-ui-input3", "pseudo-ui-input4", "pseudo-ui-input5", "pseudo-ui-input6", + "pseudo-ui-input7", "pseudo-ui-input8", "pseudo-ui-input9", "pseudo-ui-textarea1", "pseudo-ui-button1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :disabled (Level 3) + {name: ":enabled pseudo-class selector, matching all disabled form controls (1)", selector: "#pseudo-ui :disabled", ctx: "", expect: ["pseudo-ui-input10", "pseudo-ui-input11", "pseudo-ui-input12", "pseudo-ui-input13", "pseudo-ui-input14", "pseudo-ui-input15", + "pseudo-ui-input16", "pseudo-ui-input17", "pseudo-ui-input18", "pseudo-ui-textarea2", "pseudo-ui-button2"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :checked (Level 3) + {name: ":checked pseudo-class selector, matching checked radio buttons and checkboxes (1)", selector: "#pseudo-ui :checked", ctx: "", expect: ["pseudo-ui-input4", "pseudo-ui-input6", "pseudo-ui-input13", "pseudo-ui-input15"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // - :not(s) (Level 3) + {name: ":not pseudo-class selector, matching (1)", selector: "#not>:not(div)", ctx: "", expect: ["not-p1", "not-p2", "not-p3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":not pseudo-class selector, matching (1)", selector: "#not * :not(:first-child)", ctx: "", expect: ["not-em1", "not-em2", "not-em3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":not pseudo-class selector, matching nothing", selector: ":not(*)", ctx: "", expect: [] /* no matches */, level: 3, testType: TEST_FIND}, + {name: ":not pseudo-class selector, matching nothing", selector: ":not(*|*)", ctx: "", expect: [] /* no matches */, level: 3, testType: TEST_FIND}, + + // Pseudo-elements + // - ::first-line + {name: ":first-line pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:first-line", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "::first-line pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::first-line", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + + // - ::first-letter + {name: ":first-letter pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:first-letter", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "::first-letter pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::first-letter", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + + // - ::before + {name: ":before pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:before", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "::before pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::before", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + + // - ::after + {name: ":after pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:after", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "::after pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::after", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + + // Class Selectors + {name: "Class selector, matching element with specified class (1)", selector: ".class-p", ctx: "", expect: ["class-p1","class-p2", "class-p3"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Class selector, chained, matching only elements with all specified classes (1)", selector: "#class .apple.orange.banana", ctx: "", expect: ["class-div1", "class-div2", "class-p4", "class-div3", "class-p6", "class-div4"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Class Selector, chained, with type selector (1)", selector: "div.apple.banana.orange", ctx: "", expect: ["class-div1", "class-div2", "class-div3", "class-div4"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Class selector, matching element with class value using non-ASCII characters (2)", selector: ".\u53F0\u5317Ta\u0301ibe\u030Ci", ctx: "", expect: ["class-span1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Class selector, matching multiple elements with class value using non-ASCII characters (1)", selector: ".\u53F0\u5317", ctx: "", expect: ["class-span1","class-span2"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Class selector, chained, matching element with multiple class values using non-ASCII characters (2)", selector: ".\u53F0\u5317Ta\u0301ibe\u030Ci.\u53F0\u5317", ctx: "", expect: ["class-span1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Class selector, matching element with class with escaped character (1)", selector: ".foo\\:bar", ctx: "", expect: ["class-span3"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Class selector, matching element with class with escaped character (1)", selector: ".test\\.foo\\[5\\]bar", ctx: "", expect: ["class-span4"], level: 1, testType: TEST_FIND | TEST_MATCH}, + + // ID Selectors + {name: "ID selector, matching element with specified id (1)", selector: "#id #id-div1", ctx: "", expect: ["id-div1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "ID selector, chained, matching element with specified id (1)", selector: "#id-div1, #id-div1", ctx: "", expect: ["id-div1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "ID selector, chained, matching element with specified id (1)", selector: "#id-div1, #id-div2", ctx: "", expect: ["id-div1", "id-div2"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "ID Selector, chained, with type selector (1)", selector: "div#id-div1, div#id-div2", ctx: "", expect: ["id-div1", "id-div2"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "ID selector, not matching non-existent descendant", selector: "#id #none", ctx: "", expect: [] /*no matches*/, level: 1, testType: TEST_FIND}, + {name: "ID selector, not matching non-existent ancestor", selector: "#none #id-div1", ctx: "", expect: [] /*no matches*/, level: 1, testType: TEST_FIND}, + {name: "ID selector, matching multiple elements with duplicate id (1)", selector: "#id-li-duplicate", ctx: "", expect: ["id-li-duplicate", "id-li-duplicate", "id-li-duplicate", "id-li-duplicate"], level: 1, testType: TEST_FIND | TEST_MATCH}, + + {name: "ID selector, matching id value using non-ASCII characters (3)", selector: "#\u53F0\u5317Ta\u0301ibe\u030Ci", ctx: "", expect: ["\u53F0\u5317Ta\u0301ibe\u030Ci"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "ID selector, matching id value using non-ASCII characters (4)", selector: "#\u53F0\u5317", ctx: "", expect: ["\u53F0\u5317"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "ID selector, matching id values using non-ASCII characters (2)", selector: "#\u53F0\u5317Ta\u0301ibe\u030Ci, #\u53F0\u5317", ctx: "", expect: ["\u53F0\u5317Ta\u0301ibe\u030Ci", "\u53F0\u5317"], level: 1, testType: TEST_FIND | TEST_MATCH}, + + // XXX runMatchesTest() in level2-lib.js can't handle this because obtaining the expected nodes requires escaping characters when generating the selector from 'expect' values + {name: "ID selector, matching element with id with escaped character", selector: "#\\#foo\\:bar", ctx: "", expect: ["#foo:bar"], level: 1, testType: TEST_FIND}, + {name: "ID selector, matching element with id with escaped character", selector: "#test\\.foo\\[5\\]bar", ctx: "", expect: ["test.foo[5]bar"], level: 1, testType: TEST_FIND}, + + // Namespaces + // XXX runMatchesTest() in level2-lib.js can't handle these because non-HTML elements don't have a recognised id + {name: "Namespace selector, matching element with any namespace", selector: "#any-namespace *|div", ctx: "", expect: ["any-namespace-div1", "any-namespace-div2", "any-namespace-div3", "any-namespace-div4"], level: 3, testType: TEST_FIND}, + {name: "Namespace selector, matching div elements in no namespace only", selector: "#no-namespace |div", ctx: "", expect: ["no-namespace-div3"], level: 3, testType: TEST_FIND}, + {name: "Namespace selector, matching any elements in no namespace only", selector: "#no-namespace |*", ctx: "", expect: ["no-namespace-div3"], level: 3, testType: TEST_FIND}, + + // Combinators + // - Descendant combinator ' ' + {name: "Descendant combinator, matching element that is a descendant of an element with id (1)", selector: "#descendant div", ctx: "", expect: ["descendant-div1", "descendant-div2", "descendant-div3", "descendant-div4"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Descendant combinator, matching element with id that is a descendant of an element (1)", selector: "body #descendant-div1", ctx: "", expect: ["descendant-div1"], exclude: ["detached", "fragment"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Descendant combinator, matching element with id that is a descendant of an element (1)", selector: "div #descendant-div1", ctx: "", expect: ["descendant-div1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Descendant combinator, matching element with id that is a descendant of an element with id (1)", selector: "#descendant #descendant-div2", ctx: "", expect: ["descendant-div2"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Descendant combinator, matching element with class that is a descendant of an element with id (1)", selector: "#descendant .descendant-div2", ctx: "", expect: ["descendant-div2"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Descendant combinator, matching element with class that is a descendant of an element with class (1)", selector: ".descendant-div1 .descendant-div3", ctx: "", expect: ["descendant-div3"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Descendant combinator, not matching element with id that is not a descendant of an element with id", selector: "#descendant-div1 #descendant-div4", ctx: "", expect: [] /*no matches*/, level: 1, testType: TEST_FIND}, + {name: "Descendant combinator, whitespace characters (1)", selector: "#descendant\t\r\n#descendant-div2", ctx: "", expect: ["descendant-div2"], level: 1, testType: TEST_FIND | TEST_MATCH}, + + // - Descendant combinator '>>' + {name: "Descendant combinator '>>', matching element that is a descendant of an element with id (1)", selector: "#descendant>>div", ctx: "", expect: ["descendant-div1", "descendant-div2", "descendant-div3", "descendant-div4"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Descendant combinator '>>', matching element with id that is a descendant of an element (1)", selector: "body>>#descendant-div1", ctx: "", expect: ["descendant-div1"], exclude: ["detached", "fragment"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Descendant combinator '>>', matching element with id that is a descendant of an element (1)", selector: "div>>#descendant-div1", ctx: "", expect: ["descendant-div1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Descendant combinator '>>', matching element with id that is a descendant of an element with id (1)", selector: "#descendant>>#descendant-div2", ctx: "", expect: ["descendant-div2"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Descendant combinator '>>', matching element with class that is a descendant of an element with id (1)", selector: "#descendant>>.descendant-div2", ctx: "", expect: ["descendant-div2"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Descendant combinator, '>>', matching element with class that is a descendant of an element with class (1)", selector: ".descendant-div1>>.descendant-div3", ctx: "", expect: ["descendant-div3"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Descendant combinator '>>', not matching element with id that is not a descendant of an element with id", selector: "#descendant-div1>>#descendant-div4", ctx: "", expect: [] /*no matches*/, level: 1, testType: TEST_FIND}, + + // - Child combinator '>' + {name: "Child combinator, matching element that is a child of an element with id (1)", selector: "#child>div", ctx: "", expect: ["child-div1", "child-div4"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Child combinator, matching element with id that is a child of an element (1)", selector: "div>#child-div1", ctx: "", expect: ["child-div1"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Child combinator, matching element with id that is a child of an element with id (1)", selector: "#child>#child-div1", ctx: "", expect: ["child-div1"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Child combinator, matching element with id that is a child of an element with class (1)", selector: "#child-div1>.child-div2", ctx: "", expect: ["child-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Child combinator, matching element with class that is a child of an element with class (1)", selector: ".child-div1>.child-div2", ctx: "", expect: ["child-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Child combinator, not matching element with id that is not a child of an element with id", selector: "#child>#child-div3", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "Child combinator, not matching element with id that is not a child of an element with class", selector: "#child-div1>.child-div3", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "Child combinator, not matching element with class that is not a child of an element with class", selector: ".child-div1>.child-div3", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "Child combinator, surrounded by whitespace (1)", selector: "#child-div1\t\r\n>\t\r\n#child-div2", ctx: "", expect: ["child-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Child combinator, whitespace after (1)", selector: "#child-div1>\t\r\n#child-div2", ctx: "", expect: ["child-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Child combinator, whitespace before (1)", selector: "#child-div1\t\r\n>#child-div2", ctx: "", expect: ["child-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Child combinator, no whitespace (1)", selector: "#child-div1>#child-div2", ctx: "", expect: ["child-div2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + + // - Adjacent sibling combinator '+' + {name: "Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id (1)", selector: "#adjacent-div2+div", ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element (1)", selector: "div+#adjacent-div4", ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id (1)", selector: "#adjacent-div2+#adjacent-div4", ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id (1)", selector: "#adjacent-div2+.adjacent-div4", ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class (1)", selector: ".adjacent-div2+.adjacent-div4", ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element (1)", selector: "#adjacent div+p", ctx: "", expect: ["adjacent-p2"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id", selector: "#adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND}, + {name: "Adjacent sibling combinator, surrounded by whitespace (1)", selector: "#adjacent-p2\t\r\n+\t\r\n#adjacent-p3", ctx: "", expect: ["adjacent-p3"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Adjacent sibling combinator, whitespace after (1)", selector: "#adjacent-p2+\t\r\n#adjacent-p3", ctx: "", expect: ["adjacent-p3"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Adjacent sibling combinator, whitespace before (1)", selector: "#adjacent-p2\t\r\n+#adjacent-p3", ctx: "", expect: ["adjacent-p3"], level: 2, testType: TEST_FIND | TEST_MATCH}, + {name: "Adjacent sibling combinator, no whitespace (1)", selector: "#adjacent-p2+#adjacent-p3", ctx: "", expect: ["adjacent-p3"], level: 2, testType: TEST_FIND | TEST_MATCH}, + + // - General sibling combinator ~ (Level 3) + {name: "General sibling combinator, matching element that is a sibling of an element with id (1)", selector: "#sibling-div2~div", ctx: "", expect: ["sibling-div4", "sibling-div6"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "General sibling combinator, matching element with id that is a sibling of an element (1)", selector: "div~#sibling-div4", ctx: "", expect: ["sibling-div4"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "General sibling combinator, matching element with id that is a sibling of an element with id (1)", selector: "#sibling-div2~#sibling-div4", ctx: "", expect: ["sibling-div4"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "General sibling combinator, matching element with class that is a sibling of an element with id (1)", selector: "#sibling-div2~.sibling-div", ctx: "", expect: ["sibling-div4", "sibling-div6"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "General sibling combinator, matching p element that is a sibling of a div element (1)", selector: "#sibling div~p", ctx: "", expect: ["sibling-p2", "sibling-p3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "General sibling combinator, not matching element with id that is not a sibling after a p element (1)", selector: "#sibling>p~div", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + {name: "General sibling combinator, not matching element with id that is not a sibling after an element with id", selector: "#sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND}, + {name: "General sibling combinator, surrounded by whitespace (1)", selector: "#sibling-p2\t\r\n~\t\r\n#sibling-p3", ctx: "", expect: ["sibling-p3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "General sibling combinator, whitespace after (1)", selector: "#sibling-p2~\t\r\n#sibling-p3", ctx: "", expect: ["sibling-p3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "General sibling combinator, whitespace before (1)", selector: "#sibling-p2\t\r\n~#sibling-p3", ctx: "", expect: ["sibling-p3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: "General sibling combinator, no whitespace (1)", selector: "#sibling-p2~#sibling-p3", ctx: "", expect: ["sibling-p3"], level: 3, testType: TEST_FIND | TEST_MATCH}, + + // Group of selectors (comma) + {name: "Syntax, group of selectors separator, surrounded by whitespace (1)", selector: "#group em\t\r \n,\t\r \n#group strong", ctx: "", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Syntax, group of selectors separator, whitespace after (1)", selector: "#group em,\t\r\n#group strong", ctx: "", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Syntax, group of selectors separator, whitespace before (1)", selector: "#group em\t\r\n,#group strong", ctx: "", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_FIND | TEST_MATCH}, + {name: "Syntax, group of selectors separator, no whitespace (1)", selector: "#group em,#group strong", ctx: "", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_FIND | TEST_MATCH}, +]; |