accessible/tests/mochitest/name/markup.js

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

michael@0 1 ////////////////////////////////////////////////////////////////////////////////
michael@0 2 // Name tests described by "markuprules.xml" file.
michael@0 3
michael@0 4 var gNameRulesFileURL = "markuprules.xml";
michael@0 5
michael@0 6 var gRuleDoc = null;
michael@0 7
michael@0 8 // Debuggin stuff.
michael@0 9 var gDumpToConsole = false;
michael@0 10
michael@0 11 /**
michael@0 12 * Start name tests. Run through markup elements and test names for test
michael@0 13 * element (see namerules.xml for details).
michael@0 14 */
michael@0 15 function testNames()
michael@0 16 {
michael@0 17 //enableLogging("tree,stack"); // debugging
michael@0 18
michael@0 19 var request = new XMLHttpRequest();
michael@0 20 request.open("get", gNameRulesFileURL, false);
michael@0 21 request.send();
michael@0 22
michael@0 23 gRuleDoc = request.responseXML;
michael@0 24
michael@0 25 var markupElms = evaluateXPath(gRuleDoc, "//rules/rulesample/markup");
michael@0 26 gTestIterator.iterateMarkups(markupElms);
michael@0 27 }
michael@0 28
michael@0 29 ////////////////////////////////////////////////////////////////////////////////
michael@0 30 // Private section.
michael@0 31
michael@0 32 /**
michael@0 33 * Helper class to interate through name tests.
michael@0 34 */
michael@0 35 var gTestIterator =
michael@0 36 {
michael@0 37 iterateMarkups: function gTestIterator_iterateMarkups(aMarkupElms)
michael@0 38 {
michael@0 39 this.markupElms = aMarkupElms;
michael@0 40
michael@0 41 this.iterateNext();
michael@0 42 },
michael@0 43
michael@0 44 iterateRules: function gTestIterator_iterateRules(aElm, aContainer,
michael@0 45 aRuleSetElm, aRuleElms,
michael@0 46 aTestID)
michael@0 47 {
michael@0 48 this.ruleSetElm = aRuleSetElm;
michael@0 49 this.ruleElms = aRuleElms;
michael@0 50 this.elm = aElm;
michael@0 51 this.container = aContainer;
michael@0 52 this.testID = aTestID;
michael@0 53
michael@0 54 this.iterateNext();
michael@0 55 },
michael@0 56
michael@0 57 iterateNext: function gTestIterator_iterateNext()
michael@0 58 {
michael@0 59 if (this.markupIdx == -1) {
michael@0 60 this.markupIdx++;
michael@0 61 testNamesForMarkup(this.markupElms[this.markupIdx]);
michael@0 62 return;
michael@0 63 }
michael@0 64
michael@0 65 this.ruleIdx++;
michael@0 66 if (this.ruleIdx == this.ruleElms.length) {
michael@0 67 // When test is finished then name is empty and no explict-name.
michael@0 68 var defaultName = this.ruleSetElm.hasAttribute("defaultName") ?
michael@0 69 this.ruleSetElm.getAttribute("defaultName") : null;
michael@0 70 testName(this.elm, defaultName,
michael@0 71 "Default name test (" + gTestIterator.testID + "). ");
michael@0 72 testAbsentAttrs(this.elm, {"explicit-name" : "true"});
michael@0 73
michael@0 74 this.markupIdx++;
michael@0 75 if (this.markupIdx == this.markupElms.length) {
michael@0 76 //disableLogging("tree"); // debugging
michael@0 77 SimpleTest.finish();
michael@0 78 return;
michael@0 79 }
michael@0 80
michael@0 81 this.ruleIdx = -1;
michael@0 82
michael@0 83 if (gDumpToConsole) {
michael@0 84 dump("\nPend next markup processing. Wait for reorder event on " +
michael@0 85 prettyName(document) + "'\n");
michael@0 86 }
michael@0 87 waitForEvent(EVENT_REORDER, document, testNamesForMarkup,
michael@0 88 null, this.markupElms[this.markupIdx]);
michael@0 89
michael@0 90 document.body.removeChild(this.container);
michael@0 91 return;
michael@0 92 }
michael@0 93
michael@0 94 testNameForRule(this.elm, this.ruleElms[this.ruleIdx]);
michael@0 95 },
michael@0 96
michael@0 97 markupElms: null,
michael@0 98 markupIdx: -1,
michael@0 99 rulesetElm: null,
michael@0 100 ruleElms: null,
michael@0 101 ruleIdx: -1,
michael@0 102 elm: null,
michael@0 103 container: null,
michael@0 104 testID: ""
michael@0 105 };
michael@0 106
michael@0 107 /**
michael@0 108 * Process every 'markup' element and test names for it. Used by testNames
michael@0 109 * function.
michael@0 110 */
michael@0 111 function testNamesForMarkup(aMarkupElm)
michael@0 112 {
michael@0 113 if (gDumpToConsole)
michael@0 114 dump("\nProcessing markup '" + aMarkupElm.getAttribute("id") + "'\n");
michael@0 115
michael@0 116 var div = document.createElement("div");
michael@0 117 div.setAttribute("id", "test");
michael@0 118
michael@0 119 var child = aMarkupElm.firstChild;
michael@0 120 while (child) {
michael@0 121 var newChild = document.importNode(child, true);
michael@0 122 div.appendChild(newChild);
michael@0 123 child = child.nextSibling;
michael@0 124 }
michael@0 125
michael@0 126 if (gDumpToConsole) {
michael@0 127 dump("\nProcessing markup. Wait for reorder event on " +
michael@0 128 prettyName(document) + "'\n");
michael@0 129 }
michael@0 130 waitForEvent(EVENT_REORDER, document, testNamesForMarkupRules,
michael@0 131 null, aMarkupElm, div);
michael@0 132
michael@0 133 document.body.appendChild(div);
michael@0 134 }
michael@0 135
michael@0 136 function testNamesForMarkupRules(aMarkupElm, aContainer)
michael@0 137 {
michael@0 138 var testID = aMarkupElm.getAttribute("id");
michael@0 139 if (gDumpToConsole)
michael@0 140 dump("\nProcessing markup rules '" + testID + "'\n");
michael@0 141
michael@0 142 var serializer = new XMLSerializer();
michael@0 143
michael@0 144 var expr = "//html/body/div[@id='test']/" + aMarkupElm.getAttribute("ref");
michael@0 145 var elm = evaluateXPath(document, expr, htmlDocResolver)[0];
michael@0 146
michael@0 147 var ruleId = aMarkupElm.getAttribute("ruleset");
michael@0 148 var ruleElm = gRuleDoc.querySelector("[id='" + ruleId + "']");
michael@0 149 var ruleElms = getRuleElmsByRulesetId(ruleId);
michael@0 150
michael@0 151 var processMarkupRules =
michael@0 152 gTestIterator.iterateRules.bind(gTestIterator, elm, aContainer,
michael@0 153 ruleElm, ruleElms, testID);
michael@0 154
michael@0 155 // Images may be recreated after we append them into subtree. We need to wait
michael@0 156 // in this case. If we are on profiling enabled build then stack tracing
michael@0 157 // works and thus let's log instead. Note, that works if you enabled logging
michael@0 158 // (refer to testNames() function).
michael@0 159 if (isAccessible(elm) || isLogged("stack"))
michael@0 160 processMarkupRules();
michael@0 161 else
michael@0 162 waitForEvent(EVENT_SHOW, elm, processMarkupRules);
michael@0 163 }
michael@0 164
michael@0 165 /**
michael@0 166 * Test name for current rule and current 'markup' element. Used by
michael@0 167 * testNamesForMarkup function.
michael@0 168 */
michael@0 169 function testNameForRule(aElm, aRuleElm)
michael@0 170 {
michael@0 171 if (aRuleElm.hasAttribute("attr")) {
michael@0 172 if (gDumpToConsole) {
michael@0 173 dump("\nProcessing rule { attr: " + aRuleElm.getAttribute("attr") +" }\n");
michael@0 174 }
michael@0 175
michael@0 176 testNameForAttrRule(aElm, aRuleElm);
michael@0 177
michael@0 178 } else if (aRuleElm.hasAttribute("elm")) {
michael@0 179 if (gDumpToConsole) {
michael@0 180 dump("\nProcessing rule { elm: " + aRuleElm.getAttribute("elm") +
michael@0 181 ", elmattr: " + aRuleElm.getAttribute("elmattr") +" }\n");
michael@0 182 }
michael@0 183
michael@0 184 testNameForElmRule(aElm, aRuleElm);
michael@0 185
michael@0 186 } else if (aRuleElm.getAttribute("fromsubtree") == "true") {
michael@0 187 if (gDumpToConsole) {
michael@0 188 dump("\nProcessing rule { fromsubtree: " +
michael@0 189 aRuleElm.getAttribute("fromsubtree") +" }\n");
michael@0 190 }
michael@0 191
michael@0 192 testNameForSubtreeRule(aElm, aRuleElm);
michael@0 193 }
michael@0 194 }
michael@0 195
michael@0 196 function testNameForAttrRule(aElm, aRule)
michael@0 197 {
michael@0 198 var name = "";
michael@0 199
michael@0 200 var attr = aRule.getAttribute("attr");
michael@0 201 var attrValue = aElm.getAttribute(attr);
michael@0 202
michael@0 203 var type = aRule.getAttribute("type");
michael@0 204 if (type == "string") {
michael@0 205 name = attrValue;
michael@0 206
michael@0 207 } else if (type == "ref" && attrValue) {
michael@0 208 var ids = attrValue.split(/\s+/);
michael@0 209 for (var idx = 0; idx < ids.length; idx++) {
michael@0 210 var labelElm = getNode(ids[idx]);
michael@0 211 if (name != "")
michael@0 212 name += " ";
michael@0 213
michael@0 214 name += labelElm.getAttribute("textequiv");
michael@0 215 }
michael@0 216 }
michael@0 217
michael@0 218 var msg = "Attribute '" + attr + "' test (" + gTestIterator.testID + "). ";
michael@0 219 testName(aElm, name, msg);
michael@0 220
michael@0 221 if (aRule.getAttribute("explict-name") != "false")
michael@0 222 testAttrs(aElm, {"explicit-name" : "true"}, true);
michael@0 223 else
michael@0 224 testAbsentAttrs(aElm, {"explicit-name" : "true"});
michael@0 225
michael@0 226 // If @recreated attribute is used then this attribute change recreates an
michael@0 227 // accessible. Wait for reorder event in this case or otherwise proceed next
michael@0 228 // test immediately.
michael@0 229 if (aRule.hasAttribute("recreated")) {
michael@0 230 waitForEvent(EVENT_REORDER, aElm.parentNode,
michael@0 231 gTestIterator.iterateNext, gTestIterator);
michael@0 232 aElm.removeAttribute(attr);
michael@0 233
michael@0 234 } else if (aRule.hasAttribute("textchanged")) {
michael@0 235 waitForEvent(EVENT_TEXT_INSERTED, aElm,
michael@0 236 gTestIterator.iterateNext, gTestIterator);
michael@0 237 aElm.removeAttribute(attr);
michael@0 238
michael@0 239 } else if (aRule.hasAttribute("contentchanged")) {
michael@0 240 waitForEvent(EVENT_REORDER, aElm,
michael@0 241 gTestIterator.iterateNext, gTestIterator);
michael@0 242 aElm.removeAttribute(attr);
michael@0 243
michael@0 244 } else {
michael@0 245 aElm.removeAttribute(attr);
michael@0 246 gTestIterator.iterateNext();
michael@0 247 }
michael@0 248 }
michael@0 249
michael@0 250 function testNameForElmRule(aElm, aRule)
michael@0 251 {
michael@0 252 var labelElm;
michael@0 253
michael@0 254 var tagname = aRule.getAttribute("elm");
michael@0 255 var attrname = aRule.getAttribute("elmattr");
michael@0 256 if (attrname) {
michael@0 257 var filter = {
michael@0 258 acceptNode: function filter_acceptNode(aNode)
michael@0 259 {
michael@0 260 if (aNode.localName == this.mLocalName &&
michael@0 261 aNode.getAttribute(this.mAttrName) == this.mAttrValue)
michael@0 262 return NodeFilter.FILTER_ACCEPT;
michael@0 263
michael@0 264 return NodeFilter.FILTER_SKIP;
michael@0 265 },
michael@0 266
michael@0 267 mLocalName: tagname,
michael@0 268 mAttrName: attrname,
michael@0 269 mAttrValue: aElm.getAttribute("id")
michael@0 270 };
michael@0 271
michael@0 272 var treeWalker = document.createTreeWalker(document.body,
michael@0 273 NodeFilter.SHOW_ELEMENT,
michael@0 274 filter);
michael@0 275 labelElm = treeWalker.nextNode();
michael@0 276
michael@0 277 } else {
michael@0 278 // if attrname is empty then look for the element in subtree.
michael@0 279 labelElm = aElm.getElementsByTagName(tagname)[0];
michael@0 280 if (!labelElm)
michael@0 281 labelElm = aElm.getElementsByTagName("html:" + tagname)[0];
michael@0 282 }
michael@0 283
michael@0 284 if (!labelElm) {
michael@0 285 ok(false, msg + " Failed to find '" + tagname + "' element.");
michael@0 286 gTestIterator.iterateNext();
michael@0 287 return;
michael@0 288 }
michael@0 289
michael@0 290 var msg = "Element '" + tagname + "' test (" + gTestIterator.testID + ").";
michael@0 291 testName(aElm, labelElm.getAttribute("textequiv"), msg);
michael@0 292 testAttrs(aElm, {"explicit-name" : "true"}, true);
michael@0 293
michael@0 294 var parentNode = labelElm.parentNode;
michael@0 295
michael@0 296 if (gDumpToConsole) {
michael@0 297 dump("\nProcessed elm rule. Wait for reorder event on " +
michael@0 298 prettyName(parentNode) + "\n");
michael@0 299 }
michael@0 300 waitForEvent(EVENT_REORDER, parentNode,
michael@0 301 gTestIterator.iterateNext, gTestIterator);
michael@0 302
michael@0 303 parentNode.removeChild(labelElm);
michael@0 304 }
michael@0 305
michael@0 306 function testNameForSubtreeRule(aElm, aRule)
michael@0 307 {
michael@0 308 var msg = "From subtree test (" + gTestIterator.testID + ").";
michael@0 309 testName(aElm, aElm.getAttribute("textequiv"), msg);
michael@0 310 testAbsentAttrs(aElm, {"explicit-name" : "true"});
michael@0 311
michael@0 312 if (gDumpToConsole) {
michael@0 313 dump("\nProcessed from subtree rule. Wait for reorder event on " +
michael@0 314 prettyName(aElm) + "\n");
michael@0 315 }
michael@0 316 waitForEvent(EVENT_REORDER, aElm, gTestIterator.iterateNext, gTestIterator);
michael@0 317
michael@0 318 while (aElm.firstChild)
michael@0 319 aElm.removeChild(aElm.firstChild);
michael@0 320 }
michael@0 321
michael@0 322 /**
michael@0 323 * Return array of 'rule' elements. Used in conjunction with
michael@0 324 * getRuleElmsFromRulesetElm() function.
michael@0 325 */
michael@0 326 function getRuleElmsByRulesetId(aRulesetId)
michael@0 327 {
michael@0 328 var expr = "//rules/ruledfn/ruleset[@id='" + aRulesetId + "']";
michael@0 329 var rulesetElm = evaluateXPath(gRuleDoc, expr);
michael@0 330 return getRuleElmsFromRulesetElm(rulesetElm[0]);
michael@0 331 }
michael@0 332
michael@0 333 function getRuleElmsFromRulesetElm(aRulesetElm)
michael@0 334 {
michael@0 335 var rulesetId = aRulesetElm.getAttribute("ref");
michael@0 336 if (rulesetId)
michael@0 337 return getRuleElmsByRulesetId(rulesetId);
michael@0 338
michael@0 339 var ruleElms = [];
michael@0 340
michael@0 341 var child = aRulesetElm.firstChild;
michael@0 342 while (child) {
michael@0 343 if (child.localName == "ruleset")
michael@0 344 ruleElms = ruleElms.concat(getRuleElmsFromRulesetElm(child));
michael@0 345 if (child.localName == "rule")
michael@0 346 ruleElms.push(child);
michael@0 347
michael@0 348 child = child.nextSibling;
michael@0 349 }
michael@0 350
michael@0 351 return ruleElms;
michael@0 352 }
michael@0 353
michael@0 354 /**
michael@0 355 * Helper method to evaluate xpath expression.
michael@0 356 */
michael@0 357 function evaluateXPath(aNode, aExpr, aResolver)
michael@0 358 {
michael@0 359 var xpe = new XPathEvaluator();
michael@0 360
michael@0 361 var resolver = aResolver;
michael@0 362 if (!resolver) {
michael@0 363 var node = aNode.ownerDocument == null ?
michael@0 364 aNode.documentElement : aNode.ownerDocument.documentElement;
michael@0 365 resolver = xpe.createNSResolver(node);
michael@0 366 }
michael@0 367
michael@0 368 var result = xpe.evaluate(aExpr, aNode, resolver, 0, null);
michael@0 369 var found = [];
michael@0 370 var res;
michael@0 371 while (res = result.iterateNext())
michael@0 372 found.push(res);
michael@0 373
michael@0 374 return found;
michael@0 375 }
michael@0 376
michael@0 377 function htmlDocResolver(aPrefix) {
michael@0 378 var ns = {
michael@0 379 'html' : 'http://www.w3.org/1999/xhtml'
michael@0 380 };
michael@0 381 return ns[aPrefix] || null;
michael@0 382 }

mercurial