accessible/tests/mochitest/name/markup.js

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:abbacb6f6aa5
1 ////////////////////////////////////////////////////////////////////////////////
2 // Name tests described by "markuprules.xml" file.
3
4 var gNameRulesFileURL = "markuprules.xml";
5
6 var gRuleDoc = null;
7
8 // Debuggin stuff.
9 var gDumpToConsole = false;
10
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
18
19 var request = new XMLHttpRequest();
20 request.open("get", gNameRulesFileURL, false);
21 request.send();
22
23 gRuleDoc = request.responseXML;
24
25 var markupElms = evaluateXPath(gRuleDoc, "//rules/rulesample/markup");
26 gTestIterator.iterateMarkups(markupElms);
27 }
28
29 ////////////////////////////////////////////////////////////////////////////////
30 // Private section.
31
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;
40
41 this.iterateNext();
42 },
43
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;
53
54 this.iterateNext();
55 },
56
57 iterateNext: function gTestIterator_iterateNext()
58 {
59 if (this.markupIdx == -1) {
60 this.markupIdx++;
61 testNamesForMarkup(this.markupElms[this.markupIdx]);
62 return;
63 }
64
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"});
73
74 this.markupIdx++;
75 if (this.markupIdx == this.markupElms.length) {
76 //disableLogging("tree"); // debugging
77 SimpleTest.finish();
78 return;
79 }
80
81 this.ruleIdx = -1;
82
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]);
89
90 document.body.removeChild(this.container);
91 return;
92 }
93
94 testNameForRule(this.elm, this.ruleElms[this.ruleIdx]);
95 },
96
97 markupElms: null,
98 markupIdx: -1,
99 rulesetElm: null,
100 ruleElms: null,
101 ruleIdx: -1,
102 elm: null,
103 container: null,
104 testID: ""
105 };
106
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");
115
116 var div = document.createElement("div");
117 div.setAttribute("id", "test");
118
119 var child = aMarkupElm.firstChild;
120 while (child) {
121 var newChild = document.importNode(child, true);
122 div.appendChild(newChild);
123 child = child.nextSibling;
124 }
125
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);
132
133 document.body.appendChild(div);
134 }
135
136 function testNamesForMarkupRules(aMarkupElm, aContainer)
137 {
138 var testID = aMarkupElm.getAttribute("id");
139 if (gDumpToConsole)
140 dump("\nProcessing markup rules '" + testID + "'\n");
141
142 var serializer = new XMLSerializer();
143
144 var expr = "//html/body/div[@id='test']/" + aMarkupElm.getAttribute("ref");
145 var elm = evaluateXPath(document, expr, htmlDocResolver)[0];
146
147 var ruleId = aMarkupElm.getAttribute("ruleset");
148 var ruleElm = gRuleDoc.querySelector("[id='" + ruleId + "']");
149 var ruleElms = getRuleElmsByRulesetId(ruleId);
150
151 var processMarkupRules =
152 gTestIterator.iterateRules.bind(gTestIterator, elm, aContainer,
153 ruleElm, ruleElms, testID);
154
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 }
164
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 }
175
176 testNameForAttrRule(aElm, aRuleElm);
177
178 } else if (aRuleElm.hasAttribute("elm")) {
179 if (gDumpToConsole) {
180 dump("\nProcessing rule { elm: " + aRuleElm.getAttribute("elm") +
181 ", elmattr: " + aRuleElm.getAttribute("elmattr") +" }\n");
182 }
183
184 testNameForElmRule(aElm, aRuleElm);
185
186 } else if (aRuleElm.getAttribute("fromsubtree") == "true") {
187 if (gDumpToConsole) {
188 dump("\nProcessing rule { fromsubtree: " +
189 aRuleElm.getAttribute("fromsubtree") +" }\n");
190 }
191
192 testNameForSubtreeRule(aElm, aRuleElm);
193 }
194 }
195
196 function testNameForAttrRule(aElm, aRule)
197 {
198 var name = "";
199
200 var attr = aRule.getAttribute("attr");
201 var attrValue = aElm.getAttribute(attr);
202
203 var type = aRule.getAttribute("type");
204 if (type == "string") {
205 name = attrValue;
206
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 += " ";
213
214 name += labelElm.getAttribute("textequiv");
215 }
216 }
217
218 var msg = "Attribute '" + attr + "' test (" + gTestIterator.testID + "). ";
219 testName(aElm, name, msg);
220
221 if (aRule.getAttribute("explict-name") != "false")
222 testAttrs(aElm, {"explicit-name" : "true"}, true);
223 else
224 testAbsentAttrs(aElm, {"explicit-name" : "true"});
225
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);
233
234 } else if (aRule.hasAttribute("textchanged")) {
235 waitForEvent(EVENT_TEXT_INSERTED, aElm,
236 gTestIterator.iterateNext, gTestIterator);
237 aElm.removeAttribute(attr);
238
239 } else if (aRule.hasAttribute("contentchanged")) {
240 waitForEvent(EVENT_REORDER, aElm,
241 gTestIterator.iterateNext, gTestIterator);
242 aElm.removeAttribute(attr);
243
244 } else {
245 aElm.removeAttribute(attr);
246 gTestIterator.iterateNext();
247 }
248 }
249
250 function testNameForElmRule(aElm, aRule)
251 {
252 var labelElm;
253
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;
263
264 return NodeFilter.FILTER_SKIP;
265 },
266
267 mLocalName: tagname,
268 mAttrName: attrname,
269 mAttrValue: aElm.getAttribute("id")
270 };
271
272 var treeWalker = document.createTreeWalker(document.body,
273 NodeFilter.SHOW_ELEMENT,
274 filter);
275 labelElm = treeWalker.nextNode();
276
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 }
283
284 if (!labelElm) {
285 ok(false, msg + " Failed to find '" + tagname + "' element.");
286 gTestIterator.iterateNext();
287 return;
288 }
289
290 var msg = "Element '" + tagname + "' test (" + gTestIterator.testID + ").";
291 testName(aElm, labelElm.getAttribute("textequiv"), msg);
292 testAttrs(aElm, {"explicit-name" : "true"}, true);
293
294 var parentNode = labelElm.parentNode;
295
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);
302
303 parentNode.removeChild(labelElm);
304 }
305
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"});
311
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);
317
318 while (aElm.firstChild)
319 aElm.removeChild(aElm.firstChild);
320 }
321
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 }
332
333 function getRuleElmsFromRulesetElm(aRulesetElm)
334 {
335 var rulesetId = aRulesetElm.getAttribute("ref");
336 if (rulesetId)
337 return getRuleElmsByRulesetId(rulesetId);
338
339 var ruleElms = [];
340
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);
347
348 child = child.nextSibling;
349 }
350
351 return ruleElms;
352 }
353
354 /**
355 * Helper method to evaluate xpath expression.
356 */
357 function evaluateXPath(aNode, aExpr, aResolver)
358 {
359 var xpe = new XPathEvaluator();
360
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 }
367
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);
373
374 return found;
375 }
376
377 function htmlDocResolver(aPrefix) {
378 var ns = {
379 'html' : 'http://www.w3.org/1999/xhtml'
380 };
381 return ns[aPrefix] || null;
382 }

mercurial