content/base/test/test_classList.html

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/content/base/test/test_classList.html	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,429 @@
     1.4 +<!DOCTYPE HTML>
     1.5 +<html>
     1.6 +<!--
     1.7 +https://bugzilla.mozilla.org/show_bug.cgi?id=501257
     1.8 +-->
     1.9 +<head>
    1.10 +  <title>Test for the classList element attribute</title>
    1.11 +  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
    1.12 +  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
    1.13 +</head>
    1.14 +<body>
    1.15 +<a target="_blank" href="http://www.whatwg.org/specs/web-apps/current-work/#dom-classlist">classList DOM attribute</a>
    1.16 +<p id="display"></p>
    1.17 +<div id="content" style="display: none">
    1.18 +</div>
    1.19 +<pre id="test">
    1.20 +<script type="application/javascript">
    1.21 +
    1.22 +/** Test for Bug 501257 **/
    1.23 +
    1.24 +const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
    1.25 +const SVG_NS = "http://www.w3.org/2000/svg";
    1.26 +const XHTML_NS = "http://www.w3.org/1999/xhtml"
    1.27 +const MATHML_NS = "http://www.w3.org/1998/Math/MathML";
    1.28 +
    1.29 +var gMutationEvents = [];
    1.30 +
    1.31 +function onAttrModified(event) {
    1.32 +  is(event.attrName, "class", "mutation on unexpected attribute");
    1.33 +
    1.34 +  gMutationEvents.push({
    1.35 +    attrChange: event.attrChange,
    1.36 +    prevValue: event.prevValue,
    1.37 +    newValue: event.newValue,
    1.38 +  });
    1.39 +}
    1.40 +
    1.41 +function checkModification(e, funcName, args, expectedRes, before, after, expectedException) {
    1.42 +  if (!Array.isArray(args)) {
    1.43 +    args = [args];
    1.44 +  }
    1.45 +
    1.46 +  var shouldThrow = typeof(expectedException) === "string";
    1.47 +  if (shouldThrow) {
    1.48 +    // If an exception is thrown, the class attribute shouldn't change.
    1.49 +    after = before;
    1.50 +  }
    1.51 +  if (before === null)
    1.52 +    e.removeAttribute("class");
    1.53 +  else
    1.54 +    e.setAttribute("class", before);
    1.55 +
    1.56 +  var contextMsg = "(checkModification: funcName=" + funcName + ",args=" +
    1.57 +                   JSON.stringify(args) + ",expectedRes=" + expectedRes +
    1.58 +                   ",before=" + before + ",after=" + after + ")";
    1.59 +
    1.60 +  gMutationEvents = [];
    1.61 +  e.addEventListener("DOMAttrModified", onAttrModified, false);
    1.62 +  try {
    1.63 +    var list = e.classList;
    1.64 +    var res = list[funcName].apply(list, args);
    1.65 +    if (shouldThrow)
    1.66 +      ok(false, "classList modification didn't throw " + contextMsg);
    1.67 +  } catch (e) {
    1.68 +    if (!shouldThrow)
    1.69 +      ok(false, "classList modification threw an exception " + contextMsg);
    1.70 +    is(e.name, expectedException, "wrong exception thrown " + contextMsg);
    1.71 +  }
    1.72 +  e.removeEventListener("DOMAttrModified", onAttrModified, false);
    1.73 +  if (expectedRes !== null)
    1.74 +    is(res, expectedRes, "wrong return value from " + funcName +
    1.75 +       " " + contextMsg);
    1.76 +
    1.77 +  var expectedAfter = after;
    1.78 +  // XUL returns an empty string when getting a nonexistent class attribute.
    1.79 +  if (e.namespaceURI == XUL_NS && expectedAfter === null)
    1.80 +    expectedAfter = "";
    1.81 +
    1.82 +  is(e.getAttribute("class"), expectedAfter, "wrong class after modification " +
    1.83 +     contextMsg);
    1.84 +  var expectedMutation = before != after;
    1.85 +  is(gMutationEvents.length, expectedMutation ? 1 : 0,
    1.86 +     "unexpected mutation event count " + contextMsg);
    1.87 +  if (expectedMutation && gMutationEvents.length) {
    1.88 +    is(gMutationEvents[0].attrChange,
    1.89 +       before == null ? MutationEvent.ADDITION : MutationEvent.MODIFICATION,
    1.90 +       "wrong type of attribute change " + contextMsg);
    1.91 +    // If there wasn't any previous attribute, prevValue will return an empty
    1.92 +    // string.
    1.93 +    var expectedPrevValue = before === null ? "" : before;
    1.94 +    is(gMutationEvents[0].prevValue, expectedPrevValue,
    1.95 +       "wrong previous value " + contextMsg);
    1.96 +    is(gMutationEvents[0].newValue, after, "wrong new value " + contextMsg);
    1.97 +  }
    1.98 +}
    1.99 +
   1.100 +function assignToClassListStrict(e) {
   1.101 +  "use strict";
   1.102 +  try {
   1.103 +    e.classList = "foo";
   1.104 +    ok(false, "assigning to classList didn't throw");
   1.105 +  } catch (e) { }
   1.106 +}
   1.107 +
   1.108 +function assignToClassList(e) {
   1.109 +  try {
   1.110 +    var expect = e.classList;
   1.111 +    e.classList = "foo";
   1.112 +    is(e.classList, expect, "classList should be unchanged after assignment");
   1.113 +  } catch (e) {
   1.114 +    ok(false, "assigning to classList threw");
   1.115 +  }
   1.116 +}
   1.117 +
   1.118 +function testClassList(e) {
   1.119 +
   1.120 +  // basic tests
   1.121 +
   1.122 +  isnot(e.classList, undefined, "no classList attribute");
   1.123 +  is(typeof(e.classList.contains), "function",
   1.124 +     "no classList.contains function");
   1.125 +  is(typeof(e.classList.add), "function", "no classList.add function");
   1.126 +  is(typeof(e.classList.remove), "function", "no classList.remove function");
   1.127 +  is(typeof(e.classList.toggle), "function", "no classList.toggle function");
   1.128 +
   1.129 +  assignToClassListStrict(e);
   1.130 +  assignToClassList(e);
   1.131 +
   1.132 +  // length attribute
   1.133 +
   1.134 +  is(e.classList.length, 0, "wrong classList.length value");
   1.135 +  e.setAttribute("class", "");
   1.136 +  is(e.classList.length, 0, "wrong classList.length value");
   1.137 +  e.setAttribute("class", "   \t  \f");
   1.138 +  is(e.classList.length, 0, "wrong classList.length value");
   1.139 +
   1.140 +  e.setAttribute("class", "a");
   1.141 +  is(e.classList.length, 1, "wrong classList.length value");
   1.142 +  e.setAttribute("class", "a A");
   1.143 +  is(e.classList.length, 2, "wrong classList.length value");
   1.144 +  e.setAttribute("class", "\r\na\t\f");
   1.145 +  is(e.classList.length, 1, "wrong classList.length value");
   1.146 +
   1.147 +  e.setAttribute("class", "a a");
   1.148 +  is(e.classList.length, 2, "wrong classList.length value");
   1.149 +
   1.150 +  e.setAttribute("class", "a a a a a a");
   1.151 +  is(e.classList.length, 6, "wrong classList.length value");
   1.152 +
   1.153 +  e.setAttribute("class", "a a b b");
   1.154 +  is(e.classList.length, 4, "wrong classList.length value");
   1.155 +
   1.156 +  e.setAttribute("class", "a A B b");
   1.157 +  is(e.classList.length, 4, "wrong classList.length value");
   1.158 +
   1.159 +  e.setAttribute("class", "a b c c b a a b c c");
   1.160 +  is(e.classList.length, 10, "wrong classList.length value");
   1.161 +
   1.162 +  // [Stringifies]
   1.163 +
   1.164 +  ok(DOMTokenList.prototype.hasOwnProperty("toString"),
   1.165 +     "Should have own toString on DOMTokenList")
   1.166 +  ok(!DOMSettableTokenList.prototype.hasOwnProperty("toString"),
   1.167 +     "Should not have own toString on DOMSettableTokenList")
   1.168 +
   1.169 +  e.removeAttribute("class");
   1.170 +  is(e.classList.toString(), "", "wrong classList.toString() value");
   1.171 +  is(e.classList + "", "", "wrong classList string conversion value");
   1.172 +
   1.173 +  e.setAttribute("class", "foo");
   1.174 +  is(e.classList.toString(), "foo", "wrong classList.toString() value");
   1.175 +  is(e.classList + "", "foo", "wrong classList string conversion value");
   1.176 +
   1.177 +  // item() method
   1.178 +
   1.179 +  e.setAttribute("class", "a");
   1.180 +  is(e.classList.item(-1), null, "wrong classList.item() result");
   1.181 +  is(e.classList[-1], undefined, "wrong classList[] result");
   1.182 +  is(e.classList.item(0), "a", "wrong classList.item() result");
   1.183 +  is(e.classList[0], "a", "wrong classList[] result");
   1.184 +  is(e.classList.item(1), null, "wrong classList.item() result");
   1.185 +  is(e.classList[1], undefined, "wrong classList[] result");
   1.186 +
   1.187 +  e.setAttribute("class", "aa AA aa");
   1.188 +  is(e.classList.item(-1), null, "wrong classList.item() result");
   1.189 +  is(e.classList[-1], undefined, "wrong classList[] result");
   1.190 +  is(e.classList.item(0), "aa", "wrong classList.item() result");
   1.191 +  is(e.classList[0], "aa", "wrong classList[] result");
   1.192 +  is(e.classList.item(1), "AA", "wrong classList.item() result");
   1.193 +  is(e.classList[1], "AA", "wrong classList[] result");
   1.194 +  is(e.classList.item(2), "aa", "wrong classList.item() result");
   1.195 +  is(e.classList[2], "aa", "wrong classList[] result");
   1.196 +  is(e.classList.item(3), null, "wrong classList.item() result");
   1.197 +  is(e.classList[3], undefined, "wrong classList[] result");
   1.198 +  is(e.classList.item(0xffffffff), null, "wrong classList.item() result");
   1.199 +  is(e.classList[0xffffffff], undefined, "wrong classList[] result");
   1.200 +  is(e.classList.item(0xfffffffe), null, "wrong classList.item() result");
   1.201 +  is(e.classList[0xffffffe], undefined, "wrong classList[] result");
   1.202 +
   1.203 +  e.setAttribute("class", "a b");
   1.204 +  is(e.classList.item(-1), null, "wrong classList.item() result");
   1.205 +  is(e.classList[-1], undefined, "wrong classList[] result");
   1.206 +  is(e.classList.item(0), "a", "wrong classList.item() result");
   1.207 +  is(e.classList[0], "a", "wrong classList[] result");
   1.208 +  is(e.classList.item(1), "b", "wrong classList.item() result");
   1.209 +  is(e.classList[1], "b", "wrong classList[] result");
   1.210 +  is(e.classList.item(2), null, "wrong classList.item() result");
   1.211 +  is(e.classList[2], undefined, "wrong classList[] result");
   1.212 +
   1.213 +  // contains() method
   1.214 +
   1.215 +  e.removeAttribute("class");
   1.216 +  is(e.classList.contains("a"), false, "wrong classList.contains() result");
   1.217 +  try {
   1.218 +    e.classList.contains("");
   1.219 +    ok(false, "classList.contains() didn't throw");
   1.220 +  } catch (e) {
   1.221 +    is(e.name, "SyntaxError", "wrong exception thrown");
   1.222 +    is(e.code, DOMException.SYNTAX_ERR, "wrong exception thrown");
   1.223 +  }
   1.224 +  try {
   1.225 +    e.classList.contains("  ");
   1.226 +    ok(false, "classList.contains() didn't throw");
   1.227 +  } catch (e) {
   1.228 +    is(e.name, "InvalidCharacterError", "wrong exception thrown");
   1.229 +    is(e.code, DOMException.INVALID_CHARACTER_ERR, "wrong exception thrown");
   1.230 +  }
   1.231 +  try {
   1.232 +    e.classList.contains("aa ");
   1.233 +    ok(false, "classList.contains() didn't throw");
   1.234 +  } catch (e) {
   1.235 +    is(e.name, "InvalidCharacterError", "wrong exception thrown");
   1.236 +    is(e.code, DOMException.INVALID_CHARACTER_ERR, "wrong exception thrown");
   1.237 +  }
   1.238 +
   1.239 +  e.setAttribute("class", "");
   1.240 +  is(e.classList.contains("a"), false, "wrong classList.contains() result");
   1.241 +
   1.242 +  e.setAttribute("class", "a");
   1.243 +  is(e.classList.contains("a"), true, "wrong classList.contains() result");
   1.244 +  is(e.classList.contains("aa"), false, "wrong classList.contains() result");
   1.245 +  is(e.classList.contains("b"), false, "wrong classList.contains() result");
   1.246 +
   1.247 +  e.setAttribute("class", "aa AA");
   1.248 +  is(e.classList.contains("aa"), true, "wrong classList.contains() result");
   1.249 +  is(e.classList.contains("AA"), true, "wrong classList.contains() result");
   1.250 +  is(e.classList.contains("aA"), false, "wrong classList.contains() result");
   1.251 +
   1.252 +  e.setAttribute("class", "a a a");
   1.253 +  is(e.classList.contains("a"), true, "wrong classList.contains() result");
   1.254 +  is(e.classList.contains("aa"), false, "wrong classList.contains() result");
   1.255 +  is(e.classList.contains("b"), false, "wrong classList.contains() result");
   1.256 +
   1.257 +  e.setAttribute("class", "a b c");
   1.258 +  is(e.classList.contains("a"), true, "wrong classList.contains() result");
   1.259 +  is(e.classList.contains("b"), true, "wrong classList.contains() result");
   1.260 +
   1.261 +  // Test for bug 530171
   1.262 +  e.setAttribute("class", "null undefined");
   1.263 +  is(e.classList.contains(null), true, "wrong classList.contains() result");
   1.264 +  is(e.classList.contains(undefined), true, "wrong classList.contains() result");
   1.265 +
   1.266 +  // add() method
   1.267 +
   1.268 +  function checkAdd(before, argument, after, expectedException) {
   1.269 +    checkModification(e, "add", argument, null, before, after, expectedException);
   1.270 +  }
   1.271 +
   1.272 +  checkAdd(null, "", null, "SyntaxError");
   1.273 +  checkAdd(null, ["a", ""], null, "SyntaxError");
   1.274 +  checkAdd(null, " ", null, "InvalidCharacterError");
   1.275 +  checkAdd(null, ["a", " "], null, "InvalidCharacterError");
   1.276 +  checkAdd(null, ["a", "aa "], null, "InvalidCharacterError");
   1.277 +
   1.278 +  checkAdd("a", "a", "a");
   1.279 +  checkAdd("aa", "AA", "aa AA");
   1.280 +  checkAdd("a b c", "a", "a b c");
   1.281 +  checkAdd("a a a  b", "a", "a a a  b");
   1.282 +  checkAdd(null, "a", "a");
   1.283 +  checkAdd("", "a", "a");
   1.284 +  checkAdd(" ", "a", " a");
   1.285 +  checkAdd("   \f", "a", "   \fa");
   1.286 +  checkAdd("a", "b", "a b");
   1.287 +  checkAdd("a b c", "d", "a b c d");
   1.288 +  checkAdd("a b c ", "d", "a b c d");
   1.289 +
   1.290 +  // multiple add
   1.291 +  checkAdd("a b c ", ["d", "e"], "a b c d e");
   1.292 +  checkAdd("a b c ", ["a", "a"], "a b c ");
   1.293 +  checkAdd("a b c ", ["d", "d"], "a b c d");
   1.294 +  checkAdd("a b c ", [], "a b c ");
   1.295 +  checkAdd(null, ["a", "b"], "a b");
   1.296 +  checkAdd("", ["a", "b"], "a b");
   1.297 +
   1.298 +  // Test for bug 530171
   1.299 +  checkAdd(null, null, "null");
   1.300 +  checkAdd(null, undefined, "undefined");
   1.301 +
   1.302 +  // remove() method
   1.303 +
   1.304 +  function checkRemove(before, argument, after, expectedException) {
   1.305 +    checkModification(e, "remove", argument, null, before, after, expectedException);
   1.306 +  }
   1.307 +
   1.308 +  checkRemove(null, "", null, "SyntaxError");
   1.309 +  checkRemove(null, " ", null, "InvalidCharacterError");
   1.310 +  checkRemove(null, "aa ", null, "InvalidCharacterError");
   1.311 +
   1.312 +  checkRemove(null, "a", null);
   1.313 +  checkRemove("", "a", "");
   1.314 +  checkRemove("a b  c", "d", "a b  c");
   1.315 +  checkRemove("a b  c", "A", "a b  c");
   1.316 +  checkRemove(" a a a ", "a", "");
   1.317 +  checkRemove("a  b", "a", "b");
   1.318 +  checkRemove("a  b  ", "a", "b  ");
   1.319 +  checkRemove("a a b", "a", "b");
   1.320 +  checkRemove("aa aa bb", "aa", "bb");
   1.321 +  checkRemove("a a b a a c a a", "a", "b c");
   1.322 +
   1.323 +  checkRemove("a  b  c", "b", "a c");
   1.324 +  checkRemove("aaa  bbb  ccc", "bbb", "aaa ccc");
   1.325 +  checkRemove(" a  b  c ", "b", " a c ");
   1.326 +  checkRemove("a b b b c", "b", "a c");
   1.327 +
   1.328 +  checkRemove("a  b  c", "c", "a  b");
   1.329 +  checkRemove(" a  b  c ", "c", " a  b");
   1.330 +  checkRemove("a b c c c", "c", "a b");
   1.331 +
   1.332 +  checkRemove("a b a c a d a", "a", "b c d");
   1.333 +  checkRemove("AA BB aa CC AA dd aa", "AA", "BB aa CC dd aa");
   1.334 +
   1.335 +  checkRemove("\ra\na\ta\f", "a", "");
   1.336 +
   1.337 +  // multiple remove
   1.338 +  checkRemove("a b c ", ["d", "e"], "a b c ");
   1.339 +  checkRemove("a b c ", ["a", "b"], "c ");
   1.340 +  checkRemove("a b c ", ["a", "c"], "b");
   1.341 +  checkRemove("a b c ", ["a", "a"], "b c ");
   1.342 +  checkRemove("a b c ", ["d", "d"], "a b c ");
   1.343 +  checkRemove("a b c ", [], "a b c ");
   1.344 +  checkRemove(null, ["a", "b"], null);
   1.345 +  checkRemove("", ["a", "b"], "");
   1.346 +
   1.347 +  // Test for bug 530171
   1.348 +  checkRemove("null", null, "");
   1.349 +  checkRemove("undefined", undefined, "");
   1.350 +
   1.351 +  // toggle() method
   1.352 +
   1.353 +  function checkToggle(before, argument, expectedRes, after, expectedException) {
   1.354 +    checkModification(e, "toggle", argument, expectedRes, before, after, expectedException);
   1.355 +  }
   1.356 +
   1.357 +  checkToggle(null, "", null, null, "SyntaxError");
   1.358 +  checkToggle(null, "aa ", null, null, "InvalidCharacterError");
   1.359 +
   1.360 +  checkToggle(null, "a", true, "a");
   1.361 +  checkToggle("", "a", true, "a");
   1.362 +  checkToggle(" ", "a", true, " a");
   1.363 +  checkToggle("   \f", "a", true, "   \fa");
   1.364 +  checkToggle("a", "b", true, "a b");
   1.365 +  checkToggle("a", "A", true, "a A");
   1.366 +  checkToggle("a b c", "d", true, "a b c d");
   1.367 +  checkToggle("a b c", "d", true, "a b c d");
   1.368 +
   1.369 +  checkToggle("a", "a", false, "");
   1.370 +  checkToggle(" a a a ", "a", false, "");
   1.371 +  checkToggle(" A A A ", "a", true, " A A A a");
   1.372 +  checkToggle(" a b c ", "b", false, " a c ");
   1.373 +  checkToggle(" a b c b b", "b", false, " a c");
   1.374 +  checkToggle(" a b  c  ", "c", false, " a b");
   1.375 +  checkToggle(" a b c ", "a", false, "b c ");
   1.376 +
   1.377 +  // Test for bug 530171
   1.378 +  checkToggle("null", null, false, "");
   1.379 +  checkToggle("", null, true, "null");
   1.380 +  checkToggle("undefined", undefined, false, "");
   1.381 +  checkToggle("", undefined, true, "undefined");
   1.382 +
   1.383 +
   1.384 +  // tests for the force argument handling
   1.385 +  
   1.386 +  function checkForceToggle(before, argument, force, expectedRes, after, expectedException) {
   1.387 +    checkModification(e, "toggle", [argument, force], expectedRes, before, after, expectedException);
   1.388 +  }
   1.389 +
   1.390 +  checkForceToggle("", "a", true, true, "a");
   1.391 +  checkForceToggle("a", "a", true, true, "a");
   1.392 +  checkForceToggle("a", "b", true, true, "a b");
   1.393 +  checkForceToggle("a b", "b", true, true, "a b");
   1.394 +  checkForceToggle("", "a", false, false, "");
   1.395 +  checkForceToggle("a", "a", false, false, "");
   1.396 +  checkForceToggle("a", "b", false, false, "a");
   1.397 +  checkForceToggle("a b", "b", false, false, "a");
   1.398 +}
   1.399 +
   1.400 +var content = document.getElementById("content");
   1.401 +
   1.402 +var htmlNode = document.createElement("div");
   1.403 +content.appendChild(htmlNode);
   1.404 +testClassList(htmlNode);
   1.405 +
   1.406 +var xhtmlNode = document.createElementNS(XHTML_NS, "div");
   1.407 +content.appendChild(xhtmlNode);
   1.408 +testClassList(xhtmlNode);
   1.409 +
   1.410 +var xulNode = document.createElementNS(XUL_NS, "box");
   1.411 +content.appendChild(xulNode);
   1.412 +testClassList(xulNode);
   1.413 +
   1.414 +var mathMLNode = document.createElementNS(MATHML_NS, "math");
   1.415 +content.appendChild(mathMLNode);
   1.416 +testClassList(mathMLNode);
   1.417 +
   1.418 +// Nodes not meant to be styled have a null classList property.
   1.419 +
   1.420 +var xmlNode = document.createElementNS(null, "foo");
   1.421 +content.appendChild(xmlNode);
   1.422 +is(xmlNode.classList, null, "classList is not null for plain XML nodes");
   1.423 +
   1.424 +var fooNode = document.createElementNS("http://example.org/foo", "foo");
   1.425 +content.appendChild(fooNode);
   1.426 +is(fooNode.classList, null, "classList is not null for nodes in " +
   1.427 +                            " http://example.org/foo namespace");
   1.428 +
   1.429 +</script>
   1.430 +</pre>
   1.431 +</body>
   1.432 +</html>

mercurial