summaryrefslogtreecommitdiff
path: root/dom/base/test/test_classList.html
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base/test/test_classList.html')
-rw-r--r--dom/base/test/test_classList.html426
1 files changed, 426 insertions, 0 deletions
diff --git a/dom/base/test/test_classList.html b/dom/base/test/test_classList.html
new file mode 100644
index 0000000000..2a108d7f55
--- /dev/null
+++ b/dom/base/test/test_classList.html
@@ -0,0 +1,426 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=501257
+-->
+<head>
+ <title>Test for the classList element attribute</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="http://www.whatwg.org/specs/web-apps/current-work/#dom-classlist">classList DOM attribute</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 501257 **/
+
+const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+const SVG_NS = "http://www.w3.org/2000/svg";
+const XHTML_NS = "http://www.w3.org/1999/xhtml"
+const MATHML_NS = "http://www.w3.org/1998/Math/MathML";
+
+var gMutationEvents = [];
+
+function onAttrModified(event) {
+ is(event.attrName, "class", "mutation on unexpected attribute");
+
+ gMutationEvents.push({
+ attrChange: event.attrChange,
+ prevValue: event.prevValue,
+ newValue: event.newValue,
+ });
+}
+
+function checkModification(e, funcName, args, expectedRes, before, after, expectedException) {
+ if (!Array.isArray(args)) {
+ args = [args];
+ }
+
+ var shouldThrow = typeof(expectedException) === "string";
+ if (shouldThrow) {
+ // If an exception is thrown, the class attribute shouldn't change.
+ after = before;
+ }
+ if (before === null)
+ e.removeAttribute("class");
+ else
+ e.setAttribute("class", before);
+
+ var contextMsg = "(checkModification: funcName=" + funcName + ",args=" +
+ JSON.stringify(args) + ",expectedRes=" + expectedRes +
+ ",before=" + before + ",after=" + after + ")";
+
+ gMutationEvents = [];
+ e.addEventListener("DOMAttrModified", onAttrModified, false);
+ try {
+ var list = e.classList;
+ var res = list[funcName].apply(list, args);
+ if (shouldThrow)
+ ok(false, "classList modification didn't throw " + contextMsg);
+ } catch (e) {
+ if (!shouldThrow)
+ ok(false, "classList modification threw an exception " + contextMsg);
+ is(e.name, expectedException, "wrong exception thrown " + contextMsg);
+ }
+ e.removeEventListener("DOMAttrModified", onAttrModified, false);
+ if (expectedRes !== null)
+ is(res, expectedRes, "wrong return value from " + funcName +
+ " " + contextMsg);
+
+ var expectedAfter = after;
+ // XUL returns an empty string when getting a nonexistent class attribute.
+ if (e.namespaceURI == XUL_NS && expectedAfter === null)
+ expectedAfter = "";
+
+ is(e.getAttribute("class"), expectedAfter, "wrong class after modification " +
+ contextMsg);
+ var expectedMutation = before != after;
+ is(gMutationEvents.length, expectedMutation ? 1 : 0,
+ "unexpected mutation event count " + contextMsg);
+ if (expectedMutation && gMutationEvents.length) {
+ is(gMutationEvents[0].attrChange,
+ before == null ? MutationEvent.ADDITION : MutationEvent.MODIFICATION,
+ "wrong type of attribute change " + contextMsg);
+ // If there wasn't any previous attribute, prevValue will return an empty
+ // string.
+ var expectedPrevValue = before === null ? "" : before;
+ is(gMutationEvents[0].prevValue, expectedPrevValue,
+ "wrong previous value " + contextMsg);
+ is(gMutationEvents[0].newValue, after, "wrong new value " + contextMsg);
+ }
+}
+
+function assignToClassListStrict(e) {
+ "use strict";
+ try {
+ e.classList = "foo";
+ ok(true, "assigning to classList didn't throw");
+ e.removeAttribute("class");
+ } catch (e) {
+ ok(false, "assigning to classList threw");
+ }
+}
+
+function assignToClassList(e) {
+ try {
+ var expect = e.classList;
+ e.classList = "foo";
+ ok(true, "assigning to classList didn't throw");
+ is(e.classList, expect, "classList should be unchanged after assignment");
+ e.removeAttribute("class");
+ } catch (e) {
+ ok(false, "assigning to classList threw");
+ }
+}
+
+function testClassList(e) {
+
+ // basic tests
+
+ isnot(e.classList, undefined, "no classList attribute");
+ is(typeof(e.classList.contains), "function",
+ "no classList.contains function");
+ is(typeof(e.classList.add), "function", "no classList.add function");
+ is(typeof(e.classList.remove), "function", "no classList.remove function");
+ is(typeof(e.classList.toggle), "function", "no classList.toggle function");
+
+ assignToClassListStrict(e);
+ assignToClassList(e);
+
+ // length attribute
+
+ is(e.classList.length, 0, "wrong classList.length value");
+ e.setAttribute("class", "");
+ is(e.classList.length, 0, "wrong classList.length value");
+ e.setAttribute("class", " \t \f");
+ is(e.classList.length, 0, "wrong classList.length value");
+
+ e.setAttribute("class", "a");
+ is(e.classList.length, 1, "wrong classList.length value");
+ e.setAttribute("class", "a A");
+ is(e.classList.length, 2, "wrong classList.length value");
+ e.setAttribute("class", "\r\na\t\f");
+ is(e.classList.length, 1, "wrong classList.length value");
+
+ e.setAttribute("class", "a a");
+ is(e.classList.length, 2, "wrong classList.length value");
+
+ e.setAttribute("class", "a a a a a a");
+ is(e.classList.length, 6, "wrong classList.length value");
+
+ e.setAttribute("class", "a a b b");
+ is(e.classList.length, 4, "wrong classList.length value");
+
+ e.setAttribute("class", "a A B b");
+ is(e.classList.length, 4, "wrong classList.length value");
+
+ e.setAttribute("class", "a b c c b a a b c c");
+ is(e.classList.length, 10, "wrong classList.length value");
+
+ // [Stringifies]
+
+ ok(DOMTokenList.prototype.hasOwnProperty("toString"),
+ "Should have own toString on DOMTokenList")
+
+ e.removeAttribute("class");
+ is(e.classList.toString(), "", "wrong classList.toString() value");
+ is(e.classList + "", "", "wrong classList string conversion value");
+
+ e.setAttribute("class", "foo");
+ is(e.classList.toString(), "foo", "wrong classList.toString() value");
+ is(e.classList + "", "foo", "wrong classList string conversion value");
+
+ // item() method
+
+ e.setAttribute("class", "a");
+ is(e.classList.item(-1), null, "wrong classList.item() result");
+ is(e.classList[-1], undefined, "wrong classList[] result");
+ is(e.classList.item(0), "a", "wrong classList.item() result");
+ is(e.classList[0], "a", "wrong classList[] result");
+ is(e.classList.item(1), null, "wrong classList.item() result");
+ is(e.classList[1], undefined, "wrong classList[] result");
+
+ e.setAttribute("class", "aa AA aa");
+ is(e.classList.item(-1), null, "wrong classList.item() result");
+ is(e.classList[-1], undefined, "wrong classList[] result");
+ is(e.classList.item(0), "aa", "wrong classList.item() result");
+ is(e.classList[0], "aa", "wrong classList[] result");
+ is(e.classList.item(1), "AA", "wrong classList.item() result");
+ is(e.classList[1], "AA", "wrong classList[] result");
+ is(e.classList.item(2), "aa", "wrong classList.item() result");
+ is(e.classList[2], "aa", "wrong classList[] result");
+ is(e.classList.item(3), null, "wrong classList.item() result");
+ is(e.classList[3], undefined, "wrong classList[] result");
+ is(e.classList.item(0xffffffff), null, "wrong classList.item() result");
+ is(e.classList[0xffffffff], undefined, "wrong classList[] result");
+ is(e.classList.item(0xfffffffe), null, "wrong classList.item() result");
+ is(e.classList[0xffffffe], undefined, "wrong classList[] result");
+
+ e.setAttribute("class", "a b");
+ is(e.classList.item(-1), null, "wrong classList.item() result");
+ is(e.classList[-1], undefined, "wrong classList[] result");
+ is(e.classList.item(0), "a", "wrong classList.item() result");
+ is(e.classList[0], "a", "wrong classList[] result");
+ is(e.classList.item(1), "b", "wrong classList.item() result");
+ is(e.classList[1], "b", "wrong classList[] result");
+ is(e.classList.item(2), null, "wrong classList.item() result");
+ is(e.classList[2], undefined, "wrong classList[] result");
+
+ // contains() method
+
+ e.removeAttribute("class");
+ is(e.classList.contains("a"), false, "wrong classList.contains() result");
+ try {
+ e.classList.contains("");
+ ok(true, "classList.contains(empty_string) didn't throw");
+ } catch (e) {
+ ok(false, "classList.contains(empty_string) threw");
+ }
+ try {
+ e.classList.contains(" ");
+ ok(true, "classList.contains(string_with_spaces) didn't throw");
+ } catch (e) {
+ ok(false, "classList.contains(string_with_spaces) threw");
+ }
+ try {
+ e.classList.contains("aa ");
+ ok(true, "classList.contains(string_with_spaces) didn't throw");
+ } catch (e) {
+ ok(false, "classList.contains(string_with_spaces) threw");
+ }
+
+ e.setAttribute("class", "");
+ is(e.classList.contains("a"), false, "wrong classList.contains() result");
+
+ e.setAttribute("class", "a");
+ is(e.classList.contains("a"), true, "wrong classList.contains() result");
+ is(e.classList.contains("aa"), false, "wrong classList.contains() result");
+ is(e.classList.contains("b"), false, "wrong classList.contains() result");
+
+ e.setAttribute("class", "aa AA");
+ is(e.classList.contains("aa"), true, "wrong classList.contains() result");
+ is(e.classList.contains("AA"), true, "wrong classList.contains() result");
+ is(e.classList.contains("aA"), false, "wrong classList.contains() result");
+
+ e.setAttribute("class", "a a a");
+ is(e.classList.contains("a"), true, "wrong classList.contains() result");
+ is(e.classList.contains("aa"), false, "wrong classList.contains() result");
+ is(e.classList.contains("b"), false, "wrong classList.contains() result");
+
+ e.setAttribute("class", "a b c");
+ is(e.classList.contains("a"), true, "wrong classList.contains() result");
+ is(e.classList.contains("b"), true, "wrong classList.contains() result");
+
+ // Test for bug 530171
+ e.setAttribute("class", "null undefined");
+ is(e.classList.contains(null), true, "wrong classList.contains() result");
+ is(e.classList.contains(undefined), true, "wrong classList.contains() result");
+
+ // add() method
+
+ function checkAdd(before, argument, after, expectedException) {
+ checkModification(e, "add", argument, null, before, after, expectedException);
+ }
+
+ checkAdd(null, "", null, "SyntaxError");
+ checkAdd(null, ["a", ""], null, "SyntaxError");
+ checkAdd(null, " ", null, "InvalidCharacterError");
+ checkAdd(null, ["a", " "], null, "InvalidCharacterError");
+ checkAdd(null, ["a", "aa "], null, "InvalidCharacterError");
+
+ checkAdd("a", "a", "a");
+ checkAdd("aa", "AA", "aa AA");
+ checkAdd("a b c", "a", "a b c");
+ checkAdd("a a a b", "a", "a a a b");
+ checkAdd(null, "a", "a");
+ checkAdd("", "a", "a");
+ checkAdd(" ", "a", " a");
+ checkAdd(" \f", "a", " \fa");
+ checkAdd("a", "b", "a b");
+ checkAdd("a b c", "d", "a b c d");
+ checkAdd("a b c ", "d", "a b c d");
+
+ // multiple add
+ checkAdd("a b c ", ["d", "e"], "a b c d e");
+ checkAdd("a b c ", ["a", "a"], "a b c ");
+ checkAdd("a b c ", ["d", "d"], "a b c d");
+ checkAdd("a b c ", [], "a b c ");
+ checkAdd(null, ["a", "b"], "a b");
+ checkAdd("", ["a", "b"], "a b");
+
+ // Test for bug 530171
+ checkAdd(null, null, "null");
+ checkAdd(null, undefined, "undefined");
+
+ // remove() method
+
+ function checkRemove(before, argument, after, expectedException) {
+ checkModification(e, "remove", argument, null, before, after, expectedException);
+ }
+
+ checkRemove(null, "", null, "SyntaxError");
+ checkRemove(null, " ", null, "InvalidCharacterError");
+ checkRemove(null, "aa ", null, "InvalidCharacterError");
+
+ checkRemove(null, "a", null);
+ checkRemove("", "a", "");
+ checkRemove("a b c", "d", "a b c");
+ checkRemove("a b c", "A", "a b c");
+ checkRemove(" a a a ", "a", "");
+ checkRemove("a b", "a", "b");
+ checkRemove("a b ", "a", "b");
+ checkRemove("a a b", "a", "b");
+ checkRemove("aa aa bb", "aa", "bb");
+ checkRemove("a a b a a c a a", "a", "b c");
+
+ checkRemove("a b c", "b", "a c");
+ checkRemove("aaa bbb ccc", "bbb", "aaa ccc");
+ checkRemove(" a b c ", "b", "a c");
+ checkRemove("a b b b c", "b", "a c");
+
+ checkRemove("a b c", "c", "a b");
+ checkRemove(" a b c ", "c", "a b");
+ checkRemove("a b c c c", "c", "a b");
+
+ checkRemove("a b a c a d a", "a", "b c d");
+ checkRemove("AA BB aa CC AA dd aa", "AA", "BB aa CC dd aa");
+
+ checkRemove("\ra\na\ta\f", "a", "");
+
+ // multiple remove
+ checkRemove("a b c ", ["d", "e"], "a b c");
+ checkRemove("a b c ", ["a", "b"], "c");
+ checkRemove("a b c ", ["a", "c"], "b");
+ checkRemove("a b c ", ["a", "a"], "b c");
+ checkRemove("a b c ", ["d", "d"], "a b c");
+ checkRemove("a b c ", [], "a b c");
+ checkRemove(null, ["a", "b"], null);
+ checkRemove("", ["a", "b"], "");
+
+ // Test for bug 530171
+ checkRemove("null", null, "");
+ checkRemove("undefined", undefined, "");
+
+ // toggle() method
+
+ function checkToggle(before, argument, expectedRes, after, expectedException) {
+ checkModification(e, "toggle", argument, expectedRes, before, after, expectedException);
+ }
+
+ checkToggle(null, "", null, null, "SyntaxError");
+ checkToggle(null, "aa ", null, null, "InvalidCharacterError");
+
+ checkToggle(null, "a", true, "a");
+ checkToggle("", "a", true, "a");
+ checkToggle(" ", "a", true, " a");
+ checkToggle(" \f", "a", true, " \fa");
+ checkToggle("a", "b", true, "a b");
+ checkToggle("a", "A", true, "a A");
+ checkToggle("a b c", "d", true, "a b c d");
+ checkToggle("a b c", "d", true, "a b c d");
+
+ checkToggle("a", "a", false, "");
+ checkToggle(" a a a ", "a", false, "");
+ checkToggle(" A A A ", "a", true, " A A A a");
+ checkToggle(" a b c ", "b", false, "a c");
+ checkToggle(" a b c b b", "b", false, "a c");
+ checkToggle(" a b c ", "c", false, "a b");
+ checkToggle(" a b c ", "a", false, "b c");
+
+ // Test for bug 530171
+ checkToggle("null", null, false, "");
+ checkToggle("", null, true, "null");
+ checkToggle("undefined", undefined, false, "");
+ checkToggle("", undefined, true, "undefined");
+
+
+ // tests for the force argument handling
+
+ function checkForceToggle(before, argument, force, expectedRes, after, expectedException) {
+ checkModification(e, "toggle", [argument, force], expectedRes, before, after, expectedException);
+ }
+
+ checkForceToggle("", "a", true, true, "a");
+ checkForceToggle("a", "a", true, true, "a");
+ checkForceToggle("a", "b", true, true, "a b");
+ checkForceToggle("a b", "b", true, true, "a b");
+ checkForceToggle("", "a", false, false, "");
+ checkForceToggle("a", "a", false, false, "");
+ checkForceToggle("a", "b", false, false, "a");
+ checkForceToggle("a b", "b", false, false, "a");
+}
+
+var content = document.getElementById("content");
+
+var htmlNode = document.createElement("div");
+content.appendChild(htmlNode);
+testClassList(htmlNode);
+
+var xhtmlNode = document.createElementNS(XHTML_NS, "div");
+content.appendChild(xhtmlNode);
+testClassList(xhtmlNode);
+
+var xulNode = document.createElementNS(XUL_NS, "box");
+content.appendChild(xulNode);
+testClassList(xulNode);
+
+var mathMLNode = document.createElementNS(MATHML_NS, "math");
+content.appendChild(mathMLNode);
+testClassList(mathMLNode);
+
+var xmlNode = document.createElementNS(null, "foo");
+content.appendChild(xmlNode);
+testClassList(xmlNode);
+
+var fooNode = document.createElementNS("http://example.org/foo", "foo");
+content.appendChild(fooNode);
+testClassList(fooNode);
+
+</script>
+</pre>
+</body>
+</html>