diff options
Diffstat (limited to 'accessible/tests/mochitest/name/markup.js')
-rw-r--r-- | accessible/tests/mochitest/name/markup.js | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/accessible/tests/mochitest/name/markup.js b/accessible/tests/mochitest/name/markup.js new file mode 100644 index 000000000..d3ecd8982 --- /dev/null +++ b/accessible/tests/mochitest/name/markup.js @@ -0,0 +1,382 @@ +//////////////////////////////////////////////////////////////////////////////// +// Name tests described by "markuprules.xml" file. + +var gNameRulesFileURL = "markuprules.xml"; + +var gRuleDoc = null; + +// Debuggin stuff. +var gDumpToConsole = false; + +/** + * Start name tests. Run through markup elements and test names for test + * element (see namerules.xml for details). + */ +function testNames() +{ + //enableLogging("tree,stack"); // debugging + + var request = new XMLHttpRequest(); + request.open("get", gNameRulesFileURL, false); + request.send(); + + gRuleDoc = request.responseXML; + + var markupElms = evaluateXPath(gRuleDoc, "//rules/rulesample/markup"); + gTestIterator.iterateMarkups(markupElms); +} + +//////////////////////////////////////////////////////////////////////////////// +// Private section. + +/** + * Helper class to interate through name tests. + */ +var gTestIterator = +{ + iterateMarkups: function gTestIterator_iterateMarkups(aMarkupElms) + { + this.markupElms = aMarkupElms; + + this.iterateNext(); + }, + + iterateRules: function gTestIterator_iterateRules(aElm, aContainer, + aRuleSetElm, aRuleElms, + aTestID) + { + this.ruleSetElm = aRuleSetElm; + this.ruleElms = aRuleElms; + this.elm = aElm; + this.container = aContainer; + this.testID = aTestID; + + this.iterateNext(); + }, + + iterateNext: function gTestIterator_iterateNext() + { + if (this.markupIdx == -1) { + this.markupIdx++; + testNamesForMarkup(this.markupElms[this.markupIdx]); + return; + } + + this.ruleIdx++; + if (this.ruleIdx == this.ruleElms.length) { + // When test is finished then name is empty and no explict-name. + var defaultName = this.ruleSetElm.hasAttribute("defaultName") ? + this.ruleSetElm.getAttribute("defaultName") : null; + testName(this.elm, defaultName, + "Default name test (" + gTestIterator.testID + "). "); + testAbsentAttrs(this.elm, {"explicit-name" : "true"}); + + this.markupIdx++; + if (this.markupIdx == this.markupElms.length) { + //disableLogging("tree"); // debugging + SimpleTest.finish(); + return; + } + + this.ruleIdx = -1; + + if (gDumpToConsole) { + dump("\nPend next markup processing. Wait for reorder event on " + + prettyName(document) + "'\n"); + } + waitForEvent(EVENT_REORDER, document, testNamesForMarkup, + null, this.markupElms[this.markupIdx]); + + document.body.removeChild(this.container); + return; + } + + testNameForRule(this.elm, this.ruleElms[this.ruleIdx]); + }, + + markupElms: null, + markupIdx: -1, + rulesetElm: null, + ruleElms: null, + ruleIdx: -1, + elm: null, + container: null, + testID: "" +}; + +/** + * Process every 'markup' element and test names for it. Used by testNames + * function. + */ +function testNamesForMarkup(aMarkupElm) +{ + if (gDumpToConsole) + dump("\nProcessing markup '" + aMarkupElm.getAttribute("id") + "'\n"); + + var div = document.createElement("div"); + div.setAttribute("id", "test"); + + var child = aMarkupElm.firstChild; + while (child) { + var newChild = document.importNode(child, true); + div.appendChild(newChild); + child = child.nextSibling; + } + + if (gDumpToConsole) { + dump("\nProcessing markup. Wait for reorder event on " + + prettyName(document) + "'\n"); + } + waitForEvent(EVENT_REORDER, document, testNamesForMarkupRules, + null, aMarkupElm, div); + + document.body.appendChild(div); +} + +function testNamesForMarkupRules(aMarkupElm, aContainer) +{ + var testID = aMarkupElm.getAttribute("id"); + if (gDumpToConsole) + dump("\nProcessing markup rules '" + testID + "'\n"); + + var serializer = new XMLSerializer(); + + var expr = "//html/body/div[@id='test']/" + aMarkupElm.getAttribute("ref"); + var elm = evaluateXPath(document, expr, htmlDocResolver)[0]; + + var ruleId = aMarkupElm.getAttribute("ruleset"); + var ruleElm = gRuleDoc.querySelector("[id='" + ruleId + "']"); + var ruleElms = getRuleElmsByRulesetId(ruleId); + + var processMarkupRules = + gTestIterator.iterateRules.bind(gTestIterator, elm, aContainer, + ruleElm, ruleElms, testID); + + // Images may be recreated after we append them into subtree. We need to wait + // in this case. If we are on profiling enabled build then stack tracing + // works and thus let's log instead. Note, that works if you enabled logging + // (refer to testNames() function). + if (isAccessible(elm) || isLogged("stack")) + processMarkupRules(); + else + waitForEvent(EVENT_SHOW, elm, processMarkupRules); +} + +/** + * Test name for current rule and current 'markup' element. Used by + * testNamesForMarkup function. + */ +function testNameForRule(aElm, aRuleElm) +{ + if (aRuleElm.hasAttribute("attr")) { + if (gDumpToConsole) { + dump("\nProcessing rule { attr: " + aRuleElm.getAttribute("attr") +" }\n"); + } + + testNameForAttrRule(aElm, aRuleElm); + + } else if (aRuleElm.hasAttribute("elm")) { + if (gDumpToConsole) { + dump("\nProcessing rule { elm: " + aRuleElm.getAttribute("elm") + + ", elmattr: " + aRuleElm.getAttribute("elmattr") +" }\n"); + } + + testNameForElmRule(aElm, aRuleElm); + + } else if (aRuleElm.getAttribute("fromsubtree") == "true") { + if (gDumpToConsole) { + dump("\nProcessing rule { fromsubtree: " + + aRuleElm.getAttribute("fromsubtree") +" }\n"); + } + + testNameForSubtreeRule(aElm, aRuleElm); + } +} + +function testNameForAttrRule(aElm, aRule) +{ + var name = ""; + + var attr = aRule.getAttribute("attr"); + var attrValue = aElm.getAttribute(attr); + + var type = aRule.getAttribute("type"); + if (type == "string") { + name = attrValue; + + } else if (type == "ref" && attrValue) { + var ids = attrValue.split(/\s+/); + for (var idx = 0; idx < ids.length; idx++) { + var labelElm = getNode(ids[idx]); + if (name != "") + name += " "; + + name += labelElm.getAttribute("textequiv"); + } + } + + var msg = "Attribute '" + attr + "' test (" + gTestIterator.testID + "). "; + testName(aElm, name, msg); + + if (aRule.getAttribute("explict-name") != "false") + testAttrs(aElm, {"explicit-name" : "true"}, true); + else + testAbsentAttrs(aElm, {"explicit-name" : "true"}); + + // If @recreated attribute is used then this attribute change recreates an + // accessible. Wait for reorder event in this case or otherwise proceed next + // test immediately. + if (aRule.hasAttribute("recreated")) { + waitForEvent(EVENT_REORDER, aElm.parentNode, + gTestIterator.iterateNext, gTestIterator); + aElm.removeAttribute(attr); + + } else if (aRule.hasAttribute("textchanged")) { + waitForEvent(EVENT_TEXT_INSERTED, aElm, + gTestIterator.iterateNext, gTestIterator); + aElm.removeAttribute(attr); + + } else if (aRule.hasAttribute("contentchanged")) { + waitForEvent(EVENT_REORDER, aElm, + gTestIterator.iterateNext, gTestIterator); + aElm.removeAttribute(attr); + + } else { + aElm.removeAttribute(attr); + gTestIterator.iterateNext(); + } +} + +function testNameForElmRule(aElm, aRule) +{ + var labelElm; + + var tagname = aRule.getAttribute("elm"); + var attrname = aRule.getAttribute("elmattr"); + if (attrname) { + var filter = { + acceptNode: function filter_acceptNode(aNode) + { + if (aNode.localName == this.mLocalName && + aNode.getAttribute(this.mAttrName) == this.mAttrValue) + return NodeFilter.FILTER_ACCEPT; + + return NodeFilter.FILTER_SKIP; + }, + + mLocalName: tagname, + mAttrName: attrname, + mAttrValue: aElm.getAttribute("id") + }; + + var treeWalker = document.createTreeWalker(document.body, + NodeFilter.SHOW_ELEMENT, + filter); + labelElm = treeWalker.nextNode(); + + } else { + // if attrname is empty then look for the element in subtree. + labelElm = aElm.getElementsByTagName(tagname)[0]; + if (!labelElm) + labelElm = aElm.getElementsByTagName("html:" + tagname)[0]; + } + + if (!labelElm) { + ok(false, msg + " Failed to find '" + tagname + "' element."); + gTestIterator.iterateNext(); + return; + } + + var msg = "Element '" + tagname + "' test (" + gTestIterator.testID + ")."; + testName(aElm, labelElm.getAttribute("textequiv"), msg); + testAttrs(aElm, {"explicit-name" : "true"}, true); + + var parentNode = labelElm.parentNode; + + if (gDumpToConsole) { + dump("\nProcessed elm rule. Wait for reorder event on " + + prettyName(parentNode) + "\n"); + } + waitForEvent(EVENT_REORDER, parentNode, + gTestIterator.iterateNext, gTestIterator); + + parentNode.removeChild(labelElm); +} + +function testNameForSubtreeRule(aElm, aRule) +{ + var msg = "From subtree test (" + gTestIterator.testID + ")."; + testName(aElm, aElm.getAttribute("textequiv"), msg); + testAbsentAttrs(aElm, {"explicit-name" : "true"}); + + if (gDumpToConsole) { + dump("\nProcessed from subtree rule. Wait for reorder event on " + + prettyName(aElm) + "\n"); + } + waitForEvent(EVENT_REORDER, aElm, gTestIterator.iterateNext, gTestIterator); + + while (aElm.firstChild) + aElm.removeChild(aElm.firstChild); +} + +/** + * Return array of 'rule' elements. Used in conjunction with + * getRuleElmsFromRulesetElm() function. + */ +function getRuleElmsByRulesetId(aRulesetId) +{ + var expr = "//rules/ruledfn/ruleset[@id='" + aRulesetId + "']"; + var rulesetElm = evaluateXPath(gRuleDoc, expr); + return getRuleElmsFromRulesetElm(rulesetElm[0]); +} + +function getRuleElmsFromRulesetElm(aRulesetElm) +{ + var rulesetId = aRulesetElm.getAttribute("ref"); + if (rulesetId) + return getRuleElmsByRulesetId(rulesetId); + + var ruleElms = []; + + var child = aRulesetElm.firstChild; + while (child) { + if (child.localName == "ruleset") + ruleElms = ruleElms.concat(getRuleElmsFromRulesetElm(child)); + if (child.localName == "rule") + ruleElms.push(child); + + child = child.nextSibling; + } + + return ruleElms; +} + +/** + * Helper method to evaluate xpath expression. + */ +function evaluateXPath(aNode, aExpr, aResolver) +{ + var xpe = new XPathEvaluator(); + + var resolver = aResolver; + if (!resolver) { + var node = aNode.ownerDocument == null ? + aNode.documentElement : aNode.ownerDocument.documentElement; + resolver = xpe.createNSResolver(node); + } + + var result = xpe.evaluate(aExpr, aNode, resolver, 0, null); + var found = []; + var res; + while (res = result.iterateNext()) + found.push(res); + + return found; +} + +function htmlDocResolver(aPrefix) { + var ns = { + 'html' : 'http://www.w3.org/1999/xhtml' + }; + return ns[aPrefix] || null; +} |