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

     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 }

mercurial