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