summaryrefslogtreecommitdiffstats
path: root/accessible/tests/mochitest/name
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/tests/mochitest/name')
-rw-r--r--accessible/tests/mochitest/name/a11y.toml29
-rw-r--r--accessible/tests/mochitest/name/markup.js425
-rw-r--r--accessible/tests/mochitest/name/markuprules.xml367
-rw-r--r--accessible/tests/mochitest/name/test_ARIACore_examples.html90
-rw-r--r--accessible/tests/mochitest/name/test_browserui.xhtml85
-rw-r--r--accessible/tests/mochitest/name/test_counterstyle.html150
-rw-r--r--accessible/tests/mochitest/name/test_general.html780
-rw-r--r--accessible/tests/mochitest/name/test_general.xhtml345
-rw-r--r--accessible/tests/mochitest/name/test_link.html87
-rw-r--r--accessible/tests/mochitest/name/test_list.html103
-rw-r--r--accessible/tests/mochitest/name/test_markup.html58
-rw-r--r--accessible/tests/mochitest/name/test_svg.html53
-rw-r--r--accessible/tests/mochitest/name/test_tree.xhtml207
13 files changed, 2779 insertions, 0 deletions
diff --git a/accessible/tests/mochitest/name/a11y.toml b/accessible/tests/mochitest/name/a11y.toml
new file mode 100644
index 0000000000..8faf1b1c45
--- /dev/null
+++ b/accessible/tests/mochitest/name/a11y.toml
@@ -0,0 +1,29 @@
+[DEFAULT]
+support-files = [
+ "markup.js",
+ "markuprules.xml",
+ "!/accessible/tests/mochitest/*.js",
+ "!/accessible/tests/mochitest/moz.png"]
+
+["test_ARIACore_examples.html"]
+
+["test_browserui.xhtml"]
+
+["test_counterstyle.html"]
+
+["test_general.html"]
+
+["test_general.xhtml"]
+
+["test_link.html"]
+
+["test_list.html"]
+
+["test_markup.html"]
+skip-if = [
+ "win11_2009 && debug", # Bug 1296784
+]
+
+["test_svg.html"]
+
+["test_tree.xhtml"]
diff --git a/accessible/tests/mochitest/name/markup.js b/accessible/tests/mochitest/name/markup.js
new file mode 100644
index 0000000000..a267bd4f7b
--- /dev/null
+++ b/accessible/tests/mochitest/name/markup.js
@@ -0,0 +1,425 @@
+/* import-globals-from ../attributes.js */
+/* import-globals-from ../common.js */
+/* import-globals-from ../events.js */
+/* import-globals-from ../name.js */
+
+// //////////////////////////////////////////////////////////////////////////////
+// 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 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" });
+ }
+
+ waitForEvent(
+ EVENT_NAME_CHANGE,
+ aElm,
+ gTestIterator.iterateNext,
+ gTestIterator
+ );
+
+ aElm.removeAttribute(attr);
+}
+
+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 name change event on " +
+ prettyName(aElm) +
+ "\n"
+ );
+ }
+ waitForEvent(
+ EVENT_NAME_CHANGE,
+ aElm,
+ 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_NAME_CHANGE,
+ aElm,
+ gTestIterator.iterateNext,
+ gTestIterator
+ );
+
+ while (aElm.firstChild) {
+ aElm.firstChild.remove();
+ }
+}
+
+/**
+ * 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;
+}
diff --git a/accessible/tests/mochitest/name/markuprules.xml b/accessible/tests/mochitest/name/markuprules.xml
new file mode 100644
index 0000000000..045a25b437
--- /dev/null
+++ b/accessible/tests/mochitest/name/markuprules.xml
@@ -0,0 +1,367 @@
+<?xml version="1.0"?>
+
+<!--
+ This XML file is used to create sequence of accessible name tests. It consist
+ of two sections. The first section 'ruledfn' declares name computation rules.
+ The second section 'rulesample' defines markup samples we need to check name
+ computation rules for.
+
+ <ruledfn>
+ <ruleset>
+ <rule>
+
+ Section 'ruledfn' contains 'ruleset' elements. Every 'ruleset' element is
+ presented by 'rule' elements so that sequence of 'rule' elements gives the
+ sequence of name computations rules. Every 'rule' element can be one of four
+ types.
+
+ * <rule attr='' type='string'/> used when name is equal to the value of
+ attribute presented on the element.
+
+ Example, 'aria-label' attribute. In this case 'rule' element has 'attr'
+ attribute pointing to attribute name and 'type' attribute with 'string'
+ value. For example, <rule attr="aria-label" type="string"/>.
+
+ * <rule attr='' type='ref'/> used when name is calculated from elements that
+ are pointed to by attribute value on the element.
+
+ Example is 'aria-labelledby'. In this case 'rule' element has 'attr'
+ attribute holding the sequence of IDs of elements used to compute the name,
+ in addition the 'rule' element has 'type' attribute with 'ref' value.
+ For example, <rule attr="aria-labelledby" type="ref"/>.
+
+ * <rule elm='' elmattr=''/> used when name is calculated from another
+ element. These attributes are used to find an element by tagname and
+ attribute with value equaled to ID of the element. If 'elmattr' is missed
+ then element from subtree with the given tagname is used.
+
+ Example, html:label@for element, <rule elm="label" elmattr="for"/>.
+ Example, html:caption element, <rule elm="caption"/>
+
+ * <rule fromsubtree='true'/> used when name is computed from subtree.
+
+ Example, html:button. In this case 'rule' element has 'fromsubtree'
+ attribute with 'true' value.
+
+ <rulesample>
+ <markup ruleset=''>
+
+ Section 'rulesample' provides set of markup samples ('markup' elements). Every
+ 'markup' element contains an element that accessible name will be computed for
+ (let's call it test element). In addition the 'markup' element contains some
+ other elements from native markup used in name calculation process for test
+ element. Test element is pointed to by 'ref' attribute on 'markup' element.
+ Also 'markup' element has 'ruleset' attribute to indicate ruleset for the test
+ element.
+
+ How does it work? Let's consider simple example:
+ <ruledfn>
+ <ruleset id="aria">
+ <rule attr="aria-label" type="string"/>
+ <rule attr="aria-labelledby" type="ref"/>
+ </ruleset>
+ </ruledfn>
+ <rulesample>
+ <markup ref="html:div" ruleset="aria">
+ <html:span id="label" textequiv="test2">test2</html:span>
+ <html:div aria-label="test1"
+ aria-labelledby="label">it's a div</html:div>
+ </markup>
+ </rulesample>
+
+ Initially 'markup' element holds markup for all rules specified by 'ruleset'
+ attribute. This allows us to check if the sequence of name computation rules
+ is correct. Here 'ruleset' element defines two rules. We get the first rule
+ which means accessible name is computed from value of 'aria-label' attribute.
+ Then we check accessible name for the test element and remove 'aria-label'
+ attribute. After we get the second rule which means we should get IDs from
+ 'aria-labelledby' attribute and compose accessible name from values of
+ 'textequiv' attributes (that are supposed to give the desired name for each
+ element that is being pointed to by aria-labelledby). Check accessible name
+ and finish test.
+-->
+
+<rules xmlns:html="http://www.w3.org/1999/xhtml"
+ xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <ruledfn>
+
+ <!-- bricks -->
+ <ruleset id="ARIA">
+ <rule attr="aria-labelledby" type="ref"/>
+ <rule attr="aria-label" type="string"/>
+ </ruleset>
+
+ <ruleset id="HTMLControl:Head">
+ <ruleset ref="ARIA"/>
+ <rule elm="label" elmattr="for"/>
+ </ruleset>
+
+ <!-- general -->
+ <ruleset id="HTMLControl">
+ <ruleset ref="HTMLControl:Head"/>
+ <rule fromsubtree="true"/>
+ <rule attr="title" type="string"/>
+ </ruleset>
+
+ <ruleset id="HTMLElm">
+ <ruleset ref="ARIA"/>
+ <rule attr="title" type="string"/>
+ </ruleset>
+
+ <!-- specific -->
+ <ruleset id="HTMLARIAGridCell">
+ <ruleset ref="ARIA"/>
+ <rule fromsubtree="true"/>
+ <rule attr="title" type="string"/>
+ </ruleset>
+
+ <ruleset id="HTMLInputButton">
+ <ruleset ref="HTMLControl:Head"/>
+ <rule attr="value" type="string" explict-name="false" reordered="true"/>
+ <rule attr="title" type="string"/>
+ </ruleset>
+
+ <ruleset id="HTMLInputSubmit" defaultName="Submit Query">
+ <ruleset ref="HTMLControl:Head"/>
+ <rule attr="value" type="string" explict-name="false"/>
+ </ruleset>
+
+ <ruleset id="HTMLInputReset" defaultName="Reset">
+ <ruleset ref="HTMLControl:Head"/>
+ <rule attr="value" type="string" explict-name="false"/>
+ </ruleset>
+
+ <ruleset id="HTMLInputImage">
+ <ruleset ref="HTMLControl:Head"/>
+ <rule attr="alt" type="string"/>
+ <rule attr="value" type="string"/>
+ <rule attr="title" type="string"/>
+ </ruleset>
+
+ <ruleset id="HTMLInputImageNoValidSrc" defaultName="Submit Query">
+ <ruleset ref="HTMLControl:Head"/>
+ <rule attr="alt" type="string" explict-name="false"/>
+ <rule attr="value" type="string" explict-name="false"/>
+ </ruleset>
+
+ <ruleset id="HTMLOption">
+ <ruleset ref="ARIA"/>
+ <rule attr="label" type="string"/>
+ <rule fromsubtree="true"/>
+ <rule attr="title" type="string"/>
+ </ruleset>
+
+ <ruleset id="HTMLImg">
+ <ruleset ref="ARIA"/>
+ <rule attr="alt" type="string"/>
+ <rule attr="title" type="string"/>
+ </ruleset>
+
+ <ruleset id="HTMLTable">
+ <ruleset ref="ARIA"/>
+ <rule elm="caption"/>
+ <rule attr="summary" type="string"/>
+ <rule attr="title" type="string"/>
+ </ruleset>
+ </ruledfn>
+
+ <rulesample>
+
+ <markup id="HTMLButtonTest"
+ ref="html:button" ruleset="HTMLControl">
+ <html:span id="l1" textequiv="test2">test2</html:span>
+ <html:span id="l2" textequiv="test3">test3</html:span>
+ <html:label for="btn" textequiv="test4">test4</html:label>
+ <html:button id="btn"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ title="test5"
+ textequiv="press me">press me</html:button>
+ </markup>
+
+ <markup id="HTMLInputButtonTest"
+ ref="html:input" ruleset="HTMLInputButton">
+ <html:span id="l1" textequiv="test2">test2</html:span>
+ <html:span id="l2" textequiv="test3">test3</html:span>
+ <html:label for="btn" textequiv="test4">test4</html:label>
+ <html:input id="btn"
+ type="button"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ value="name from value"
+ alt="no name from al"
+ src="no name from src"
+ data="no name from data"
+ title="name from title"/>
+ </markup>
+
+ <markup id="HTMLInputSubmitTest"
+ ref="html:input" ruleset="HTMLInputSubmit">
+ <html:span id="l1" textequiv="test2">test2</html:span>
+ <html:span id="l2" textequiv="test3">test3</html:span>
+ <html:label for="btn-submit" textequiv="test4">test4</html:label>
+ <html:input id="btn-submit"
+ type="submit"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ value="name from value"
+ alt="no name from atl"
+ src="no name from src"
+ data="no name from data"
+ title="no name from title"/>
+ </markup>
+
+ <markup id="HTMLInputResetTest"
+ ref="html:input" ruleset="HTMLInputReset">
+ <html:span id="l1" textequiv="test2">test2</html:span>
+ <html:span id="l2" textequiv="test3">test3</html:span>
+ <html:label for="btn-reset" textequiv="test4">test4</html:label>
+ <html:input id="btn-reset"
+ type="reset"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ value="name from value"
+ alt="no name from alt"
+ src="no name from src"
+ data="no name from data"
+ title="no name from title"/>
+ </markup>
+
+ <!--
+ Disabled due to intermittent failures (bug 1436323) which became more
+ frequent due to the landing of bug 1383682. The latter bug made loading
+ of images from cache much more consistent, which appears to have impacted
+ the timing for this test case. If the image is switched to a unique
+ image (e.g. always decoding since there is no cache), the failure rate
+ increases, presumably because the test is dependent on a specific ordering
+ of events, and implicitly assumes the image is loaded immediately.
+ -->
+
+ <!--
+ <markup id="HTMLInputImageTest"
+ ref="html:input" ruleset="HTMLInputImage">
+ <html:span id="l1" textequiv="test2">test2</html:span>
+ <html:span id="l2" textequiv="test3">test3</html:span>
+ <html:label for="btn-image" textequiv="test4">test4</html:label>
+ <html:input id="btn-image"
+ type="image"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ alt="name from alt"
+ value="name from value"
+ src="../moz.png"
+ data="no name from data"
+ title="name from title"/>
+ </markup>
+ -->
+
+ <markup id="HTMLInputImageNoValidSrcTest"
+ ref="html:input" ruleset="HTMLInputImageNoValidSrc">
+ <html:span id="l1" textequiv="test2">test2</html:span>
+ <html:span id="l2" textequiv="test3">test3</html:span>
+ <html:label for="btn-image" textequiv="test4">test4</html:label>
+ <html:input id="btn-image"
+ type="image"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ alt="name from alt"
+ value="name from value"
+ data="no name from data"
+ title="no name from title"/>
+ </markup>
+
+ <markup id="HTMLOptionTest"
+ ref="html:select/html:option[1]" ruleset="HTMLOption">
+ <html:span id="l1" textequiv="test2">test2</html:span>
+ <html:span id="l2" textequiv="test3">test3</html:span>
+ <html:select>
+ <html:option id="opt"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ label="test4"
+ title="test5"
+ textequiv="option1">option1</html:option>
+ <html:option>option2</html:option>
+ </html:select>
+ </markup>
+
+ <markup id="HTMLImageTest"
+ ref="html:img" ruleset="HTMLImg">
+ <html:span id="l1" textequiv="test2">test2</html:span>
+ <html:span id="l2" textequiv="test3">test3</html:span>
+ <html:img id="img"
+ aria-label="Logo of Mozilla"
+ aria-labelledby="l1 l2"
+ alt="Mozilla logo"
+ title="This is a logo"
+ src="../moz.png"/>
+ </markup>
+
+ <markup id="HTMLTdTest"
+ ref="html:table/html:tr/html:td" ruleset="HTMLElm">
+ <html:span id="l1" textequiv="test2">test2</html:span>
+ <html:span id="l2" textequiv="test3">test3</html:span>
+ <html:label for="tc" textequiv="test4">test4</html:label>
+ <html:table>
+ <html:tr>
+ <html:td id="tc"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ title="test5">
+ <html:p>This is a paragraph</html:p>
+ <html:a href="#">This is a link</html:a>
+ <html:ul>
+ <html:li>This is a list</html:li>
+ </html:ul>
+ </html:td>
+ </html:tr>
+ </html:table>
+ </markup>
+
+ <markup id="HTMLTdARIAGridCellTest"
+ ref="html:table/html:tr/html:td" ruleset="HTMLARIAGridCell">
+ <html:span id="l1" textequiv="test2">test2</html:span>
+ <html:span id="l2" textequiv="test3">test3</html:span>
+ <html:label for="gc" textequiv="test4">test4</html:label>
+ <html:table>
+ <html:tr>
+ <html:td id="gc"
+ role="gridcell"
+ aria-label="test1"
+ aria-labelledby="l1 l2"
+ textequiv="This is a paragraph This is a link • Listitem1 • Listitem2"
+ title="This is a paragraph This is a link This is a list">
+ <html:p>This is a paragraph</html:p>
+ <html:a href="#">This is a link</html:a>
+ <html:ul>
+ <html:li>Listitem1</html:li>
+ <html:li>Listitem2</html:li>
+ </html:ul>
+ </html:td>
+ </html:tr>
+ </html:table>
+ </markup>
+
+ <markup id="HTMLTableTest"
+ ref="html:table" ruleset="HTMLTable">
+ <html:span id="l1" textequiv="lby_tst6_1">lby_tst6_1</html:span>
+ <html:span id="l2" textequiv="lby_tst6_2">lby_tst6_2</html:span>
+ <html:label for="t" textequiv="label_tst6">label_tst6</html:label>
+ <!-- layout frame are recreated due to varous reasons, here's text frame
+ placed after caption frame triggres table frame recreation when
+ caption element is removed from DOM; get rid text node after caption
+ node to make the test working -->
+ <html:table id="t" aria-label="arialabel_tst6"
+ aria-labelledby="l1 l2"
+ summary="summary_tst6"
+ title="title_tst6">
+ <html:caption textequiv="caption_tst6">caption_tst6</html:caption><html:tr>
+ <html:td>cell1</html:td>
+ <html:td>cell2</html:td>
+ </html:tr>
+ </html:table>
+ </markup>
+
+ </rulesample>
+</rules>
diff --git a/accessible/tests/mochitest/name/test_ARIACore_examples.html b/accessible/tests/mochitest/name/test_ARIACore_examples.html
new file mode 100644
index 0000000000..a15fee78f8
--- /dev/null
+++ b/accessible/tests/mochitest/name/test_ARIACore_examples.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+ <title>Testing a11y name ccomputation testcases</title>
+
+ <link rel="stylesheet"
+ type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <script type="application/javascript"
+ src="../common.js"></script>
+ <script type="application/javascript"
+ src="../name.js"></script>
+
+ <script type="application/javascript">
+ function doTest() {
+ // All test cases taken from https://www.w3.org/TR/accname-1.1/
+ // These were especially called out to demonstrate edge cases.
+
+ // Example 1 from section 4.3.1 under 2.B.
+ // Element1 should get its name from the text in element3.
+ // Element2 should not gets name from element1 because that already
+ // gets its name from another element.
+ testName("el1", "hello");
+ testName("el2", null);
+
+ // Example 2 from section 4.3.1 under 2.C.
+ // The buttons should get their name from their labels and the links.
+ testName("del_row1", "Delete Documentation.pdf");
+ testName("del_row2", "Delete HolidayLetter.pdf");
+
+ // Example 3 from section 4.3.1 under 2.F.
+ // Name should be own content text plus the value of the input plus
+ // more own inner text, separated by 1 space.
+ testName("chkbx", "Flash the screen 5 times");
+
+ // Example 4 from section 4.3.1 under 2.F.
+ // Name from content should include all the child nodes, including
+ // table cells.
+ testName("input_with_html_label", "foo bar baz");
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(doTest);
+ </script>
+
+</head>
+<body>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+
+ <!-- el1 should be labeled, el2 should not. -->
+ <div id="el1" aria-labelledby="el3"></div>
+ <div id="el2" aria-labelledby="el1"></div>
+ <div id="el3"> hello </div>
+
+ <!-- The buttons should be labeled by themselves and the referenced link -->
+ <ul>
+ <li>
+ <a id="file_row1" href="./files/Documentation.pdf">Documentation.pdf</a>
+ <span role="button" tabindex="0" id="del_row1" aria-label="Delete"
+ aria-labelledby="del_row1 file_row1"></span>
+ </li>
+ <li>
+ <a id="file_row2" href="./files/HolidayLetter.pdf">HolidayLetter.pdf</a>
+ <span role="button" tabindex="0" id="del_row2" aria-label="Delete"
+ aria-labelledby="del_row2 file_row2"></span>
+ </li>
+ </ul>
+
+ <!-- Label from combined text and subtree -->
+ <div id="chkbx" role="checkbox" aria-checked="false">Flash the screen
+ <span role="textbox" aria-multiline="false"> 5 </span> times</div>
+
+ <!-- Label with name from content should include table -->
+ <input id="input_with_html_label" />
+ <label for="input_with_html_label" id="label">
+ <div>foo</div>
+ <table><tr><td>bar</td></tr></table>
+ <div>baz</div>
+ </label>
+
+</body>
+</html>
diff --git a/accessible/tests/mochitest/name/test_browserui.xhtml b/accessible/tests/mochitest/name/test_browserui.xhtml
new file mode 100644
index 0000000000..d7834eb3c0
--- /dev/null
+++ b/accessible/tests/mochitest/name/test_browserui.xhtml
@@ -0,0 +1,85 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="Accessibility Name Calculating Test.">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+ <script type="application/javascript"
+ src="../common.js"></script>
+ <script type="application/javascript"
+ src="../promisified-events.js"></script>
+
+ <script type="application/javascript">
+ <![CDATA[
+ const { BrowserTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/BrowserTestUtils.sys.mjs");
+ const ABOUT_MOZILLA_URL = "about:mozilla";
+ const ABOUT_LICENSE_URL = "about:license";
+
+ SimpleTest.waitForExplicitFinish();
+
+ (async () => {
+ info("Opening a new browser window.");
+ const win = await BrowserTestUtils.openNewBrowserWindow({
+ remote: false,
+ fission: false,
+ });
+ const winFocused = SimpleTest.promiseFocus(win);
+ const loaded = BrowserTestUtils.browserLoaded(
+ win.gBrowser.selectedBrowser);
+ let docLoaded = waitForEvent(EVENT_DOCUMENT_LOAD_COMPLETE, event =>
+ event.accessible.QueryInterface(nsIAccessibleDocument).URL === ABOUT_LICENSE_URL,
+ `Loaded tab: ${ABOUT_LICENSE_URL}`);
+ BrowserTestUtils.startLoadingURIString(win.gBrowser.selectedBrowser,
+ "about:license");
+ await loaded;
+ await docLoaded;
+ await winFocused;
+
+ info(`Loading a new tab: ${ABOUT_MOZILLA_URL}.`);
+ docLoaded = waitForEvent(EVENT_DOCUMENT_LOAD_COMPLETE, event =>
+ event.accessible.QueryInterface(nsIAccessibleDocument).URL === ABOUT_MOZILLA_URL,
+ `Added tab: ${ABOUT_MOZILLA_URL}`);
+ const tab = win.gBrowser.addTrustedTab(ABOUT_MOZILLA_URL);
+ await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+ await docLoaded;
+
+ info("Focusing on the newly opened tab.");
+ const focused = waitForEvent(EVENT_FOCUS, event =>
+ event.DOMNode === win.gBrowser.getBrowserAtIndex(1).contentDocument);
+ await BrowserTestUtils.synthesizeKey("VK_TAB", { ctrlKey: true },
+ win.gBrowser.selectedBrowser);
+ const focusEvent = await focused;
+
+ const title = getAccessible(win.document).name;
+ const accName = focusEvent.accessible.name;
+ isnot(title.indexOf(accName), -1,
+ `Window title contains the name of active tab document (Is "${accName}" in "${title}"?)`);
+
+ await BrowserTestUtils.closeWindow(win);
+ SimpleTest.finish();
+ })();
+ ]]>
+ </script>
+
+ <vbox flex="1" style="overflow: auto;">
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=507382"
+ title="focus is fired earlier than root accessible name is changed when switching between tabs">
+ Mozilla Bug
+ </a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <pre id="test">
+ </pre>
+ </body>
+
+ <vbox id="eventdump"></vbox>
+ </vbox>
+</window>
diff --git a/accessible/tests/mochitest/name/test_counterstyle.html b/accessible/tests/mochitest/name/test_counterstyle.html
new file mode 100644
index 0000000000..a20aca23f1
--- /dev/null
+++ b/accessible/tests/mochitest/name/test_counterstyle.html
@@ -0,0 +1,150 @@
+<html>
+
+<head>
+ <title>nsIAccessible::name calculation for @counter-style</title>
+ <link rel="stylesheet" type="text/css"
+ href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <script type="application/javascript"
+ src="../common.js"></script>
+ <script type="application/javascript"
+ src="../name.js"></script>
+
+ <style id="counterstyles" type="text/css">
+ @counter-style system-alphabetic {
+ system: alphabetic;
+ symbols: x y z;
+ }
+ @counter-style system-cyclic {
+ system: cyclic;
+ symbols: x y z;
+ }
+ @counter-style system-numeric {
+ system: numeric;
+ symbols: x y z;
+ }
+ @counter-style speak-as-bullets {
+ system: extends decimal;
+ speak-as: bullets;
+ }
+ @counter-style speak-as-numbers {
+ system: extends system-alphabetic;
+ speak-as: numbers;
+ }
+ @counter-style speak-as-words {
+ system: additive;
+ additive-symbols: 20 "twenty ", 9 "nine", 7 "seven", 1 "one";
+ speak-as: words;
+ }
+ @counter-style speak-as-spell-out {
+ system: extends system-alphabetic;
+ speak-as: spell-out;
+ }
+ @counter-style speak-as-other {
+ system: extends decimal;
+ speak-as: speak-as-words;
+ }
+ @counter-style speak-as-loop {
+ system: extends upper-latin;
+ speak-as: speak-as-loop0;
+ }
+ @counter-style speak-as-loop0 {
+ system: extends disc;
+ speak-as: speak-as-loop1;
+ }
+ @counter-style speak-as-loop1 {
+ system: extends decimal;
+ speak-as: speak-as-loop0;
+ }
+ @counter-style speak-as-extended0 {
+ system: extends decimal;
+ speak-as: speak-as-extended1;
+ }
+ @counter-style speak-as-extended1 {
+ system: extends speak-as-extended0;
+ speak-as: disc;
+ }
+ @counter-style speak-as-extended2 {
+ system: extends decimal;
+ speak-as: speak-as-extended3;
+ }
+ @counter-style speak-as-extended3 {
+ system: extends speak-as-extended2;
+ }
+ </style>
+
+ <script type="application/javascript">
+
+ function doTest() {
+ function testRule(aRule, aNames, aTodo) {
+ testName(aRule + "-1", aNames[0], null, aTodo);
+ testName(aRule + "-7", aNames[1], null, aTodo);
+ testName(aRule + "-29", aNames[2], null, aTodo);
+ }
+
+ var spellOutNames = ["X. 1", "Y X. 7", "Y Z Y. 29"];
+ var bulletsNames = [kDiscBulletText + "1",
+ kDiscBulletText + "7",
+ kDiscBulletText + "29"];
+ var numbersNames = ["1. 1", "7. 7", "29. 29"];
+ var wordsNames = ["one. 1", "seven. 7", "twenty nine. 29"];
+
+ testRule("system-alphabetic", spellOutNames, true); // bug 1024178
+ testRule("system-cyclic", bulletsNames);
+ testRule("system-numeric", numbersNames);
+
+ testRule("speak-as-bullets", bulletsNames);
+ testRule("speak-as-numbers", numbersNames);
+ testRule("speak-as-words", wordsNames);
+ testRule("speak-as-spell-out", spellOutNames, true); // bug 1024178
+ testRule("speak-as-other", wordsNames);
+
+ testRule("speak-as-loop", bulletsNames);
+ testRule("speak-as-loop0", bulletsNames);
+ testRule("speak-as-loop1", numbersNames);
+
+ testRule("speak-as-extended0", bulletsNames);
+ testRule("speak-as-extended1", bulletsNames);
+ testRule("speak-as-extended2", numbersNames);
+ testRule("speak-as-extended3", numbersNames);
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(doTest);
+ </script>
+
+</head>
+
+<body>
+
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=966166"
+ title="Bug 966166 - Implement @counter-style rule">
+ Bug 966166
+ </a>
+
+ <ol id="list"></ol>
+
+ <script type="application/javascript">
+ var list = getNode("list");
+ var rules = getNode("counterstyles").sheet.cssRules;
+ var values = [1, 7, 29];
+ for (var i = 0; i < rules.length; i++) {
+ var rule = rules[i];
+ for (var j = 0; j < values.length; j++) {
+ var item = document.createElement("li");
+ item.id = rule.name + "-" + values[j];
+ item.value = values[j];
+ item.textContent = values[j];
+ item.setAttribute("style", "list-style-type: " + rule.name);
+ list.appendChild(item);
+ }
+ }
+ </script>
+
+</body>
+</html>
diff --git a/accessible/tests/mochitest/name/test_general.html b/accessible/tests/mochitest/name/test_general.html
new file mode 100644
index 0000000000..09723e6222
--- /dev/null
+++ b/accessible/tests/mochitest/name/test_general.html
@@ -0,0 +1,780 @@
+<html>
+
+<head>
+ <title>nsIAccessible::name calculation</title>
+ <link rel="stylesheet" type="text/css"
+ href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <script type="application/javascript"
+ src="../common.js"></script>
+ <script type="application/javascript"
+ src="../name.js"></script>
+
+ <script type="application/javascript">
+
+ function doTest() {
+ // aria-label
+
+ // Simple label provided via ARIA
+ testName("btn_simple_aria_label", "I am a button");
+
+ // aria-label and aria-labelledby, expect aria-labelledby
+ testName("btn_both_aria_labels", "text I am a button, two");
+
+ // ////////////////////////////////////////////////////////////////////////
+ // aria-labelledby
+
+ // Single relation. The value of 'aria-labelledby' contains the ID of
+ // an element. Gets the name from text node of that element.
+ testName("btn_labelledby_text", "text");
+
+ // Multiple relations. The value of 'aria-labelledby' contains the IDs
+ // of elements. Gets the name from text nodes of those elements.
+ testName("btn_labelledby_texts", "text1 text2");
+
+ // ////////////////////////////////////////////////////////////////////////
+ // Name from named accessible
+
+ testName("input_labelledby_namedacc", "Data");
+
+ // ////////////////////////////////////////////////////////////////////////
+ // Name from subtree (single relation labelled_by).
+
+ // Gets the name from text nodes contained by nested elements
+ testName("btn_labelledby_mixed", "nomore text");
+
+ // Gets the name from text nodes contained by nested elements, ignores
+ // hidden elements (bug 443081).
+ testName("btn_labelledby_mixed_hidden_child", "nomore text2");
+
+ // Gets the name from hidden text nodes contained by nested elements,
+ // (label element is hidden entirely), (bug 443081).
+ testName("btn_labelledby_mixed_hidden", "lala more hidden text");
+
+ // Gets the name from text nodes contained by nested elements having block
+ // representation (every text node value in the name should be devided by
+ // spaces)
+ testName("btn_labelledby_mixed_block", "text more text");
+
+ // Gets the name from text nodes contained by html:td. The text nodes
+ // should not be divided by spaces.
+ testName("btn_labelledby_mixed_table", "textTEXTtext");
+
+ // Gets the name from image accessible.
+ testName("btn_labelledby_mixed_img", "text image");
+
+ // Gets the name from input accessibles
+ // Note: if input have label elements then the name isn't calculated
+ // from them.
+ testName("btn_labelledby_mixed_input",
+ "input button Submit Query Reset Submit Query");
+
+ // Gets the name from the title of object element.
+ testName("btn_labelledby_mixed_object", "object");
+
+ // Gets the name from text nodes. Element br adds space between them.
+ testName("btn_labelledby_mixed_br", "text text");
+
+ // Gets the name from label content which allows name from subtree,
+ // ignore @title attribute on label
+ testName("from_label_ignoretitle", "Country:");
+
+ // Gets the name from html:p content, which doesn't allow name from
+ // subtree, ignore @title attribute on label
+ testName("from_p_ignoretitle", "Choose country from.");
+
+ // Gets the name from html:input value, ignore @title attribute on input
+ testName("from_input_ignoretitle", "Custom country");
+
+ // Insert spaces around the control's value to not jamm sibling text nodes
+ testName("insert_spaces_around_control", "start value end");
+
+ // Gets the name from @title, ignore whitespace content
+ testName("from_label_ignore_ws_subtree", "about");
+
+ // role="alert" doesn't get name from subtree...
+ testName("alert", null);
+ // but the subtree is used if referenced by aria-labelledby.
+ testName("inputLabelledByAlert", "Error");
+
+ // ////////////////////////////////////////////////////////////////////////
+ // label element
+
+ // The label element contains the button. The name is calculated from
+ // this button.
+ // Note: the name contains the content of the button.
+ testName("btn_label_inside", "text10text");
+
+ // The label element and the button are placed in the same form. Gets
+ // the name from the label subtree.
+ testName("btn_label_inform", "in form");
+
+ // The label element is placed outside of form where the button is.
+ // Take into account the label.
+ testName("btn_label_outform", "out form");
+
+ // The label element and the button are in the same document. Gets the
+ // name from the label subtree.
+ testName("btn_label_indocument", "in document");
+
+ // Multiple label elements for single button
+ testName("btn_label_multi", "label1label2");
+
+ // Multiple controls inside a label element
+ testName("ctrl_in_label_1", "Enable a button control");
+ testName("ctrl_in_label_2", "button");
+
+
+ // ////////////////////////////////////////////////////////////////////////
+ // name from children
+
+ // ARIA role button is presented allowing the name calculation from
+ // children.
+ testName("btn_children", "14");
+
+ // html:button, no name from content
+ testName("btn_nonamefromcontent", null);
+
+ // ARIA role option is presented allowing the name calculation from
+ // visible children (bug 443081).
+ testName("lb_opt1_children_hidden", "i am visible");
+
+ // Get the name from subtree of menuitem crossing role nothing to get
+ // the name from its children.
+ testName("tablemenuitem", "menuitem 1");
+
+ // Get the name from child acronym title attribute rather than from
+ // acronym content.
+ testName("label_with_acronym", "O A T F World Wide Web");
+
+ testName("testArticle", "Test article");
+
+ testName("h1", "heading");
+ testName("aria_heading", "aria_heading");
+
+ // ////////////////////////////////////////////////////////////////////////
+ // title attribute
+
+ // If nothing is left. Let's try title attribute.
+ testName("btn_title", "title");
+
+ // ////////////////////////////////////////////////////////////////////////
+ // textarea name
+
+ // textarea's name should have the value, which initially is specified by
+ // a text child.
+ testName("textareawithchild", "Story Foo is ended.");
+
+ // new textarea name should reflect the value change.
+ var elem = document.getElementById("textareawithchild");
+ elem.value = "Bar";
+
+ testName("textareawithchild", "Story Bar is ended.");
+
+ // ////////////////////////////////////////////////////////////////////////
+ // controls having a value used as a part of computed name
+
+ testName("ctrlvalue_progressbar:input", "foo 5 baz");
+ testName("ctrlvalue_scrollbar:input", "foo 5 baz");
+ testName("ctrlvalue_slider:input", "foo 5 baz");
+ testName("ctrlvalue_spinbutton:input", "foo 5 baz");
+ testName("ctrlvalue_combobox:input", "foo 5 baz");
+ testName("ctrlvalue_meter:input", "foo 5 baz");
+
+
+ // ///////////////////////////////////////////////////////////////////////
+ // label with nested combobox (test for 'f' item of name computation guide)
+
+ testName("comboinstart", "One day(s).");
+ testName("combo3", "day(s).");
+
+ testName("textboxinstart", "Two days.");
+ testName("textbox1", "days.");
+
+ testName("comboinmiddle", "Subscribe to ATOM feed.");
+ testName("combo4", "Subscribe to ATOM feed.");
+
+ testName("comboinmiddle2", "Play the Haliluya sound when new mail arrives");
+ testName("combo5", null); // label isn't used as a name for control
+ testName("checkbox", "Play the Haliluya sound when new mail arrives");
+ testName("comboinmiddle3", "Play the Haliluya sound when new mail arrives");
+ testName("combo6", "Play the Haliluya sound when new mail arrives");
+
+ testName("comboinend", "This day was sunny");
+ testName("combo7", "This day was");
+
+ testName("textboxinend", "This day was sunny");
+ testName("textbox2", "This day was");
+
+ // placeholder
+ testName("ph_password", "a placeholder");
+ testName("ph_text", "a placeholder");
+ testName("ph_textarea", "a placeholder");
+ testName("ph_text2", "a label");
+ testName("ph_textarea2", "a label");
+ testName("ph_text3", "a label");
+
+ // Test equation image
+ testName("img_eq", "x^2 + y^2 + z^2");
+ testName("input_img_eq", "x^2 + y^2 + z^2");
+ testName("txt_eq", "x^2 + y^2 + z^2");
+
+ // //////////////////////////////////////////////////////////////////////
+ // tests for duplicate announcement of content
+
+ testName("test_note", null);
+
+ // //////////////////////////////////////////////////////////////////////
+ // Tests for name from sub tree of tr element.
+
+ // By default, we want no name.
+ testName("NoNameForTR", null);
+ testName("NoNameForNonStandardTR", null);
+
+ // But we want it if the tr has an ARIA role.
+ testName("NameForTRBecauseStrongARIA", "a b");
+
+ // But not if it is a weak (landmark) ARIA role
+ testName("NoNameForTRBecauseWeakARIA", null);
+
+ // Name from sub tree of grouping if requested by other accessible.
+ testName("grouping", null);
+ testName("requested_name_from_grouping", "label");
+ testName("listitem_containing_block_tbody", "label");
+ // Groupings shouldn't be included when calculating from the subtree of
+ // a treeitem.
+ testName("treeitem_containing_grouping", "root");
+
+ // Name from subtree of grouping labelled by an ancestor.
+ testName("grouping_labelledby_ancestor", "label");
+
+ // Name from subtree of a container containing text nodes and inline
+ // elements. There should be no spaces because everyhing is inline.
+ testName("container_text_inline", "abc");
+ // Name from subtree of a container containing text nodes and block
+ // elements. There should be a space on both sides of the block.
+ testName("container_text_block", "a b c");
+ // Name from subtree of a container containing text nodes and empty
+ // block elements. There should be space on either side of the blocks, but
+ // not a double space.
+ testName("container_text_emptyblock", "a b");
+
+ const shadowRoot = getNode("shadowHost").shadowRoot;
+ const shadowButtonVisibleText = shadowRoot.getElementById("shadowButtonVisibleText");
+ testName(shadowButtonVisibleText, "shadowButtonVisibleText");
+ const shadowButtonHiddenText = shadowRoot.getElementById("shadowButtonHiddenText");
+ testName(shadowButtonHiddenText, "shadowButtonHiddenText");
+
+ // Label from a hidden element containing script and style elements.
+ testName("buttonScriptStyle", "content");
+
+ // Name from subtree on a link containing <code>, etc.
+ testName("linkWithCodeSupSubInsDel", "before code sup sub ins del after");
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(doTest);
+ </script>
+
+</head>
+
+<body>
+
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=428479"
+ title="Bug 428479 - Support ARIA role=math">
+ Bug 428479
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=429666"
+ title="Expose ROLE_DOCUMENT for ARIA landmarks that inherit from document">
+ Bug 429666
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=444279"
+ title="mochitest for accessible name calculating">
+ Bug 444279
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=459635"
+ title="nsIAccessible::name calculation for HTML buttons">
+ Bug 459635
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=530081"
+ title="Clean up our tree walker">
+ Bug 530081
+ </a><br>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=604391"
+ title="Use placeholder as name if name is otherwise empty">
+ Bug 604391
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=669312"
+ title="Accessible name is duplicated when input has a label associated uisng for/id and is wrapped around the input">
+ Bug 669312
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=704416"
+ title="HTML acronym and abbr names should be provided by @title">
+ Bug 704416
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=812041"
+ title="ARIA slider and spinbutton don't provide a value for name computation">
+ Bug 812041
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=823927"
+ title="Text is jammed with control's text in name computation">
+ Bug 823927
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=835666"
+ title="ARIA combobox selected value is not a part of name computation">
+ Bug 835666
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=833256"
+ title="role note shouldn't pick up the name from subtree">
+ Mozilla Bug 833256
+ </a>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+
+ <!-- aria-label, simple label -->
+ <span id="btn_simple_aria_label" role="button" aria-label="I am a button"/>
+ <br/>
+ <!-- aria-label plus aria-labelledby -->
+ <span id="btn_both_aria_labels" role="button" aria-label="I am a button, two"
+ aria-labelledby="labelledby_text btn_both_aria_labels"/>
+ <br/>
+
+ <!-- aria-labelledby, single relation -->
+ <span id="labelledby_text">text</span>
+ <button id="btn_labelledby_text"
+ aria-labelledby="labelledby_text">1</button>
+ <br/>
+
+ <!-- aria-labelledby, multiple relations -->
+ <span id="labelledby_text1">text1</span>
+ <span id="labelledby_text2">text2</span>
+ <button id="btn_labelledby_texts"
+ aria-labelledby="labelledby_text1 labelledby_text2">2</button>
+ <br/>
+
+ <!-- name from named accessible -->
+ <input id="labelledby_namedacc" type="checkbox"
+ aria-label="Data" />
+ <input id="input_labelledby_namedacc"
+ aria-labelledby="labelledby_namedacc" />
+
+ <!-- the name from subtree, mixed content -->
+ <span id="labelledby_mixed">no<span>more text</span></span>
+ <button id="btn_labelledby_mixed"
+ aria-labelledby="labelledby_mixed">3</button>
+ <br/>
+
+ <!-- the name from subtree, mixed/hidden content -->
+ <span id="labelledby_mixed_hidden_child">
+ no<span>more
+ <span style="display: none;">hidden</span>
+ text2
+ <span style="visibility: hidden">hidden2</span>
+ </span>
+ </span>
+ <button id="btn_labelledby_mixed_hidden_child"
+ aria-labelledby="labelledby_mixed_hidden_child">3.1</button>
+ <br/>
+
+ <!-- the name from subtree, mixed/completely hidden content -->
+ <span id="labelledby_mixed_hidden"
+ style="display: none;">lala <span>more hidden </span>text</span></span>
+ <button id="btn_labelledby_mixed_hidden"
+ aria-labelledby="labelledby_mixed_hidden">3.2</button>
+ <br/>
+
+ <!-- the name from subtree, mixed content, block structure -->
+ <div id="labelledby_mixed_block"><div>text</div>more text</div></div>
+ <button id="btn_labelledby_mixed_block"
+ aria-labelledby="labelledby_mixed_block">4</button>
+ <br/>
+
+ <!-- the name from subtree, mixed content, table structure -->
+ <table><tr>
+ <td id="labelledby_mixed_table">text<span>TEXT</span>text</td>
+ </tr></table>
+ <button id="btn_labelledby_mixed_table"
+ aria-labelledby="labelledby_mixed_table">5</button>
+ <br/>
+
+ <!-- the name from subtree, child img -->
+ <span id="labelledby_mixed_img">text<img alt="image"/></span>
+ <button id="btn_labelledby_mixed_img"
+ aria-labelledby="labelledby_mixed_img">6</button>
+ <br/>
+
+ <!-- the name from subtree, child inputs -->
+ <span id="labelledby_mixed_input">
+ <input type="button" id="input_button" title="input button"/>
+ <input type="submit" id="input_submit"/>
+ <input type="reset" id="input_reset"/>
+ <input type="image" id="input_image" title="input image"/>
+ </span>
+ <button id="btn_labelledby_mixed_input"
+ aria-labelledby="labelledby_mixed_input">7</button>
+ <br/>
+
+ <!-- the name from subtree, child object -->
+ <span id="labelledby_mixed_object">
+ <object data="about:blank" title="object"></object>
+ </span>
+ <button id="btn_labelledby_mixed_object"
+ aria-labelledby="labelledby_mixed_object">8</button>
+ <br/>
+
+ <!-- the name from subtree, child br -->
+ <span id="labelledby_mixed_br">text<br/>text</span>
+ <button id="btn_labelledby_mixed_br"
+ aria-labelledby="labelledby_mixed_br">9</button>
+ <br/>
+
+ <!-- the name from subtree, name from label content rather than from its title
+ attribute -->
+ <label for="from_label_ignoretitle"
+ title="Select your country of origin">Country:</label>
+ <select id="from_label_ignoretitle">
+ <option>Germany</option>
+ <option>Russia</option>
+ </select>
+
+ <!-- the name from subtree, name from html:p content rather than from its
+ title attribute -->
+ <p id="p_ignoretitle"
+ title="Select your country of origin">Choose country from.</p>
+ <select id="from_p_ignoretitle" aria-labelledby="p_ignoretitle">
+ <option>Germany</option>
+ <option>Russia</option>
+ </select>
+
+ <!-- the name from subtree, name from html:input value rather than from its
+ title attribute -->
+ <p id="from_input_ignoretitle" aria-labelledby="input_ignoretitle">Country</p>
+ <input id="input_ignoretitle"
+ value="Custom country"
+ title="Input your country of origin"/ >
+
+ <!-- name from subtree, surround control by spaces to not jamm the text -->
+ <label id="insert_spaces_around_control">
+ start<input value="value">end
+ </label>
+
+ <!-- no name from subtree because it holds whitespaces only -->
+ <a id="from_label_ignore_ws_subtree" href="about:mozilla" title="about">&nbsp;&nbsp; </a>
+
+ <!-- Don't use subtree unless referenced by aria-labelledby. -->
+ <div id="alert" role="alert">Error</div>
+ <input type="text" id="inputLabelledByAlert" aria-labelledby="alert">
+
+ <!-- label element, label contains control -->
+ <label>text<button id="btn_label_inside">10</button>text</label>
+ <br/>
+
+ <!-- label element, label and the button are in the same form -->
+ <form>
+ <label for="btn_label_inform">in form</label>
+ <button id="btn_label_inform">11</button>
+ </form>
+
+ <!-- label element, label is outside of the form of the button -->
+ <label for="btn_label_outform">out form</label>
+ <form>
+ <button id="btn_label_outform">12</button>
+ </form>
+
+ <!-- label element, label and the button are in the same document -->
+ <label for="btn_label_indocument">in document</label>
+ <button id="btn_label_indocument">13</button>
+
+ <!-- multiple label elements for single button -->
+ <label for="btn_label_multi">label1</label>
+ <label for="btn_label_multi">label2</label>
+ <button id="btn_label_multi">button</button>
+
+ <!-- a label containing more than one controls -->
+ <label>
+ Enable <input id="ctrl_in_label_1" type="checkbox"> a
+ <input id="ctrl_in_label_2" type="button" value="button"> control
+ </label>
+
+ <!-- name from children -->
+ <span id="btn_children" role="button">14</span>
+
+ <!-- no name from content, ARIA role overrides this rule -->
+ <button id="btn_nonamefromcontent" role="img">1</button>
+
+ <!-- name from children, hidden children -->
+ <div role="listbox" tabindex="0">
+ <div id="lb_opt1_children_hidden" role="option" tabindex="0">
+ <span>i am visible</span>
+ <span style="display:none">i am hidden</span>
+ </div>
+ </div>
+
+ <table role="menu">
+ <tr role="menuitem" id="tablemenuitem">
+ <td>menuitem 1</td>
+ </tr>
+ <tr role="menuitem">
+ <td>menuitem 2</td>
+ </tr>
+ </table>
+
+ <label id="label_with_acronym">
+ <acronym title="O A T F">OATF</acronym>
+ <abbr title="World Wide Web">WWW</abbr>
+ </label>
+
+ <div id="testArticle" role="article" title="Test article">
+ <p>This is a paragraph inside the article.</p>
+ </div>
+
+ <h1 id="h1" title="oops">heading</h1>
+ <div role="heading" id="aria_heading">aria_heading</div>
+
+ <!-- name from title attribute -->
+ <span id="btn_title" role="group" title="title">15</span>
+
+ <!-- A textarea nested in a label with a text child (bug #453371). -->
+ <form>
+ <label>Story
+ <textarea id="textareawithchild" name="name">Foo</textarea>
+ is ended.
+ </label>
+ </form>
+
+ <!-- controls having a value used as part of computed name -->
+ <input type="checkbox" id="ctrlvalue_progressbar:input">
+ <label for="ctrlvalue_progressbar:input">
+ foo <span role="progressbar"
+ aria-valuenow="5" aria-valuemin="1"
+ aria-valuemax="10">5</span> baz
+ </label>
+
+ <input type="checkbox" id="ctrlvalue_scrollbar:input" />
+ <label for="ctrlvalue_scrollbar:input">
+ foo <span role="scrollbar"
+ aria-valuenow="5" aria-valuemin="1"
+ aria-valuemax="10">5</span> baz
+ </label>
+
+ <input type="checkbox" id="ctrlvalue_slider:input">
+ <label for="ctrlvalue_slider:input">
+ foo <input role="slider" type="range"
+ value="5" min="1" max="10"
+ aria-valuenow="5" aria-valuemin="1"
+ aria-valuemax="10"> baz
+ </label>
+
+ <input type="checkbox" id="ctrlvalue_spinbutton:input">
+ <label for="ctrlvalue_spinbutton:input">
+ foo <input role="spinbutton" type="number"
+ value="5" min="1" max="10"
+ aria-valuenow="5" aria-valuemin="1"
+ aria-valuemax="10">
+ baz
+ </label>
+
+ <input type="checkbox" id="ctrlvalue_combobox:input">
+ <label for="ctrlvalue_combobox:input">
+ foo
+ <div role="combobox">
+ <div role="textbox"></div>
+ <ul role="listbox" style="list-style-type: none;">
+ <li role="option">1</li>
+ <li role="option" aria-selected="true">5</li>
+ <li role="option">3</li>
+ </ul>
+ </div>
+ baz
+ </label>
+
+ <input type="checkbox" id="ctrlvalue_meter:input">
+ <label for="ctrlvalue_meter:input">
+ foo
+ <meter>5</meter>
+ </div>
+ baz
+ </label>
+
+ <!-- a label with a nested control in the start, middle and end -->
+ <form>
+ <!-- at the start (without and with whitespaces) -->
+ <label id="comboinstart"><select id="combo3">
+ <option>One</option>
+ <option>Two</option>
+ </select>
+ day(s).
+ </label>
+
+ <label id="textboxinstart">
+ <input id="textbox1" value="Two">
+ days.
+ </label>
+
+ <!-- in the middle -->
+ <label id="comboinmiddle">
+ Subscribe to
+ <select id="combo4" name="occupation">
+ <option>ATOM</option>
+ <option>RSS</option>
+ </select>
+ feed.
+ </label>
+
+ <label id="comboinmiddle2" for="checkbox">Play the
+ <select id="combo5">
+ <option>Haliluya</option>
+ <option>Hurra</option>
+ </select>
+ sound when new mail arrives
+ </label>
+ <input id="checkbox" type="checkbox" />
+
+ <label id="comboinmiddle3" for="combo6">Play the
+ <select id="combo6">
+ <option>Haliluya</option>
+ <option>Hurra</option>
+ </select>
+ sound when new mail arrives
+ </label>
+
+ <!-- at the end (without and with whitespaces) -->
+ <label id="comboinend">
+ This day was
+ <select id="combo7" name="occupation">
+ <option>sunny</option>
+ <option>rainy</option>
+ </select></label>
+
+ <label id="textboxinend">
+ This day was
+ <input id="textbox2" value="sunny">
+ </label>
+ </form>
+
+ <!-- placeholder -->
+ <input id="ph_password" type="password" value="" placeholder="a placeholder" />
+ <input id="ph_text" type="text" placeholder="a placeholder" />
+ <textarea id="ph_textarea" cols="5" placeholder="a placeholder"></textarea>
+
+ <!-- placeholder does not win -->
+ <input id="ph_text2" type="text" aria-label="a label" placeholder="meh" />
+ <textarea id="ph_textarea2" cols="5" aria-labelledby="ph_text2"
+ placeholder="meh"></textarea>
+
+ <label for="ph_text3">a label</label>
+ <input id="ph_text3" placeholder="meh" />
+
+ <p>Image:
+ <img id="img_eq" role="math" src="foo" alt="x^2 + y^2 + z^2">
+ <input type="image" id="input_img_eq" src="foo" alt="x^2 + y^2 + z^2">
+ </p>
+
+ <p>Text:
+ <span id="txt_eq" role="math" title="x^2 + y^2 + z^2">x<sup>2</sup> +
+ y<sup>2</sup> + z<sup>2</sup></span>
+
+ <!-- duplicate announcement -->
+ <div id="test_note" role="note">subtree</div>
+
+ <!-- No name for tr from its sub tree -->
+ <table><tr id="NoNameForTR"><th>a</th><td>b</td></tr></table>
+ <table style="display: block;">
+ <tr id="NoNameForNonStandardTR" style="display:block;">
+ <th>a</th><td>b</td>
+ </tr>
+ </table>
+
+ <!-- Name from sub tree of tr, because it has a strong ARIA role -->
+ <table><tr id="NameForTRBecauseStrongARIA" role="row"><th>a</th><td>b</td></tr></table>
+
+ <!-- No name for tr because of weak (landmark) role -->
+ <table><tr id="NoNameForTRBecauseWeakARIA" role="main"><th>a</th><td>b</td></tr></table>
+
+ <!-- Name from subtree of grouping if requested by other object -->
+ <div id="grouping" role="group">label</div>
+ <button id="requested_name_from_grouping"aria-labelledby="grouping"></button>
+ <!-- Name from sub tree of tbody marked as display:block;, which is also a grouping -->
+ <div id="listitem_containing_block_tbody" role="listitem">
+ <table>
+ <tbody style="display: block;">
+ <tr><td>label</td></tr>
+ </tbody>
+ </table>
+ </div>
+ <!-- Name from subtree of treeitem containing grouping -->
+ <div id="treeitem_containing_grouping" role="treeitem" aria-level="1" aria-expanded="true">root
+ <div role="group">
+ <div role="treeitem" aria-level="2">sub</div>
+ </div>
+ </div>
+
+ <!-- Name from subtree of grouping labelled by an ancestor. -->
+ <div id="grouping_ancestor_label">label
+ <div id="grouping_labelledby_ancestor" role="group" aria-labelledby="grouping_ancestor_label">
+ This content should not be included in the grouping's label.
+ </div>
+ </div>
+
+ <!-- Text nodes and inline elements. -->
+ <div id="container_text_inline" role="option">a<strong>b</strong>c</div>
+ <!-- Text nodes and block elements. -->
+ <div id="container_text_block" role="option">a<p>b</p>c</div>
+ <!-- Text nodes and empty block elements. -->
+ <div id="container_text_emptyblock" role="option">a<p></p><p></p>b</div>
+
+ <!-- aria-labelledby referring to a slot -->
+ <div id="shadowHost">
+ shadowButtonVisibleText
+ <span slot="hiddenSlot">shadowButtonHiddenText</span>
+ </div>
+ <template id="shadowTemplate">
+ <input type="button" id="shadowButtonVisibleText" aria-labelledby="visibleSlot">
+ <slot id="visibleSlot"></slot>
+ <input type="button" id="shadowButtonHiddenText" aria-labelledby="hiddenSlot">
+ <slot id="hiddenSlot" name="hiddenSlot" hidden></slot>
+ </template>
+ <script>
+ const shadowHost = document.getElementById("shadowHost");
+ const shadowRoot = shadowHost.attachShadow({ mode: "open" });
+ shadowRoot.append(document.getElementById("shadowTemplate").content.cloneNode(true));
+ </script>
+
+ <!-- aria-labelledby referring to a hidden container with script/style -->
+ <button id="buttonScriptStyle" aria-labelledby="hiddenScriptStyle"></button>
+ <div id="hiddenScriptStyle" hidden>
+ <script> 42; </script>
+ <style> .noOp {} </style>
+ <span>content</span>
+ </div>
+
+ <!-- Name from subtree on link including <code>, etc. -->
+ <a id="linkWithCodeSupSubInsDel" href="#">
+ before
+ <code>code</code>
+ <sup>sup</sup>
+ <sub>sub</sub>
+ <ins>ins</ins>
+ <del>del</del>
+ after
+ </a>
+</body>
+</html>
diff --git a/accessible/tests/mochitest/name/test_general.xhtml b/accessible/tests/mochitest/name/test_general.xhtml
new file mode 100644
index 0000000000..3c5bb23309
--- /dev/null
+++ b/accessible/tests/mochitest/name/test_general.xhtml
@@ -0,0 +1,345 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ title="Accessibility Name Calculating Test.">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+ <script type="application/javascript"
+ src="../common.js"></script>
+ <script type="application/javascript"
+ src="../role.js"></script>
+ <script type="application/javascript"
+ src="../name.js"></script>
+
+ <script type="application/javascript">
+ <![CDATA[
+ function doTest()
+ {
+ // aria-label
+
+ // Simple label provided via ARIA
+ testName("btn_simple_aria_label", "I am a button");
+
+ // aria-label and aria-labelledby, expect aria-labelledby
+ testName("btn_both_aria_labels", "text I am a button, two");
+
+ //////////////////////////////////////////////////////////////////////////
+ // aria-labelledby
+
+ // Single relation. The value of 'aria-labelledby' contains the ID of
+ // an element. Gets the name from text node of that element.
+ testName("btn_labelledby_text", "text");
+
+ // Multiple relations. The value of 'aria-labelledby' contains the IDs
+ // of elements. Gets the name from text nodes of those elements.
+ testName("btn_labelledby_texts", "text1 text2");
+
+ // Trick cases. Self and recursive referencing.
+ testName("rememberHistoryDays", "Remember 3 days");
+ testName("historyDays", "Remember 3 days");
+ testName("rememberAfter", "days");
+
+ //////////////////////////////////////////////////////////////////////////
+ // Name from subtree (single relation labelled_by).
+
+ // Gets the name from text nodes contained by nested elements.
+ testName("btn_labelledby_mixed", "no more text");
+
+ // Gets the name from text nodes and selected item of menulist
+ // (other items are ignored).
+ testName("btn_labelledby_mixed_menulist",
+ "no more text selected item more text");
+
+ // Gets the name from text nodes contained by nested elements, ignores
+ // hidden elements (bug 443081).
+ testName("btn_labelledby_mixed_hidden_child", "no more text2");
+
+ // Gets the name from hidden text nodes contained by nested elements,
+ // (label element is hidden entirely), (bug 443081)
+ testName("btn_labelledby_mixed_hidden", "lala more hidden text");
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // Name from @label attribute.
+
+ // Gets the name from @label attribute.
+ testName("btn_labelattr", "labeled element");
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // Name for nsIDOMXULSelectControlItemElement.
+
+ // Gets the name from @label attribute.
+ testName("li_nsIDOMXULSelectControlItemElement", "select control item");
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // Name if the XUL element doesn't implement nsIDOMXULSelectControlElement
+ // and has @label attribute.
+
+ testName("box_not_nsIDOMXULSelectControlElement", "box");
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // Name from the label element.
+
+ // The label and button are placed on 2nd level relative common parent.
+ testName("btn_label_1", "label1");
+
+ // The label is on 1st, the button is on 5th level relative common parent.
+ testName("btn_label_2", "label2");
+
+ // The label and button are siblings.
+ testName("btn_label_3", "label3");
+
+ // Multiple labels for single button: XUL button takes the last one.
+ testName("btn_label_4", "label5");
+
+ // Label associated with HTML element.
+ testName("input_label", "input label");
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // tooltiptext (if nothing above isn't presented then tooltiptext is used)
+ testName("box_tooltiptext", "tooltiptext label");
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // Name from the @title attribute of <toolbaritem/> (original bug 237249).
+
+ // Direct child of toolbaritem.
+ testName("toolbaritem_child", null);
+
+ // Child from subtree of toolbaritem.
+ testName("toolbaritem_hboxbutton", "button");
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // name from label inside toolbar button
+ testName("toolbarbuttonwithlabel", "I am the button");
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // Name from children
+
+ // ARIA role button is presented allowing the name calculation from
+ // children.
+ testName("box_children", "14");
+
+ // Button labelled by a text child.
+ testName("button_text", "Text");
+ testName("toolbarbutton_text", "Text");
+
+ // ARIA role option is presented allowing the name calculation from
+ // the visible children (bug 443081)
+ testName("lb_opt1_children_hidden", "i am visible");
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // Name from aria-labelledby: menuitem label+ listitem label
+ testName("li_labelledby", "Show an Alert The moment the event starts");
+
+ //////////////////////////////////////////////////////////////////////////
+ // groupbox labeling from first label
+ testName("groupbox", "Some caption");
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(doTest);
+ ]]>
+ </script>
+
+ <hbox flex="1" style="overflow: auto;">
+
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=444279"
+ title="mochitest for accessible name calculating">
+ Mozilla Bug 444279
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=441991"
+ title="nsXULListitemAccessible::GetName prefers label \
+ attribute over aria-labelledby and doesn't allow recursion">
+ Mozilla Bug 441991
+ </a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <pre id="test">
+ </pre>
+ </body>
+
+ <vbox flex="1">
+
+ <!-- aria-label, simple label -->
+ <button id="btn_simple_aria_label" aria-label="I am a button"/>
+
+ <!-- aria-label plus aria-labelledby -->
+ <button id="btn_both_aria_labels" aria-label="I am a button, two"
+ aria-labelledby="labelledby_text btn_both_aria_labels"/>
+
+ <!-- aria-labelledby, single relation -->
+ <description id="labelledby_text">text</description>
+ <button id="btn_labelledby_text"
+ aria-labelledby="labelledby_text"/>
+
+ <!-- aria-labelledby, multiple relations -->
+ <description id="labelledby_text1">text1</description>
+ <description id="labelledby_text2">text2</description>
+ <button id="btn_labelledby_texts"
+ aria-labelledby="labelledby_text1 labelledby_text2"/>
+
+ <!-- trick aria-labelledby -->
+ <checkbox id="rememberHistoryDays"
+ label="Remember "
+ aria-labelledby="rememberHistoryDays historyDays rememberAfter"/>
+ <html:input id="historyDays" value="3"
+ aria-labelledby="rememberHistoryDays historyDays rememberAfter"/>
+ <label id="rememberAfter">days</label>
+
+ <!-- the name from subtree, mixed content -->
+ <description id="labelledby_mixed">
+ no<description>more text</description>
+ </description>
+ <button id="btn_labelledby_mixed"
+ aria-labelledby="labelledby_mixed"/>
+
+ <!-- the name from subtree, mixed/hidden content -->
+ <description id="labelledby_mixed_hidden_child">no<description>more <description hidden="true">hidden</description>text2</description></description>
+ <button id="btn_labelledby_mixed_hidden_child"
+ aria-labelledby="labelledby_mixed_hidden_child"/>
+
+ <!-- the name from subtree, mixed/completely hidden content -->
+ <description id="labelledby_mixed_hidden"
+ hidden="true">lala <description>more hidden </description>text</description>
+ <button id="btn_labelledby_mixed_hidden"
+ aria-labelledby="labelledby_mixed_hidden"/>
+ <br/>
+
+ <!-- the name from subtree, mixed content, ignore items of menulist -->
+ <description id="labelledby_mixed_menulist">
+ no<description>more text</description>
+ <menulist>
+ <menupopup>
+ <menuitem label="selected item"/>
+ <menuitem label="item"/>
+ </menupopup>
+ </menulist>
+ more text
+ </description>
+ <button id="btn_labelledby_mixed_menulist"
+ aria-labelledby="labelledby_mixed_menulist"/>
+
+ <!-- @label -->
+ <button id="btn_labelattr"
+ label="labeled element"/>
+
+ <!-- nsIDOMXULSelectControlItemElement -->
+ <richlistbox>
+ <richlistitem id="li_nsIDOMXULSelectControlItemElement">
+ <label value="select control item"/>
+ </richlistitem>
+ </richlistbox>
+
+ <!-- not nsIDOMXULSelectControlElement -->
+ <box id="box_not_nsIDOMXULSelectControlElement" role="group" label="box"/>
+
+ <!-- label element -->
+ <hbox>
+ <box>
+ <label control="btn_label_1">label1</label>
+ </box>
+ <label control="btn_label_2">label2</label>
+ <box>
+ <button id="btn_label_1"/>
+ <box>
+ <box>
+ <box>
+ <button id="btn_label_2"/>
+ </box>
+ </box>
+ </box>
+ </box>
+ <label control="btn_label_3">label3</label>
+ <button id="btn_label_3"/>
+
+ <label control="btn_label_4">label4</label>
+ <label control="btn_label_4">label5</label>
+ <button id="btn_label_4"/>
+
+ <label control="input_label">input label</label>
+ <html:input id="input_label"/>
+ </hbox>
+
+ <!-- tooltiptext -->
+ <box id="box_tooltiptext"
+ role="group"
+ tooltiptext="tooltiptext label"/>
+
+ <!-- the name from @title of toolbaritem -->
+ <!-- and the name from label of a toolbarbutton -->
+ <toolbar>
+ <toolbaritem title="ooospspss">
+ <box id="toolbaritem_child"
+ role="group"
+ flex="1">
+ <hbox role="button" id="toolbaritem_hboxbutton">
+ <description value="button"/>
+ </hbox>
+ </box>
+ </toolbaritem>
+ <toolbarbutton id="toolbarbuttonwithlabel">
+ <label flex="1">I am the button</label>
+ </toolbarbutton>
+ </toolbar>
+
+ <!-- name from children -->
+ <box id="box_children" role="button">14</box>
+ <button id="button_text">Text</button>
+ <toolbarbutton id="toolbarbutton_text">Text</toolbarbutton>
+
+ <!-- name from children, hidden children -->
+ <vbox role="listbox" tabindex="0">
+ <hbox id="lb_opt1_children_hidden" role="option" tabindex="0">
+ <description>i am visible</description>
+ <description style="display:none">i am hidden</description>
+ </hbox>
+
+ <!-- Name from caption sub tree -->
+ <groupbox id="groupbox">
+ <label>Some caption</label>
+ <checkbox label="some checkbox label" />
+ </groupbox>
+ </vbox>
+
+ <!-- bug 441991; create name from other menuitem label listitem's own label -->
+ <hbox>
+ <richlistbox>
+ <richlistitem id="li_labelledby"
+ aria-labelledby="menuitem-DISPLAY li_labelledby">
+ <label value="The moment the event starts"/>
+ </richlistitem>
+ </richlistbox>
+ <menulist>
+ <menupopup>
+ <menuitem id="menuitem-DISPLAY"
+ value="DISPLAY"
+ label="Show an Alert"/>
+ <menuitem id="menuitem-EMAIL"
+ value="EMAIL"
+ label="Send an E-mail"/>
+ </menupopup>
+ </menulist>
+ </hbox>
+
+ </vbox> <!-- close tests area -->
+ </hbox> <!-- close main area -->
+</window>
diff --git a/accessible/tests/mochitest/name/test_link.html b/accessible/tests/mochitest/name/test_link.html
new file mode 100644
index 0000000000..6a289dd44f
--- /dev/null
+++ b/accessible/tests/mochitest/name/test_link.html
@@ -0,0 +1,87 @@
+<html>
+
+<head>
+ <title>nsIAccessible::name calculation for HTML links (html:a)</title>
+
+ <link rel="stylesheet"
+ type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <script type="application/javascript"
+ src="../common.js"></script>
+ <script type="application/javascript"
+ src="../name.js"></script>
+
+ <script type="application/javascript">
+ function doTest() {
+ // aria-label
+ testName("aria_label", "anchor label");
+
+ // aria-labelledby
+ testName("aria_labelledby", "text");
+
+ // name from content
+ testName("namefromcontent", "1");
+
+ // name from content
+ testName("namefromimg", "img title");
+
+ // no name from content
+ testName("nonamefromcontent", null);
+
+ // title
+ testName("title", "title");
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(doTest);
+ </script>
+
+</head>
+
+<body>
+
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=459782"
+ title="nsIAccessible::name calculation for HTML links (html:a)">
+ Mozilla Bug 459782
+ </a>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+
+ <!-- aria-label -->
+ <a id="aria_label" href="mozilla.org"
+ aria-label="anchor label">1</a>
+ <br/>
+
+ <!-- aria-labelledby, preferred to html:label -->
+ <span id="text">text</span>
+ <label for="aria_labelledby">label</label>
+ <a id="aria_labelledby" href="mozilla.org"
+ aria-labelledby="text">1</a>
+ <br/>
+
+ <!-- name from content, preferred to @title -->
+ <a id="namefromcontent" href="mozilla.org"
+ title="title">1</a>
+ <br/>
+
+ <!-- name from content, preferred to @title -->
+ <a id="namefromimg" href="mozilla.org"
+ title="title"><img alt="img title" /></a>
+
+ <!-- no name from content, ARIA role overrides this rule -->
+ <a id="nonamefromcontent" href="mozilla.org" role="img">1</a>
+ <br/>
+
+ <!-- no content, name from @title -->
+ <a id="title" href="mozilla.org"
+ title="title"></a>
+
+</body>
+</html>
diff --git a/accessible/tests/mochitest/name/test_list.html b/accessible/tests/mochitest/name/test_list.html
new file mode 100644
index 0000000000..95f0c06d2a
--- /dev/null
+++ b/accessible/tests/mochitest/name/test_list.html
@@ -0,0 +1,103 @@
+<html>
+
+<head>
+ <title>nsIAccessible::name calculation for HTML li</title>
+ <link rel="stylesheet" type="text/css"
+ href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <script type="application/javascript"
+ src="../common.js"></script>
+ <script type="application/javascript"
+ src="../name.js"></script>
+ <script type="application/javascript"
+ src="../events.js"></script>
+
+ <script type="application/javascript">
+ /**
+ * Alter list item numbering and change list style type.
+ */
+ function bulletUpdate() {
+ this.eventSeq = [
+ new invokerChecker(EVENT_REORDER, getNode("list")),
+ ];
+
+ this.invoke = function bulletUpdate_invoke() {
+ testName("li_end", "1. list end");
+
+ var li = document.createElement("li");
+ li.setAttribute("id", "li_start");
+ li.textContent = "list start";
+ getNode("list").insertBefore(li, getNode("li_end"));
+ };
+
+ this.finalCheck = function bulletUpdate_finalCheck() {
+ testName("li_start", "1. list start");
+ testName("li_end", "2. list end");
+ };
+
+ this.getID = function bulletUpdate_getID() {
+ return "insertBefore new list item";
+ };
+ }
+ function bulletUpdate2() {
+ this.eventSeq = [
+ new invokerChecker(EVENT_REORDER, getNode("li_end")),
+ ];
+
+ this.invoke = function bulletUpdate2_invoke() {
+ // change list style type
+ var list = getNode("list");
+ list.setAttribute("style", "list-style-type: disc;");
+
+ // Flush both the style change and the resulting layout change.
+ // Flushing style on its own is not sufficient, because that can
+ // leave frames marked with NS_FRAME_IS_DIRTY, which will cause
+ // nsTextFrame::GetRenderedText to report the text of a text
+ // frame is empty.
+ list.offsetWidth; // flush layout (which also flushes style)
+ };
+
+ this.finalCheck = function bulletUpdate2_finalCheck() {
+ testName("li_start", kDiscBulletText + "list start");
+ testName("li_end", kDiscBulletText + "list end");
+ };
+
+ this.getID = function bulletUpdate2_getID() {
+ return "Update list item style";
+ };
+ }
+
+ var gQueue = null;
+ function doTest() {
+ gQueue = new eventQueue();
+ gQueue.push(new bulletUpdate());
+ gQueue.push(new bulletUpdate2());
+ gQueue.invoke(); // SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(doTest);
+ </script>
+
+</head>
+
+<body>
+
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=634200"
+ title="crash [@ nsIFrame::StyleVisibility() ]">
+ Mozilla Bug 634200
+ </a>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+
+ <ol id="list">
+ <li id="li_end">list end</li>
+ </ol>
+
+</body>
+</html>
diff --git a/accessible/tests/mochitest/name/test_markup.html b/accessible/tests/mochitest/name/test_markup.html
new file mode 100644
index 0000000000..735027f44f
--- /dev/null
+++ b/accessible/tests/mochitest/name/test_markup.html
@@ -0,0 +1,58 @@
+<html>
+
+<head>
+ <title>nsIAccessible::name calculation for elements</title>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+
+ <script type="application/javascript"
+ src="../common.js"></script>
+ <script type="application/javascript"
+ src="../events.js"></script>
+ <script type="application/javascript"
+ src="../name.js"></script>
+ <script type="application/javascript"
+ src="../attributes.js"></script>
+
+ <script type="application/javascript"
+ src="markup.js"></script>
+
+ <script type="application/javascript">
+ // gA11yEventDumpID = "eventdump";
+ // gDumpToConsole = true;
+ // gA11yEventDumpToConsole = true;
+
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(testNames);
+ </script>
+
+</head>
+
+<body>
+
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=459635"
+ title="nsIAccessible::name calculation for elements">
+ Bug 459635
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=666212"
+ title="summary attribute content mapped to accessible name in MSAA">
+ Bug 666212
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=786163"
+ title=" Sort out name calculation for HTML input buttons">
+ Bug 786163
+ </a>
+
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+
+ <div id="eventdump"></div>
+</body>
+</html>
diff --git a/accessible/tests/mochitest/name/test_svg.html b/accessible/tests/mochitest/name/test_svg.html
new file mode 100644
index 0000000000..535fcdbf20
--- /dev/null
+++ b/accessible/tests/mochitest/name/test_svg.html
@@ -0,0 +1,53 @@
+<html>
+
+<head>
+ <title>Accessible name and description for SVG elements</title>
+ <link rel="stylesheet" type="text/css"
+ href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <script type="application/javascript"
+ src="../common.js"></script>
+ <script type="application/javascript"
+ src="../name.js"></script>
+
+ <script type="application/javascript">
+
+ function doTest() {
+ testName("svg1", "A name");
+ testDescr("svg1", "A description");
+ testName("svg2", "A tooltip");
+ testDescr("svg2", "");
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(doTest);
+ </script>
+
+</head>
+
+<body>
+
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=459357"
+ title="Support accessible name computation for SVG">
+ Mozilla Bug 459357
+ </a>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+
+ <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg1">
+ <title>A name</title>
+ <desc>A description</title>
+ </svg>
+
+ <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg2">
+ <desc>A tooltip</desc>
+ </svg>
+</body>
+</html>
diff --git a/accessible/tests/mochitest/name/test_tree.xhtml b/accessible/tests/mochitest/name/test_tree.xhtml
new file mode 100644
index 0000000000..3564481d00
--- /dev/null
+++ b/accessible/tests/mochitest/name/test_tree.xhtml
@@ -0,0 +1,207 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="Accessibility Name Calculating Test.">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+ <script type="application/javascript"
+ src="../treeview.js" />
+
+ <script type="application/javascript"
+ src="../common.js"></script>
+ <script type="application/javascript"
+ src="../role.js"></script>
+ <script type="application/javascript"
+ src="../name.js"></script>
+ <script type="application/javascript"
+ src="../events.js"></script>
+
+ <script type="application/javascript">
+ <![CDATA[
+ function treeTester(aID)
+ {
+ this.DOMNode = getNode(aID);
+
+ this.invoke = function treeTester_invoke()
+ {
+ this.DOMNode.view = new nsTreeTreeView();
+ }
+
+ this.check = function treeTester_check(aEvent)
+ {
+ var tree = {
+ role: ROLE_OUTLINE,
+ children: [
+ {
+ role: ROLE_LIST
+ },
+ {
+ role: ROLE_OUTLINEITEM,
+ children: [],
+ name: "row1col"
+ },
+ {
+ role: ROLE_OUTLINEITEM,
+ children: [],
+ name: "row2_col"
+ },
+ {
+ role: ROLE_OUTLINEITEM,
+ children: [],
+ name: "row2.1_col"
+ },
+ {
+ role: ROLE_OUTLINEITEM,
+ children: [],
+ name: "row2.2_col"
+ },
+ {
+ role: ROLE_OUTLINEITEM,
+ children: [],
+ name: "row3_col"
+ },
+ {
+ role: ROLE_OUTLINEITEM,
+ children: [],
+ name: "row4col"
+ }
+ ]
+ };
+ testAccessibleTree(this.DOMNode, tree);
+ }
+
+ this.getID = function treeTester_getID()
+ {
+ return "Tree name testing for " + aID;
+ }
+ }
+
+ function tableTester(aID, aIsTable, aCol1ID, aCol2ID)
+ {
+ this.DOMNode = getNode(aID);
+
+ this.invoke = function tableTester_invoke()
+ {
+ this.DOMNode.view = new nsTableTreeView(2);
+ }
+
+ this.check = function tableTester_check(aEvent)
+ {
+ var tree = {
+ role: aIsTable ? ROLE_TABLE : ROLE_TREE_TABLE,
+ children: [
+ {
+ role: ROLE_LIST
+ },
+ {
+ role: ROLE_ROW,
+ children: [
+ {
+ role: ROLE_GRID_CELL,
+ children: [],
+ name: "row0_" + aCol1ID
+ },
+ {
+ role: ROLE_GRID_CELL,
+ children: [],
+ name: "row0_" + aCol2ID
+ }
+ ],
+ name: "row0_" + aCol1ID + " row0_" + aCol2ID
+ },
+ {
+ role: ROLE_ROW,
+ children: [
+ {
+ role: ROLE_GRID_CELL,
+ children: [],
+ name: "row1_" + aCol1ID
+ },
+ {
+ role: ROLE_GRID_CELL,
+ children: [],
+ name: "row1_" + aCol2ID
+ }
+ ],
+ name: "row1_" + aCol1ID + " row1_" + aCol2ID
+ }
+ ]
+ };
+ testAccessibleTree(this.DOMNode, tree);
+ }
+
+ this.getID = function tableTester_getID()
+ {
+ return "Tree name testing for " + aID;
+ }
+ }
+
+ var gQueue = null;
+ function doTest()
+ {
+ gQueue = new eventQueue(EVENT_REORDER);
+
+ gQueue.push(new treeTester("tree"));
+ gQueue.push(new tableTester("table", true, "t_col1", "t_col2"));
+ gQueue.push(new tableTester("treetable", false, "tt_col1", "tt_col2"));
+
+ gQueue.invoke(); // Will call SimpleTest.finish()
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(doTest);
+ ]]>
+ </script>
+
+ <hbox flex="1" style="overflow: auto;">
+
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=546812"
+ title="Treegrid row accessible shouldn't inherit name from tree accessible">
+ Mozilla Bug 546812
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=664376"
+ title="Table rows of XUL trees no longer containing cell content as accessible name">
+ Mozilla Bug 664376
+ </a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <pre id="test">
+ </pre>
+ </body>
+
+ <vbox flex="1">
+
+ <tree id="tree" flex="1">
+ <treecols>
+ <treecol id="col" flex="1" primary="true" label="column"/>
+ </treecols>
+ <treechildren/>
+ </tree>
+
+ <tree id="table" flex="1">
+ <treecols>
+ <treecol id="t_col1" flex="1" label="column"/>
+ <treecol id="t_col2" flex="1" label="column 2"/>
+ </treecols>
+ <treechildren/>
+ </tree>
+
+ <tree id="treetable" flex="1">
+ <treecols>
+ <treecol id="tt_col1" flex="1" label="column" primary="true"/>
+ <treecol id="tt_col2" flex="1" label="column 2"/>
+ </treecols>
+ <treechildren/>
+ </tree>
+
+ </vbox> <!-- close tests area -->
+ </hbox> <!-- close main area -->
+</window>