content/base/test/test_classList.html

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 <!DOCTYPE HTML>
michael@0 2 <html>
michael@0 3 <!--
michael@0 4 https://bugzilla.mozilla.org/show_bug.cgi?id=501257
michael@0 5 -->
michael@0 6 <head>
michael@0 7 <title>Test for the classList element attribute</title>
michael@0 8 <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
michael@0 9 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
michael@0 10 </head>
michael@0 11 <body>
michael@0 12 <a target="_blank" href="http://www.whatwg.org/specs/web-apps/current-work/#dom-classlist">classList DOM attribute</a>
michael@0 13 <p id="display"></p>
michael@0 14 <div id="content" style="display: none">
michael@0 15 </div>
michael@0 16 <pre id="test">
michael@0 17 <script type="application/javascript">
michael@0 18
michael@0 19 /** Test for Bug 501257 **/
michael@0 20
michael@0 21 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
michael@0 22 const SVG_NS = "http://www.w3.org/2000/svg";
michael@0 23 const XHTML_NS = "http://www.w3.org/1999/xhtml"
michael@0 24 const MATHML_NS = "http://www.w3.org/1998/Math/MathML";
michael@0 25
michael@0 26 var gMutationEvents = [];
michael@0 27
michael@0 28 function onAttrModified(event) {
michael@0 29 is(event.attrName, "class", "mutation on unexpected attribute");
michael@0 30
michael@0 31 gMutationEvents.push({
michael@0 32 attrChange: event.attrChange,
michael@0 33 prevValue: event.prevValue,
michael@0 34 newValue: event.newValue,
michael@0 35 });
michael@0 36 }
michael@0 37
michael@0 38 function checkModification(e, funcName, args, expectedRes, before, after, expectedException) {
michael@0 39 if (!Array.isArray(args)) {
michael@0 40 args = [args];
michael@0 41 }
michael@0 42
michael@0 43 var shouldThrow = typeof(expectedException) === "string";
michael@0 44 if (shouldThrow) {
michael@0 45 // If an exception is thrown, the class attribute shouldn't change.
michael@0 46 after = before;
michael@0 47 }
michael@0 48 if (before === null)
michael@0 49 e.removeAttribute("class");
michael@0 50 else
michael@0 51 e.setAttribute("class", before);
michael@0 52
michael@0 53 var contextMsg = "(checkModification: funcName=" + funcName + ",args=" +
michael@0 54 JSON.stringify(args) + ",expectedRes=" + expectedRes +
michael@0 55 ",before=" + before + ",after=" + after + ")";
michael@0 56
michael@0 57 gMutationEvents = [];
michael@0 58 e.addEventListener("DOMAttrModified", onAttrModified, false);
michael@0 59 try {
michael@0 60 var list = e.classList;
michael@0 61 var res = list[funcName].apply(list, args);
michael@0 62 if (shouldThrow)
michael@0 63 ok(false, "classList modification didn't throw " + contextMsg);
michael@0 64 } catch (e) {
michael@0 65 if (!shouldThrow)
michael@0 66 ok(false, "classList modification threw an exception " + contextMsg);
michael@0 67 is(e.name, expectedException, "wrong exception thrown " + contextMsg);
michael@0 68 }
michael@0 69 e.removeEventListener("DOMAttrModified", onAttrModified, false);
michael@0 70 if (expectedRes !== null)
michael@0 71 is(res, expectedRes, "wrong return value from " + funcName +
michael@0 72 " " + contextMsg);
michael@0 73
michael@0 74 var expectedAfter = after;
michael@0 75 // XUL returns an empty string when getting a nonexistent class attribute.
michael@0 76 if (e.namespaceURI == XUL_NS && expectedAfter === null)
michael@0 77 expectedAfter = "";
michael@0 78
michael@0 79 is(e.getAttribute("class"), expectedAfter, "wrong class after modification " +
michael@0 80 contextMsg);
michael@0 81 var expectedMutation = before != after;
michael@0 82 is(gMutationEvents.length, expectedMutation ? 1 : 0,
michael@0 83 "unexpected mutation event count " + contextMsg);
michael@0 84 if (expectedMutation && gMutationEvents.length) {
michael@0 85 is(gMutationEvents[0].attrChange,
michael@0 86 before == null ? MutationEvent.ADDITION : MutationEvent.MODIFICATION,
michael@0 87 "wrong type of attribute change " + contextMsg);
michael@0 88 // If there wasn't any previous attribute, prevValue will return an empty
michael@0 89 // string.
michael@0 90 var expectedPrevValue = before === null ? "" : before;
michael@0 91 is(gMutationEvents[0].prevValue, expectedPrevValue,
michael@0 92 "wrong previous value " + contextMsg);
michael@0 93 is(gMutationEvents[0].newValue, after, "wrong new value " + contextMsg);
michael@0 94 }
michael@0 95 }
michael@0 96
michael@0 97 function assignToClassListStrict(e) {
michael@0 98 "use strict";
michael@0 99 try {
michael@0 100 e.classList = "foo";
michael@0 101 ok(false, "assigning to classList didn't throw");
michael@0 102 } catch (e) { }
michael@0 103 }
michael@0 104
michael@0 105 function assignToClassList(e) {
michael@0 106 try {
michael@0 107 var expect = e.classList;
michael@0 108 e.classList = "foo";
michael@0 109 is(e.classList, expect, "classList should be unchanged after assignment");
michael@0 110 } catch (e) {
michael@0 111 ok(false, "assigning to classList threw");
michael@0 112 }
michael@0 113 }
michael@0 114
michael@0 115 function testClassList(e) {
michael@0 116
michael@0 117 // basic tests
michael@0 118
michael@0 119 isnot(e.classList, undefined, "no classList attribute");
michael@0 120 is(typeof(e.classList.contains), "function",
michael@0 121 "no classList.contains function");
michael@0 122 is(typeof(e.classList.add), "function", "no classList.add function");
michael@0 123 is(typeof(e.classList.remove), "function", "no classList.remove function");
michael@0 124 is(typeof(e.classList.toggle), "function", "no classList.toggle function");
michael@0 125
michael@0 126 assignToClassListStrict(e);
michael@0 127 assignToClassList(e);
michael@0 128
michael@0 129 // length attribute
michael@0 130
michael@0 131 is(e.classList.length, 0, "wrong classList.length value");
michael@0 132 e.setAttribute("class", "");
michael@0 133 is(e.classList.length, 0, "wrong classList.length value");
michael@0 134 e.setAttribute("class", " \t \f");
michael@0 135 is(e.classList.length, 0, "wrong classList.length value");
michael@0 136
michael@0 137 e.setAttribute("class", "a");
michael@0 138 is(e.classList.length, 1, "wrong classList.length value");
michael@0 139 e.setAttribute("class", "a A");
michael@0 140 is(e.classList.length, 2, "wrong classList.length value");
michael@0 141 e.setAttribute("class", "\r\na\t\f");
michael@0 142 is(e.classList.length, 1, "wrong classList.length value");
michael@0 143
michael@0 144 e.setAttribute("class", "a a");
michael@0 145 is(e.classList.length, 2, "wrong classList.length value");
michael@0 146
michael@0 147 e.setAttribute("class", "a a a a a a");
michael@0 148 is(e.classList.length, 6, "wrong classList.length value");
michael@0 149
michael@0 150 e.setAttribute("class", "a a b b");
michael@0 151 is(e.classList.length, 4, "wrong classList.length value");
michael@0 152
michael@0 153 e.setAttribute("class", "a A B b");
michael@0 154 is(e.classList.length, 4, "wrong classList.length value");
michael@0 155
michael@0 156 e.setAttribute("class", "a b c c b a a b c c");
michael@0 157 is(e.classList.length, 10, "wrong classList.length value");
michael@0 158
michael@0 159 // [Stringifies]
michael@0 160
michael@0 161 ok(DOMTokenList.prototype.hasOwnProperty("toString"),
michael@0 162 "Should have own toString on DOMTokenList")
michael@0 163 ok(!DOMSettableTokenList.prototype.hasOwnProperty("toString"),
michael@0 164 "Should not have own toString on DOMSettableTokenList")
michael@0 165
michael@0 166 e.removeAttribute("class");
michael@0 167 is(e.classList.toString(), "", "wrong classList.toString() value");
michael@0 168 is(e.classList + "", "", "wrong classList string conversion value");
michael@0 169
michael@0 170 e.setAttribute("class", "foo");
michael@0 171 is(e.classList.toString(), "foo", "wrong classList.toString() value");
michael@0 172 is(e.classList + "", "foo", "wrong classList string conversion value");
michael@0 173
michael@0 174 // item() method
michael@0 175
michael@0 176 e.setAttribute("class", "a");
michael@0 177 is(e.classList.item(-1), null, "wrong classList.item() result");
michael@0 178 is(e.classList[-1], undefined, "wrong classList[] result");
michael@0 179 is(e.classList.item(0), "a", "wrong classList.item() result");
michael@0 180 is(e.classList[0], "a", "wrong classList[] result");
michael@0 181 is(e.classList.item(1), null, "wrong classList.item() result");
michael@0 182 is(e.classList[1], undefined, "wrong classList[] result");
michael@0 183
michael@0 184 e.setAttribute("class", "aa AA aa");
michael@0 185 is(e.classList.item(-1), null, "wrong classList.item() result");
michael@0 186 is(e.classList[-1], undefined, "wrong classList[] result");
michael@0 187 is(e.classList.item(0), "aa", "wrong classList.item() result");
michael@0 188 is(e.classList[0], "aa", "wrong classList[] result");
michael@0 189 is(e.classList.item(1), "AA", "wrong classList.item() result");
michael@0 190 is(e.classList[1], "AA", "wrong classList[] result");
michael@0 191 is(e.classList.item(2), "aa", "wrong classList.item() result");
michael@0 192 is(e.classList[2], "aa", "wrong classList[] result");
michael@0 193 is(e.classList.item(3), null, "wrong classList.item() result");
michael@0 194 is(e.classList[3], undefined, "wrong classList[] result");
michael@0 195 is(e.classList.item(0xffffffff), null, "wrong classList.item() result");
michael@0 196 is(e.classList[0xffffffff], undefined, "wrong classList[] result");
michael@0 197 is(e.classList.item(0xfffffffe), null, "wrong classList.item() result");
michael@0 198 is(e.classList[0xffffffe], undefined, "wrong classList[] result");
michael@0 199
michael@0 200 e.setAttribute("class", "a b");
michael@0 201 is(e.classList.item(-1), null, "wrong classList.item() result");
michael@0 202 is(e.classList[-1], undefined, "wrong classList[] result");
michael@0 203 is(e.classList.item(0), "a", "wrong classList.item() result");
michael@0 204 is(e.classList[0], "a", "wrong classList[] result");
michael@0 205 is(e.classList.item(1), "b", "wrong classList.item() result");
michael@0 206 is(e.classList[1], "b", "wrong classList[] result");
michael@0 207 is(e.classList.item(2), null, "wrong classList.item() result");
michael@0 208 is(e.classList[2], undefined, "wrong classList[] result");
michael@0 209
michael@0 210 // contains() method
michael@0 211
michael@0 212 e.removeAttribute("class");
michael@0 213 is(e.classList.contains("a"), false, "wrong classList.contains() result");
michael@0 214 try {
michael@0 215 e.classList.contains("");
michael@0 216 ok(false, "classList.contains() didn't throw");
michael@0 217 } catch (e) {
michael@0 218 is(e.name, "SyntaxError", "wrong exception thrown");
michael@0 219 is(e.code, DOMException.SYNTAX_ERR, "wrong exception thrown");
michael@0 220 }
michael@0 221 try {
michael@0 222 e.classList.contains(" ");
michael@0 223 ok(false, "classList.contains() didn't throw");
michael@0 224 } catch (e) {
michael@0 225 is(e.name, "InvalidCharacterError", "wrong exception thrown");
michael@0 226 is(e.code, DOMException.INVALID_CHARACTER_ERR, "wrong exception thrown");
michael@0 227 }
michael@0 228 try {
michael@0 229 e.classList.contains("aa ");
michael@0 230 ok(false, "classList.contains() didn't throw");
michael@0 231 } catch (e) {
michael@0 232 is(e.name, "InvalidCharacterError", "wrong exception thrown");
michael@0 233 is(e.code, DOMException.INVALID_CHARACTER_ERR, "wrong exception thrown");
michael@0 234 }
michael@0 235
michael@0 236 e.setAttribute("class", "");
michael@0 237 is(e.classList.contains("a"), false, "wrong classList.contains() result");
michael@0 238
michael@0 239 e.setAttribute("class", "a");
michael@0 240 is(e.classList.contains("a"), true, "wrong classList.contains() result");
michael@0 241 is(e.classList.contains("aa"), false, "wrong classList.contains() result");
michael@0 242 is(e.classList.contains("b"), false, "wrong classList.contains() result");
michael@0 243
michael@0 244 e.setAttribute("class", "aa AA");
michael@0 245 is(e.classList.contains("aa"), true, "wrong classList.contains() result");
michael@0 246 is(e.classList.contains("AA"), true, "wrong classList.contains() result");
michael@0 247 is(e.classList.contains("aA"), false, "wrong classList.contains() result");
michael@0 248
michael@0 249 e.setAttribute("class", "a a a");
michael@0 250 is(e.classList.contains("a"), true, "wrong classList.contains() result");
michael@0 251 is(e.classList.contains("aa"), false, "wrong classList.contains() result");
michael@0 252 is(e.classList.contains("b"), false, "wrong classList.contains() result");
michael@0 253
michael@0 254 e.setAttribute("class", "a b c");
michael@0 255 is(e.classList.contains("a"), true, "wrong classList.contains() result");
michael@0 256 is(e.classList.contains("b"), true, "wrong classList.contains() result");
michael@0 257
michael@0 258 // Test for bug 530171
michael@0 259 e.setAttribute("class", "null undefined");
michael@0 260 is(e.classList.contains(null), true, "wrong classList.contains() result");
michael@0 261 is(e.classList.contains(undefined), true, "wrong classList.contains() result");
michael@0 262
michael@0 263 // add() method
michael@0 264
michael@0 265 function checkAdd(before, argument, after, expectedException) {
michael@0 266 checkModification(e, "add", argument, null, before, after, expectedException);
michael@0 267 }
michael@0 268
michael@0 269 checkAdd(null, "", null, "SyntaxError");
michael@0 270 checkAdd(null, ["a", ""], null, "SyntaxError");
michael@0 271 checkAdd(null, " ", null, "InvalidCharacterError");
michael@0 272 checkAdd(null, ["a", " "], null, "InvalidCharacterError");
michael@0 273 checkAdd(null, ["a", "aa "], null, "InvalidCharacterError");
michael@0 274
michael@0 275 checkAdd("a", "a", "a");
michael@0 276 checkAdd("aa", "AA", "aa AA");
michael@0 277 checkAdd("a b c", "a", "a b c");
michael@0 278 checkAdd("a a a b", "a", "a a a b");
michael@0 279 checkAdd(null, "a", "a");
michael@0 280 checkAdd("", "a", "a");
michael@0 281 checkAdd(" ", "a", " a");
michael@0 282 checkAdd(" \f", "a", " \fa");
michael@0 283 checkAdd("a", "b", "a b");
michael@0 284 checkAdd("a b c", "d", "a b c d");
michael@0 285 checkAdd("a b c ", "d", "a b c d");
michael@0 286
michael@0 287 // multiple add
michael@0 288 checkAdd("a b c ", ["d", "e"], "a b c d e");
michael@0 289 checkAdd("a b c ", ["a", "a"], "a b c ");
michael@0 290 checkAdd("a b c ", ["d", "d"], "a b c d");
michael@0 291 checkAdd("a b c ", [], "a b c ");
michael@0 292 checkAdd(null, ["a", "b"], "a b");
michael@0 293 checkAdd("", ["a", "b"], "a b");
michael@0 294
michael@0 295 // Test for bug 530171
michael@0 296 checkAdd(null, null, "null");
michael@0 297 checkAdd(null, undefined, "undefined");
michael@0 298
michael@0 299 // remove() method
michael@0 300
michael@0 301 function checkRemove(before, argument, after, expectedException) {
michael@0 302 checkModification(e, "remove", argument, null, before, after, expectedException);
michael@0 303 }
michael@0 304
michael@0 305 checkRemove(null, "", null, "SyntaxError");
michael@0 306 checkRemove(null, " ", null, "InvalidCharacterError");
michael@0 307 checkRemove(null, "aa ", null, "InvalidCharacterError");
michael@0 308
michael@0 309 checkRemove(null, "a", null);
michael@0 310 checkRemove("", "a", "");
michael@0 311 checkRemove("a b c", "d", "a b c");
michael@0 312 checkRemove("a b c", "A", "a b c");
michael@0 313 checkRemove(" a a a ", "a", "");
michael@0 314 checkRemove("a b", "a", "b");
michael@0 315 checkRemove("a b ", "a", "b ");
michael@0 316 checkRemove("a a b", "a", "b");
michael@0 317 checkRemove("aa aa bb", "aa", "bb");
michael@0 318 checkRemove("a a b a a c a a", "a", "b c");
michael@0 319
michael@0 320 checkRemove("a b c", "b", "a c");
michael@0 321 checkRemove("aaa bbb ccc", "bbb", "aaa ccc");
michael@0 322 checkRemove(" a b c ", "b", " a c ");
michael@0 323 checkRemove("a b b b c", "b", "a c");
michael@0 324
michael@0 325 checkRemove("a b c", "c", "a b");
michael@0 326 checkRemove(" a b c ", "c", " a b");
michael@0 327 checkRemove("a b c c c", "c", "a b");
michael@0 328
michael@0 329 checkRemove("a b a c a d a", "a", "b c d");
michael@0 330 checkRemove("AA BB aa CC AA dd aa", "AA", "BB aa CC dd aa");
michael@0 331
michael@0 332 checkRemove("\ra\na\ta\f", "a", "");
michael@0 333
michael@0 334 // multiple remove
michael@0 335 checkRemove("a b c ", ["d", "e"], "a b c ");
michael@0 336 checkRemove("a b c ", ["a", "b"], "c ");
michael@0 337 checkRemove("a b c ", ["a", "c"], "b");
michael@0 338 checkRemove("a b c ", ["a", "a"], "b c ");
michael@0 339 checkRemove("a b c ", ["d", "d"], "a b c ");
michael@0 340 checkRemove("a b c ", [], "a b c ");
michael@0 341 checkRemove(null, ["a", "b"], null);
michael@0 342 checkRemove("", ["a", "b"], "");
michael@0 343
michael@0 344 // Test for bug 530171
michael@0 345 checkRemove("null", null, "");
michael@0 346 checkRemove("undefined", undefined, "");
michael@0 347
michael@0 348 // toggle() method
michael@0 349
michael@0 350 function checkToggle(before, argument, expectedRes, after, expectedException) {
michael@0 351 checkModification(e, "toggle", argument, expectedRes, before, after, expectedException);
michael@0 352 }
michael@0 353
michael@0 354 checkToggle(null, "", null, null, "SyntaxError");
michael@0 355 checkToggle(null, "aa ", null, null, "InvalidCharacterError");
michael@0 356
michael@0 357 checkToggle(null, "a", true, "a");
michael@0 358 checkToggle("", "a", true, "a");
michael@0 359 checkToggle(" ", "a", true, " a");
michael@0 360 checkToggle(" \f", "a", true, " \fa");
michael@0 361 checkToggle("a", "b", true, "a b");
michael@0 362 checkToggle("a", "A", true, "a A");
michael@0 363 checkToggle("a b c", "d", true, "a b c d");
michael@0 364 checkToggle("a b c", "d", true, "a b c d");
michael@0 365
michael@0 366 checkToggle("a", "a", false, "");
michael@0 367 checkToggle(" a a a ", "a", false, "");
michael@0 368 checkToggle(" A A A ", "a", true, " A A A a");
michael@0 369 checkToggle(" a b c ", "b", false, " a c ");
michael@0 370 checkToggle(" a b c b b", "b", false, " a c");
michael@0 371 checkToggle(" a b c ", "c", false, " a b");
michael@0 372 checkToggle(" a b c ", "a", false, "b c ");
michael@0 373
michael@0 374 // Test for bug 530171
michael@0 375 checkToggle("null", null, false, "");
michael@0 376 checkToggle("", null, true, "null");
michael@0 377 checkToggle("undefined", undefined, false, "");
michael@0 378 checkToggle("", undefined, true, "undefined");
michael@0 379
michael@0 380
michael@0 381 // tests for the force argument handling
michael@0 382
michael@0 383 function checkForceToggle(before, argument, force, expectedRes, after, expectedException) {
michael@0 384 checkModification(e, "toggle", [argument, force], expectedRes, before, after, expectedException);
michael@0 385 }
michael@0 386
michael@0 387 checkForceToggle("", "a", true, true, "a");
michael@0 388 checkForceToggle("a", "a", true, true, "a");
michael@0 389 checkForceToggle("a", "b", true, true, "a b");
michael@0 390 checkForceToggle("a b", "b", true, true, "a b");
michael@0 391 checkForceToggle("", "a", false, false, "");
michael@0 392 checkForceToggle("a", "a", false, false, "");
michael@0 393 checkForceToggle("a", "b", false, false, "a");
michael@0 394 checkForceToggle("a b", "b", false, false, "a");
michael@0 395 }
michael@0 396
michael@0 397 var content = document.getElementById("content");
michael@0 398
michael@0 399 var htmlNode = document.createElement("div");
michael@0 400 content.appendChild(htmlNode);
michael@0 401 testClassList(htmlNode);
michael@0 402
michael@0 403 var xhtmlNode = document.createElementNS(XHTML_NS, "div");
michael@0 404 content.appendChild(xhtmlNode);
michael@0 405 testClassList(xhtmlNode);
michael@0 406
michael@0 407 var xulNode = document.createElementNS(XUL_NS, "box");
michael@0 408 content.appendChild(xulNode);
michael@0 409 testClassList(xulNode);
michael@0 410
michael@0 411 var mathMLNode = document.createElementNS(MATHML_NS, "math");
michael@0 412 content.appendChild(mathMLNode);
michael@0 413 testClassList(mathMLNode);
michael@0 414
michael@0 415 // Nodes not meant to be styled have a null classList property.
michael@0 416
michael@0 417 var xmlNode = document.createElementNS(null, "foo");
michael@0 418 content.appendChild(xmlNode);
michael@0 419 is(xmlNode.classList, null, "classList is not null for plain XML nodes");
michael@0 420
michael@0 421 var fooNode = document.createElementNS("http://example.org/foo", "foo");
michael@0 422 content.appendChild(fooNode);
michael@0 423 is(fooNode.classList, null, "classList is not null for nodes in " +
michael@0 424 " http://example.org/foo namespace");
michael@0 425
michael@0 426 </script>
michael@0 427 </pre>
michael@0 428 </body>
michael@0 429 </html>

mercurial