summaryrefslogtreecommitdiffstats
path: root/accessible/tests/mochitest/attributes
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--accessible/tests/mochitest/attributes.js516
-rw-r--r--accessible/tests/mochitest/attributes/a11y.ini14
-rw-r--r--accessible/tests/mochitest/attributes/test_dpub_aria_xml-roles.html120
-rw-r--r--accessible/tests/mochitest/attributes/test_graphics_aria_xml-roles.html48
-rw-r--r--accessible/tests/mochitest/attributes/test_listbox.html82
-rw-r--r--accessible/tests/mochitest/attributes/test_obj.html292
-rw-r--r--accessible/tests/mochitest/attributes/test_obj_css.html225
-rw-r--r--accessible/tests/mochitest/attributes/test_obj_group.html564
-rw-r--r--accessible/tests/mochitest/attributes/test_obj_group.xhtml215
-rw-r--r--accessible/tests/mochitest/attributes/test_obj_group_tree.xhtml84
-rw-r--r--accessible/tests/mochitest/attributes/test_tag.html80
-rw-r--r--accessible/tests/mochitest/attributes/test_xml-roles.html267
12 files changed, 2507 insertions, 0 deletions
diff --git a/accessible/tests/mochitest/attributes.js b/accessible/tests/mochitest/attributes.js
new file mode 100644
index 0000000000..ebb5a54b85
--- /dev/null
+++ b/accessible/tests/mochitest/attributes.js
@@ -0,0 +1,516 @@
+/* import-globals-from common.js */
+
+// //////////////////////////////////////////////////////////////////////////////
+// Object attributes.
+
+/**
+ * Test object attributes.
+ *
+ * @param aAccOrElmOrID [in] the accessible identifier
+ * @param aAttrs [in] the map of expected object attributes
+ * (name/value pairs)
+ * @param aSkipUnexpectedAttrs [in] points this function doesn't fail if
+ * unexpected attribute is encountered
+ * @param aTodo [in] true if this is a 'todo'
+ */
+function testAttrs(aAccOrElmOrID, aAttrs, aSkipUnexpectedAttrs, aTodo) {
+ testAttrsInternal(aAccOrElmOrID, aAttrs, aSkipUnexpectedAttrs, null, aTodo);
+}
+
+/**
+ * Test object attributes that must not be present.
+ *
+ * @param aAccOrElmOrID [in] the accessible identifier
+ * @param aAbsentAttrs [in] map of attributes that should not be
+ * present (name/value pairs)
+ * @param aTodo [in] true if this is a 'todo'
+ */
+function testAbsentAttrs(aAccOrElmOrID, aAbsentAttrs, aTodo) {
+ testAttrsInternal(aAccOrElmOrID, {}, true, aAbsentAttrs, aTodo);
+}
+
+/**
+ * Test object attributes that aren't right, but should be (todo)
+ *
+ * @param aAccOrElmOrID [in] the accessible identifier
+ * @param aKey [in] attribute name
+ * @param aExpectedValue [in] expected attribute value
+ */
+function todoAttr(aAccOrElmOrID, aKey, aExpectedValue) {
+ testAttrs(
+ aAccOrElmOrID,
+ Object.fromEntries([[aKey, aExpectedValue]]),
+ true,
+ true
+ );
+}
+
+/**
+ * Test CSS based object attributes.
+ */
+function testCSSAttrs(aID) {
+ var node = document.getElementById(aID);
+ var computedStyle = document.defaultView.getComputedStyle(node);
+
+ var attrs = {
+ display: computedStyle.display,
+ "text-align": computedStyle.textAlign,
+ "text-indent": computedStyle.textIndent,
+ "margin-left": computedStyle.marginLeft,
+ "margin-right": computedStyle.marginRight,
+ "margin-top": computedStyle.marginTop,
+ "margin-bottom": computedStyle.marginBottom,
+ };
+ testAttrs(aID, attrs, true);
+}
+
+/**
+ * Test the accessible that it doesn't have CSS-based object attributes.
+ */
+function testAbsentCSSAttrs(aID) {
+ var attrs = {
+ display: "",
+ "text-align": "",
+ "text-indent": "",
+ "margin-left": "",
+ "margin-right": "",
+ "margin-top": "",
+ "margin-bottom": "",
+ };
+ testAbsentAttrs(aID, attrs);
+}
+
+/**
+ * Test group object attributes (posinset, setsize and level) and
+ * nsIAccessible::groupPosition() method.
+ *
+ * @param aAccOrElmOrID [in] the ID, DOM node or accessible
+ * @param aPosInSet [in] the value of 'posinset' attribute
+ * @param aSetSize [in] the value of 'setsize' attribute
+ * @param aLevel [in, optional] the value of 'level' attribute
+ */
+function testGroupAttrs(aAccOrElmOrID, aPosInSet, aSetSize, aLevel, aTodo) {
+ var acc = getAccessible(aAccOrElmOrID);
+ var levelObj = {},
+ posInSetObj = {},
+ setSizeObj = {};
+ acc.groupPosition(levelObj, setSizeObj, posInSetObj);
+
+ let groupPos = {},
+ expectedGroupPos = {};
+
+ if (aPosInSet && aSetSize) {
+ groupPos.setsize = String(setSizeObj.value);
+ groupPos.posinset = String(posInSetObj.value);
+
+ expectedGroupPos.setsize = String(aSetSize);
+ expectedGroupPos.posinset = String(aPosInSet);
+ }
+
+ if (aLevel) {
+ groupPos.level = String(levelObj.value);
+
+ expectedGroupPos.level = String(aLevel);
+ }
+
+ compareSimpleObjects(
+ groupPos,
+ expectedGroupPos,
+ false,
+ "wrong groupPos",
+ aTodo
+ );
+
+ testAttrs(aAccOrElmOrID, expectedGroupPos, true, aTodo);
+}
+
+function testGroupParentAttrs(
+ aAccOrElmOrID,
+ aChildItemCount,
+ aIsHierarchical,
+ aTodo
+) {
+ testAttrs(
+ aAccOrElmOrID,
+ { "child-item-count": String(aChildItemCount) },
+ true,
+ aTodo
+ );
+
+ if (aIsHierarchical) {
+ testAttrs(aAccOrElmOrID, { tree: "true" }, true, aTodo);
+ } else {
+ testAbsentAttrs(aAccOrElmOrID, { tree: "true" });
+ }
+}
+
+// //////////////////////////////////////////////////////////////////////////////
+// Text attributes.
+
+/**
+ * Test text attributes.
+ *
+ * @param aID [in] the ID of DOM element having text
+ * accessible
+ * @param aOffset [in] the offset inside text accessible to fetch
+ * text attributes
+ * @param aAttrs [in] the map of expected text attributes
+ * (name/value pairs) exposed at the offset
+ * @param aDefAttrs [in] the map of expected text attributes
+ * (name/value pairs) exposed on hyper text
+ * accessible
+ * @param aStartOffset [in] expected start offset where text attributes
+ * are applied
+ * @param aEndOffset [in] expected end offset where text attribute
+ * are applied
+ * @param aSkipUnexpectedAttrs [in] points the function doesn't fail if
+ * unexpected attribute is encountered
+ */
+function testTextAttrs(
+ aID,
+ aOffset,
+ aAttrs,
+ aDefAttrs,
+ aStartOffset,
+ aEndOffset,
+ aSkipUnexpectedAttrs
+) {
+ var accessible = getAccessible(aID, [nsIAccessibleText]);
+ if (!accessible) {
+ return;
+ }
+
+ var startOffset = { value: -1 };
+ var endOffset = { value: -1 };
+
+ // do not include attributes exposed on hyper text accessible
+ var attrs = getTextAttributes(
+ aID,
+ accessible,
+ false,
+ aOffset,
+ startOffset,
+ endOffset
+ );
+
+ if (!attrs) {
+ return;
+ }
+
+ var errorMsg = " for " + aID + " at offset " + aOffset;
+
+ is(startOffset.value, aStartOffset, "Wrong start offset" + errorMsg);
+ is(endOffset.value, aEndOffset, "Wrong end offset" + errorMsg);
+
+ compareAttrs(errorMsg, attrs, aAttrs, aSkipUnexpectedAttrs);
+
+ // include attributes exposed on hyper text accessible
+ var expectedAttrs = {};
+ for (let name in aAttrs) {
+ expectedAttrs[name] = aAttrs[name];
+ }
+
+ for (let name in aDefAttrs) {
+ if (!(name in expectedAttrs)) {
+ expectedAttrs[name] = aDefAttrs[name];
+ }
+ }
+
+ attrs = getTextAttributes(
+ aID,
+ accessible,
+ true,
+ aOffset,
+ startOffset,
+ endOffset
+ );
+
+ if (!attrs) {
+ return;
+ }
+
+ compareAttrs(errorMsg, attrs, expectedAttrs, aSkipUnexpectedAttrs);
+}
+
+/**
+ * Test default text attributes.
+ *
+ * @param aID [in] the ID of DOM element having text
+ * accessible
+ * @param aDefAttrs [in] the map of expected text attributes
+ * (name/value pairs)
+ * @param aSkipUnexpectedAttrs [in] points the function doesn't fail if
+ * unexpected attribute is encountered
+ */
+function testDefaultTextAttrs(aID, aDefAttrs, aSkipUnexpectedAttrs) {
+ var accessible = getAccessible(aID, [nsIAccessibleText]);
+ if (!accessible) {
+ return;
+ }
+
+ var defAttrs = null;
+ try {
+ defAttrs = accessible.defaultTextAttributes;
+ } catch (e) {}
+
+ if (!defAttrs) {
+ ok(false, "Can't get default text attributes for " + aID);
+ return;
+ }
+
+ var errorMsg = ". Getting default text attributes for " + aID;
+ compareAttrs(errorMsg, defAttrs, aDefAttrs, aSkipUnexpectedAttrs);
+}
+
+/**
+ * Test text attributes for wrong offset.
+ */
+function testTextAttrsWrongOffset(aID, aOffset) {
+ var res = false;
+ try {
+ var s = {},
+ e = {};
+ // Bug 1602031
+ // eslint-disable-next-line no-undef
+ var acc = getAccessible(ID, [nsIAccessibleText]);
+ acc.getTextAttributes(false, 157, s, e);
+ } catch (ex) {
+ res = true;
+ }
+
+ ok(
+ res,
+ "text attributes are calculated successfully at wrong offset " +
+ aOffset +
+ " for " +
+ prettyName(aID)
+ );
+}
+
+const kNormalFontWeight = function equalsToNormal(aWeight) {
+ return aWeight <= 400;
+};
+
+const kBoldFontWeight = function equalsToBold(aWeight) {
+ return aWeight > 400;
+};
+
+let isNNT = SpecialPowers.getBoolPref("widget.non-native-theme.enabled");
+// The pt font size of the input element can vary by Linux distro.
+const kInputFontSize =
+ WIN || (MAC && isNNT)
+ ? "10pt"
+ : MAC
+ ? "8pt"
+ : function () {
+ return true;
+ };
+
+const kAbsentFontFamily = function (aFontFamily) {
+ return aFontFamily != "sans-serif";
+};
+const kInputFontFamily = function (aFontFamily) {
+ return aFontFamily != "sans-serif";
+};
+
+const kMonospaceFontFamily = function (aFontFamily) {
+ return aFontFamily != "monospace";
+};
+const kSansSerifFontFamily = function (aFontFamily) {
+ return aFontFamily != "sans-serif";
+};
+const kSerifFontFamily = function (aFontFamily) {
+ return aFontFamily != "serif";
+};
+
+const kCursiveFontFamily = LINUX ? "DejaVu Serif" : "Comic Sans MS";
+
+/**
+ * Return used font from the given computed style.
+ */
+function fontFamily(aComputedStyle) {
+ var name = aComputedStyle.fontFamily;
+ switch (name) {
+ case "monospace":
+ return kMonospaceFontFamily;
+ case "sans-serif":
+ return kSansSerifFontFamily;
+ case "serif":
+ return kSerifFontFamily;
+ default:
+ return name;
+ }
+}
+
+/**
+ * Returns a computed system color for this document.
+ */
+function getSystemColor(aColor) {
+ let { r, g, b, a } = InspectorUtils.colorToRGBA(aColor, document);
+ return a == 1 ? `rgb(${r}, ${g}, ${b})` : `rgba(${r}, ${g}, ${b}, ${a})`;
+}
+
+/**
+ * Build an object of default text attributes expected for the given accessible.
+ *
+ * @param aID [in] identifier of accessible
+ * @param aFontSize [in] font size
+ * @param aFontWeight [in, optional] kBoldFontWeight or kNormalFontWeight,
+ * default value is kNormalFontWeight
+ */
+function buildDefaultTextAttrs(aID, aFontSize, aFontWeight, aFontFamily) {
+ var elm = getNode(aID);
+ var computedStyle = document.defaultView.getComputedStyle(elm);
+ var bgColor =
+ computedStyle.backgroundColor == "rgba(0, 0, 0, 0)"
+ ? getSystemColor("Canvas")
+ : computedStyle.backgroundColor;
+
+ var defAttrs = {
+ "font-style": computedStyle.fontStyle,
+ "font-size": aFontSize,
+ "background-color": bgColor,
+ "font-weight": aFontWeight ? aFontWeight : kNormalFontWeight,
+ color: computedStyle.color,
+ "font-family": aFontFamily ? aFontFamily : fontFamily(computedStyle),
+ "text-position": computedStyle.verticalAlign,
+ };
+
+ return defAttrs;
+}
+
+// //////////////////////////////////////////////////////////////////////////////
+// Private.
+
+function getTextAttributes(
+ aID,
+ aAccessible,
+ aIncludeDefAttrs,
+ aOffset,
+ aStartOffset,
+ aEndOffset
+) {
+ // This function expects the passed in accessible to already be queried for
+ // nsIAccessibleText.
+ var attrs = null;
+ try {
+ attrs = aAccessible.getTextAttributes(
+ aIncludeDefAttrs,
+ aOffset,
+ aStartOffset,
+ aEndOffset
+ );
+ } catch (e) {}
+
+ if (attrs) {
+ return attrs;
+ }
+
+ ok(false, "Can't get text attributes for " + aID);
+ return null;
+}
+
+function testAttrsInternal(
+ aAccOrElmOrID,
+ aAttrs,
+ aSkipUnexpectedAttrs,
+ aAbsentAttrs,
+ aTodo
+) {
+ var accessible = getAccessible(aAccOrElmOrID);
+ if (!accessible) {
+ return;
+ }
+
+ var attrs = null;
+ try {
+ attrs = accessible.attributes;
+ } catch (e) {}
+
+ if (!attrs) {
+ ok(false, "Can't get object attributes for " + prettyName(aAccOrElmOrID));
+ return;
+ }
+
+ var errorMsg = " for " + prettyName(aAccOrElmOrID);
+ compareAttrs(
+ errorMsg,
+ attrs,
+ aAttrs,
+ aSkipUnexpectedAttrs,
+ aAbsentAttrs,
+ aTodo
+ );
+}
+
+function compareAttrs(
+ aErrorMsg,
+ aAttrs,
+ aExpectedAttrs,
+ aSkipUnexpectedAttrs,
+ aAbsentAttrs,
+ aTodo
+) {
+ // Check if all obtained attributes are expected and have expected value.
+ let attrObject = {};
+ for (let prop of aAttrs.enumerate()) {
+ attrObject[prop.key] = prop.value;
+ }
+
+ // Create expected attributes set by using the return values from
+ // embedded functions to determine the entry's value.
+ let expectedObj = Object.fromEntries(
+ Object.entries(aExpectedAttrs).map(([k, v]) => {
+ if (v instanceof Function) {
+ // If value is a function that returns true given the received
+ // attribute value, assign the attribute value to the entry.
+ // If it is false, stringify the function for good error reporting.
+ let value = v(attrObject[k]) ? attrObject[k] : v.toString();
+ return [k, value];
+ }
+
+ return [k, v];
+ })
+ );
+
+ compareSimpleObjects(
+ attrObject,
+ expectedObj,
+ aSkipUnexpectedAttrs,
+ aErrorMsg,
+ aTodo
+ );
+
+ // Check if all unexpected attributes are absent.
+ if (aAbsentAttrs) {
+ let presentAttrs = Object.keys(attrObject).filter(
+ k => aAbsentAttrs[k] !== undefined
+ );
+ if (presentAttrs.length) {
+ (aTodo ? todo : ok)(
+ false,
+ `There were unexpected attributes: ${presentAttrs}`
+ );
+ }
+ }
+}
+
+function compareSimpleObjects(
+ aObj,
+ aExpectedObj,
+ aSkipUnexpectedAttrs,
+ aMessage,
+ aTodo
+) {
+ let keys = aSkipUnexpectedAttrs
+ ? Object.keys(aExpectedObj).sort()
+ : Object.keys(aObj).sort();
+ let o1 = JSON.stringify(aObj, keys);
+ let o2 = JSON.stringify(aExpectedObj, keys);
+
+ if (aTodo) {
+ todo_is(o1, o2, `${aMessage} - Got ${o1}, expected ${o2}`);
+ } else {
+ is(o1, o2, aMessage);
+ }
+}
diff --git a/accessible/tests/mochitest/attributes/a11y.ini b/accessible/tests/mochitest/attributes/a11y.ini
new file mode 100644
index 0000000000..ab880e4fcb
--- /dev/null
+++ b/accessible/tests/mochitest/attributes/a11y.ini
@@ -0,0 +1,14 @@
+[DEFAULT]
+support-files =
+ !/accessible/tests/mochitest/*.js
+
+[test_dpub_aria_xml-roles.html]
+[test_graphics_aria_xml-roles.html]
+[test_listbox.html]
+[test_obj.html]
+[test_obj_css.html]
+[test_obj_group.html]
+[test_obj_group.xhtml]
+[test_obj_group_tree.xhtml]
+[test_tag.html]
+[test_xml-roles.html]
diff --git a/accessible/tests/mochitest/attributes/test_dpub_aria_xml-roles.html b/accessible/tests/mochitest/attributes/test_dpub_aria_xml-roles.html
new file mode 100644
index 0000000000..a6b4dd4840
--- /dev/null
+++ b/accessible/tests/mochitest/attributes/test_dpub_aria_xml-roles.html
@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>XML roles tests</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="../role.js"></script>
+ <script type="application/javascript"
+ src="../attributes.js"></script>
+
+ <script type="application/javascript">
+
+ function doTest() {
+ // DPub ARIA roles should be exposed via the xml-roles object attribute.
+ let dpub_attrs = [
+ "doc-abstract",
+ "doc-acknowledgments",
+ "doc-afterword",
+ "doc-appendix",
+ "doc-backlink",
+ "doc-biblioentry",
+ "doc-bibliography",
+ "doc-biblioref",
+ "doc-chapter",
+ "doc-colophon",
+ "doc-conclusion",
+ "doc-cover",
+ "doc-credit",
+ "doc-credits",
+ "doc-dedication",
+ "doc-endnote",
+ "doc-endnotes",
+ "doc-epigraph",
+ "doc-epilogue",
+ "doc-errata",
+ "doc-example",
+ "doc-footnote",
+ "doc-foreword",
+ "doc-glossary",
+ "doc-glossref",
+ "doc-index",
+ "doc-introduction",
+ "doc-noteref",
+ "doc-notice",
+ "doc-pagebreak",
+ "doc-pagelist",
+ "doc-part",
+ "doc-preface",
+ "doc-prologue",
+ "doc-pullquote",
+ "doc-qna",
+ "doc-subtitle",
+ "doc-tip",
+ "doc-toc",
+ ];
+ for (let attr of dpub_attrs) {
+ testAttrs(attr, {"xml-roles": attr}, true);
+ }
+ SimpleTest.finish();
+ }
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(doTest);
+ </script>
+</head>
+<body>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=1343537"
+ title="implement ARIA DPUB extension">
+ Bug 1343537
+ </a>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test"></pre>
+ <div id="doc-abstract" role="doc-abstract">abstract</div>
+ <div id="doc-acknowledgments" role="doc-acknowledgments">acknowledgments</div>
+ <div id="doc-afterword" role="doc-afterword">afterword</div>
+ <div id="doc-appendix" role="doc-appendix">appendix</div>
+ <div id="doc-backlink" role="doc-backlink">backlink</div>
+ <div id="doc-biblioentry" role="doc-biblioentry">biblioentry</div>
+ <div id="doc-bibliography" role="doc-bibliography">bibliography</div>
+ <div id="doc-biblioref" role="doc-biblioref">biblioref</div>
+ <div id="doc-chapter" role="doc-chapter">chapter</div>
+ <div id="doc-colophon" role="doc-colophon">colophon</div>
+ <div id="doc-conclusion" role="doc-conclusion">conclusion</div>
+ <div id="doc-cover" role="doc-cover">cover</div>
+ <div id="doc-credit" role="doc-credit">credit</div>
+ <div id="doc-credits" role="doc-credits">credits</div>
+ <div id="doc-dedication" role="doc-dedication">dedication</div>
+ <div id="doc-endnote" role="doc-endnote">endnote</div>
+ <div id="doc-endnotes" role="doc-endnotes">endnotes</div>
+ <div id="doc-epigraph" role="doc-epigraph">epigraph</div>
+ <div id="doc-epilogue" role="doc-epilogue">epilogue</div>
+ <div id="doc-errata" role="doc-errata">errata</div>
+ <div id="doc-example" role="doc-example">example</div>
+ <div id="doc-footnote" role="doc-footnote">footnote</div>
+ <div id="doc-foreword" role="doc-foreword">foreword</div>
+ <div id="doc-glossary" role="doc-glossary">glossary</div>
+ <div id="doc-glossref" role="doc-glossref">glossref</div>
+ <div id="doc-index" role="doc-index">index</div>
+ <div id="doc-introduction" role="doc-introduction">introduction</div>
+ <div id="doc-noteref" role="doc-noteref">noteref</div>
+ <div id="doc-notice" role="doc-notice">notice</div>
+ <div id="doc-pagebreak" role="doc-pagebreak">pagebreak</div>
+ <div id="doc-pagelist" role="doc-pagelist">pagelist</div>
+ <div id="doc-part" role="doc-part">part</div>
+ <div id="doc-preface" role="doc-preface">preface</div>
+ <div id="doc-prologue" role="doc-prologue">prologue</div>
+ <div id="doc-pullquote" role="doc-pullquote">pullquote</div>
+ <div id="doc-qna" role="doc-qna">qna</div>
+ <div id="doc-subtitle" role="doc-subtitle">subtitle</div>
+ <div id="doc-tip" role="doc-tip">tip</div>
+ <div id="doc-toc" role="doc-toc">toc</div>
+</body>
+</html>
diff --git a/accessible/tests/mochitest/attributes/test_graphics_aria_xml-roles.html b/accessible/tests/mochitest/attributes/test_graphics_aria_xml-roles.html
new file mode 100644
index 0000000000..45d5e2fa0b
--- /dev/null
+++ b/accessible/tests/mochitest/attributes/test_graphics_aria_xml-roles.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>XML roles tests</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="../role.js"></script>
+ <script type="application/javascript"
+ src="../attributes.js"></script>
+
+ <script type="application/javascript">
+
+ function doTest() {
+ // Graphics ARIA roles should be exposed via the xml-roles object attribute.
+ let graphics_attrs = [
+ "graphics-document",
+ "graphics-object",
+ "graphics-symbol",
+ ];
+ for (let attr of graphics_attrs) {
+ testAttrs(attr, {"xml-roles": attr}, true);
+ }
+ SimpleTest.finish();
+ }
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(doTest);
+ </script>
+</head>
+<body>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=1432513"
+ title="implement ARIA Graphics roles">
+ Bug 1432513
+ </a>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test"></pre>
+ <div id="graphics-document" role="graphics-document">document</div>
+ <div id="graphics-object" role="graphics-object">object</div>
+ <div id="graphics-symbol" role="graphics-symbol">symbol</div>
+</body>
+</html>
diff --git a/accessible/tests/mochitest/attributes/test_listbox.html b/accessible/tests/mochitest/attributes/test_listbox.html
new file mode 100644
index 0000000000..5489e74b74
--- /dev/null
+++ b/accessible/tests/mochitest/attributes/test_listbox.html
@@ -0,0 +1,82 @@
+<html>
+
+<head>
+ <title>Listbox group attribute tests</title>
+ <meta charset="utf-8" />
+ <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="../attributes.js"></script>
+ <script type="application/javascript"
+ src="../promisified-events.js"></script>
+
+ <script type="application/javascript">
+ async function doTest() {
+ // First test the whole lot.
+ testGroupAttrs("a", 1, 6);
+ testGroupAttrs("b", 2, 6);
+ testGroupAttrs("c", 3, 6);
+ testGroupAttrs("d", 4, 6);
+ testGroupAttrs("e", 5, 6);
+ testGroupAttrs("f", 6, 6);
+ // Remove c, reducing the set to 5.
+ let listbox = getAccessible("listbox");
+ let updated = waitForEvent(EVENT_REORDER, listbox);
+ c.remove();
+ await updated;
+ testGroupAttrs("a", 1, 5);
+ testGroupAttrs("b", 2, 5);
+ testGroupAttrs("d", 3, 5);
+ testGroupAttrs("e", 4, 5);
+ testGroupAttrs("f", 5, 5);
+ // Now, remove the first element.
+ updated = waitForEvent(EVENT_REORDER, listbox);
+ a.remove();
+ await updated;
+ testGroupAttrs("b", 1, 4);
+ testGroupAttrs("d", 2, 4);
+ testGroupAttrs("e", 3, 4);
+ testGroupAttrs("f", 4, 4);
+ // Remove the last item.
+ updated = waitForEvent(EVENT_REORDER, listbox);
+ f.remove();
+ await updated;
+ testGroupAttrs("b", 1, 3);
+ testGroupAttrs("d", 2, 3);
+ testGroupAttrs("e", 3, 3);
+ // Finally, remove the middle item.
+ updated = waitForEvent(EVENT_REORDER, listbox);
+ d.remove();
+ await updated;
+ testGroupAttrs("b", 1, 2);
+ testGroupAttrs("e", 2, 2);
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(doTest);
+ </script>
+</head>
+<body>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+
+ <!-- Group information updated after removal of list items, bug 1515186 -->
+ <div id="listbox" role="listbox">
+ <div id="a" role="option">Option a</div>
+ <div id="b" role="option">Option b</div>
+ <div id="c" role="option">Option c</div>
+ <div id="d" role="option">Option d</div>
+ <div id="e" role="option">Option e</div>
+ <div id="f" role="option">Option f</div>
+ </div>
+
+</body>
+</html>
diff --git a/accessible/tests/mochitest/attributes/test_obj.html b/accessible/tests/mochitest/attributes/test_obj.html
new file mode 100644
index 0000000000..fedf6a1b7b
--- /dev/null
+++ b/accessible/tests/mochitest/attributes/test_obj.html
@@ -0,0 +1,292 @@
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=475006
+https://bugzilla.mozilla.org/show_bug.cgi?id=391829
+https://bugzilla.mozilla.org/show_bug.cgi?id=581952
+https://bugzilla.mozilla.org/show_bug.cgi?id=558036
+-->
+<head>
+ <title>Group attributes tests</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="../attributes.js"></script>
+
+ <script type="application/javascript">
+ function doTest() {
+ // aria
+ testAttrs("atomic", {"atomic": "true", "container-atomic": "true"}, true);
+ testAttrs(getNode("atomic").firstChild, {"container-atomic": "true"}, true);
+ testAbsentAttrs("atomic_false", {"atomic": "false", "container-atomic": "false"});
+ testAbsentAttrs(getNode("atomic_false").firstChild, {"container-atomic": "false"});
+
+ testAttrs("autocomplete", {"autocomplete": "true"}, true);
+ testAttrs("checkbox", {"checkable": "true"}, true);
+ testAttrs("checkedCheckbox", {"checkable": "true"}, true);
+ testAbsentAttrs("checkedMenuitem", {"checkable": "true"});
+ testAttrs("checkedMenuitemCheckbox", {"checkable": "true"}, true);
+ testAttrs("checkedMenuitemRadio", {"checkable": "true"}, true);
+ testAttrs("checkedOption", {"checkable": "true"}, true);
+ testAttrs("checkedRadio", {"checkable": "true"}, true);
+ testAttrs("checkedTreeitem", {"checkable": "true"}, true);
+ testAttrs("dropeffect", {"dropeffect": "copy"}, true);
+ testAttrs("grabbed", {"grabbed": "true"}, true);
+ testAttrs("haspopupTrue", { "haspopup": "true" }, true);
+ testAbsentAttrs("haspopupFalse", { "haspopup": "false" });
+ testAbsentAttrs("haspopupEmpty", { "haspopup": "" });
+ testAttrs("haspopupDialog", { "haspopup": "dialog" }, true);
+ testAttrs("haspopupListbox", { "haspopup": "listbox" }, true);
+ testAttrs("haspopupMenu", { "haspopup": "menu" }, true);
+ testAttrs("haspopupTree", { "haspopup": "tree" }, true);
+ testAbsentAttrs("modal", {"modal": "true"});
+ testAttrs("sortAscending", {"sort": "ascending"}, true);
+ testAttrs("sortDescending", {"sort": "descending"}, true);
+ testAttrs("sortNone", {"sort": "none"}, true);
+ testAttrs("sortOther", {"sort": "other"}, true);
+ testAttrs("roledescr", {"roledescription": "spreadshit"}, true);
+ testAttrs("currentPage", {"current": "page"}, true);
+ testAttrs("currentStep", {"current": "step"}, true);
+ testAttrs("currentLocation", {"current": "location"}, true);
+ testAttrs("currentDate", {"current": "date"}, true);
+ testAttrs("currentTime", {"current": "time"}, true);
+ testAttrs("currentTrue", {"current": "true"}, true);
+ testAttrs("currentOther", {"current": "true"}, true);
+ testAbsentAttrs("currentFalse", {"current": "true"});
+ testAttrs("currentSpan", {"current": "page"}, true);
+
+ // live object attribute
+
+ // HTML
+ testAttrs("output", {"live": "polite"}, true);
+
+ // ARIA
+ testAttrs("live", {"live": "polite"}, true);
+ testAttrs("live2", {"live": "polite"}, true);
+ testAbsentAttrs("live3", {"live": ""});
+ if (MAC) {
+ testAttrs("alert", {"live": "assertive"}, true);
+ } else {
+ testAbsentAttrs("alert", {"live": "assertive"});
+ }
+ testAttrs("log", {"live": "polite"}, true);
+ testAttrs("logAssertive", {"live": "assertive"}, true);
+ testAttrs("marquee", {"live": "off"}, true);
+ testAttrs("status", {"live": "polite"}, true);
+ testAttrs("timer", {"live": "off"}, true);
+ testAbsentAttrs("tablist", {"live": "polite"});
+
+ // container-live object attribute
+ testAttrs("liveChild", {"container-live": "polite"}, true);
+ testAttrs("live2Child", {"container-live": "polite"}, true);
+ if (MAC) {
+ testAttrs("alertChild", {"container-live": "assertive"}, true);
+ } else {
+ testAbsentAttrs("alertChild", {"container-live": "assertive"});
+ }
+ testAttrs("logChild", {"container-live": "polite"}, true);
+ testAttrs("logAssertiveChild", {"container-live": "assertive"}, true);
+ testAttrs("marqueeChild", {"container-live": "off"}, true);
+ testAttrs("statusChild", {"container-live": "polite"}, true);
+ testAttrs("timerChild", {"container-live": "off"}, true);
+ testAbsentAttrs("tablistChild", {"container-live": "polite"});
+ testAttrs("containerLiveOutput", {"container-live": "polite"}, true);
+ testAttrs("containerLiveOutput1", {"container-live": "polite"}, true);
+ testAttrs("containerLiveOutput2", {"container-live": "polite"}, true);
+
+ // container-live-role object attribute
+ testAttrs("log", {"container-live-role": "log"}, true);
+ testAttrs("logAssertive", {"container-live-role": "log"}, true);
+ testAttrs("marquee", {"container-live-role": "marquee"}, true);
+ testAttrs("status", {"container-live-role": "status"}, true);
+ testAttrs("timer", {"container-live-role": "timer"}, true);
+ testAttrs("logChild", {"container-live-role": "log"}, true);
+ testAttrs("logAssertive", {"container-live-role": "log"}, true);
+ testAttrs("logAssertiveChild", {"container-live-role": "log"}, true);
+ testAttrs("marqueeChild", {"container-live-role": "marquee"}, true);
+ testAttrs("statusChild", {"container-live-role": "status"}, true);
+ testAttrs("timerChild", {"container-live-role": "timer"}, true);
+ testAbsentAttrs("tablistChild", {"container-live-role": "tablist"});
+
+ // absent aria-label and aria-labelledby object attribute
+ testAbsentAttrs("label", {"label": "foo"});
+ testAbsentAttrs("labelledby", {"labelledby": "label"});
+
+ // container that has no default live attribute
+ testAttrs("liveGroup", {"live": "polite"}, true);
+ testAttrs("liveGroupChild", {"container-live": "polite"}, true);
+ testAttrs("liveGroup", {"container-live-role": "group"}, true);
+ testAttrs("liveGroupChild", {"container-live-role": "group"}, true);
+
+ // text input type
+ testAbsentAttrs("button", { "text-input-type": "button"});
+ testAbsentAttrs("checkbox", { "text-input-type": "checkbox"});
+ testAbsentAttrs("radio", { "text-input-type": "radio"});
+ testAttrs("email", {"text-input-type": "email"}, true);
+ testAttrs("search", {"text-input-type": "search"}, true);
+ testAttrs("tel", {"text-input-type": "tel"}, true);
+ testAttrs("url", {"text-input-type": "url"}, true);
+ testAttrs("number", {"text-input-type": "number"}, true);
+
+ // ARIA
+ testAttrs("searchbox", {"text-input-type": "search"}, true);
+
+ // html
+ testAttrs("radio", {"checkable": "true"}, true);
+ testAttrs("checkbox", {"checkable": "true"}, true);
+ testAttrs("draggable", {"draggable": "true"}, true);
+ testAttrs("th1", { "abbr": "SS#" }, true);
+ testAttrs("th2", { "abbr": "SS#" }, true);
+ testAttrs("th2", { "axis": "social" }, true);
+
+ // don't barf on an empty abbr element.
+ testAbsentAttrs("th3", { "abbr": "" });
+
+ // application accessible
+ if (WIN) {
+ var gfxInfo = Cc["@mozilla.org/gfx/info;1"].
+ getService(Ci.nsIGfxInfo);
+ var attrs = {
+ "D2D": (gfxInfo.D2DEnabled ? "true" : "false"),
+ };
+ testAttrs(getApplicationAccessible(), attrs, false);
+ }
+
+ // no object attributes
+ testAbsentAttrs(getAccessible("listitem").firstChild, { "tag": "" });
+
+ // experimental aria
+ testAttrs("experimental", {"blah": "true"}, true);
+
+ // HTML5 aside element xml-roles
+ testAttrs("aside0", {"xml-roles": "note"}, true);
+ testAttrs("aside1", {"xml-roles": "group"}, true);
+ testAttrs("aside2", {"xml-roles": "complementary"}, true);
+
+ // non-standard data-at-shortcutkeys attribute:
+ testAttrs("shortcuts", {'data-at-shortcutkeys': '{"n":"New message","r":"Reply to message"}'}, true);
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(doTest);
+ </script>
+</head>
+<body>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+
+ <!-- container live -->
+ <output id="containerLiveOutput"><div id="containerLiveOutput1"><div id="containerLiveOutput2">Test</div></div></output>
+
+ <!-- aria -->
+ <div id="atomic" aria-atomic="true">live region</div>
+ <div id="atomic_false" aria-atomic="false">live region</div>
+ <div id="autocomplete" role="textbox" aria-autocomplete="true"></div>
+ <div id="checkbox" role="checkbox"></div>
+ <div id="checkedCheckbox" role="checkbox" aria-checked="true"></div>
+ <div id="checkedMenuitem" role="menuitem" aria-checked="true"></div>
+ <div id="checkedMenuitemCheckbox" role="menuitemcheckbox" aria-checked="true"></div>
+ <div id="checkedMenuitemRadio" role="menuitemradio" aria-checked="true"></div>
+ <div id="checkedOption" role="option" aria-checked="true"></div>
+ <div id="checkedRadio" role="radio" aria-checked="true"></div>
+ <div id="checkedTreeitem" role="treeitem" aria-checked="true"></div>
+ <div id="dropeffect" aria-dropeffect="copy"></div>
+ <div id="grabbed" aria-grabbed="true"></div>
+ <div id="haspopupTrue" aria-haspopup="true"></div>
+ <div id="haspopupFalse" aria-haspopup="false"></div>
+ <div id="haspopupEmpty" aria-haspopup=""></div>
+ <div id="haspopupDialog" aria-haspopup="dialog"></div>
+ <div id="haspopupListbox" aria-haspopup="listbox"></div>
+ <div id="haspopupMenu" aria-haspopup="menu"></div>
+ <div id="haspopupTree" aria-haspopup="tree"></div>
+ <div id="modal" aria-modal="true"></div>
+ <div id="sortAscending" role="columnheader" aria-sort="ascending"></div>
+ <div id="sortDescending" role="columnheader" aria-sort="descending"></div>
+ <div id="sortNone" role="columnheader" aria-sort="none"></div>
+ <div id="sortOther" role="columnheader" aria-sort="other"></div>
+ <div id="roledescr" aria-roledescription="spreadshit"></div>
+ <div id="currentPage" aria-current="page"></div>
+ <div id="currentStep" aria-current="step"></div>
+ <div id="currentLocation" aria-current="location"></div>
+ <div id="currentDate" aria-current="date"></div>
+ <div id="currentTime" aria-current="time"></div>
+ <div id="currentTrue" aria-current="true"></div>
+ <div id="currentOther" aria-current="other"></div>
+ <div id="currentFalse" aria-current="false"></div>
+
+ <!-- aria-current on a span which must create an accessible -->
+ <ol>
+ <li><a href="...">Page 1</a></li>
+ <li><a href="...">Page 2</a></li>
+ <li><span id="currentSpan" aria-current="page">This page</span></li>
+ </ol>
+
+ <!-- html -->
+ <output id="output"></output>
+
+ <!-- back to aria -->
+ <div id="live" aria-live="polite">excuse <div id="liveChild">me</div></div>
+ <div id="live2" role="marquee" aria-live="polite">excuse <div id="live2Child">me</div></div>
+ <div id="live3" role="region">excuse</div>
+ <div id="alert" role="alert">excuse <div id="alertChild">me</div></div>
+ <div id="log" role="log">excuse <div id="logChild">me</div></div>
+ <div id="logAssertive" role="log" aria-live="assertive">excuse <div id="logAssertiveChild">me</div></div>
+ <div id="marquee" role="marquee">excuse <div id="marqueeChild">me</div></div>
+ <div id="status" role="status">excuse <div id="statusChild">me</div></div>
+ <div id="tablist" role="tablist">tablist <div id="tablistChild">tab</div></div>
+ <div id="timer" role="timer">excuse <div id="timerChild">me</div></div>
+
+ <!-- aria-label[ledby] should not be an object attribute -->
+ <div id="label" role="checkbox" aria-label="foo"></div>
+ <div id="labelledby" role="checkbox" aria-labelledby="label"></div>
+
+ <!-- unusual live case -->
+ <div id="liveGroup" role="group" aria-live="polite">
+ excuse <div id="liveGroupChild">me</div>
+ </div>
+
+ <!-- text input type -->
+ <input id="button" type="button"/>
+ <input id="email" type="email"/>
+ <input id="search" type="search"/>
+ <input id="tel" type="tel"/>
+ <input id="url" type="url"/>
+ <input id="number" type="number"/>
+ <div id="searchbox" role="searchbox"></div>
+
+ <!-- html -->
+ <input id="radio" type="radio"/>
+ <input id="checkbox" type="checkbox"/>
+ <div id="draggable" draggable="true">Draggable div</div>
+ <table>
+ <tr>
+ <th id="th1"><abbr title="Social Security Number">SS#</abbr></th>
+ <th id="th2" abbr="SS#" axis="social">Social Security Number</th>
+ <th id="th3"><abbr></abbr></th>
+ </tr>
+ </table>
+
+ <ul>
+ <li id="listitem">item
+ </ul>
+
+ <!-- experimental aria -->
+ <div id="experimental" aria-blah="true">Fake beer</div>
+
+ <!-- HTML5 aside elements -->
+ <aside id="aside0" role="note">aside 0</aside>
+ <aside id="aside1" role="group">aside 1</aside>
+ <aside id="aside2">aside 2</aside>
+
+ <!-- Shortcuts for web applications -->
+ <div id="shortcuts" data-at-shortcutkeys='{"n":"New message","r":"Reply to message"}'></div>
+</body>
+</html>
diff --git a/accessible/tests/mochitest/attributes/test_obj_css.html b/accessible/tests/mochitest/attributes/test_obj_css.html
new file mode 100644
index 0000000000..6c702ba5a6
--- /dev/null
+++ b/accessible/tests/mochitest/attributes/test_obj_css.html
@@ -0,0 +1,225 @@
+<html>
+<head>
+ <title>CSS-like attributes tests</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="../attributes.js"></script>
+ <script type="application/javascript"
+ src="../events.js"></script>
+
+ <script type="application/javascript">
+ var gQueue = null;
+
+ function removeElm(aID) {
+ this.node = getNode(aID);
+ this.accessible = getAccessible(aID);
+
+ this.eventSeq = [
+ new invokerChecker(EVENT_HIDE, this.accessible),
+ ];
+
+ this.invoke = function removeElm_invoke() {
+ this.node.remove();
+ };
+
+ this.check = function removeElm_check() {
+ testAbsentCSSAttrs(this.accessible);
+ };
+
+ this.getID = function removeElm_getID() {
+ return "test CSS-based attributes on removed accessible";
+ };
+ }
+
+ function doTest() {
+ // CSS display
+ testCSSAttrs("display_block");
+ testCSSAttrs("display_inline");
+ testCSSAttrs("display_inline-block");
+ testCSSAttrs("display_list-item");
+ testCSSAttrs("display_table");
+ testCSSAttrs("display_inline-table");
+ testCSSAttrs("display_table-row-group");
+ testCSSAttrs("display_table-column");
+ testCSSAttrs("display_table-column-group");
+ testCSSAttrs("display_table-header-group");
+ testCSSAttrs("display_table-footer-group");
+ testCSSAttrs("display_table-row");
+ testCSSAttrs("display_table-cell");
+ testCSSAttrs("display_table-caption");
+
+ // CSS text-align
+ testCSSAttrs("text-align_left");
+ testCSSAttrs("text-align_right");
+ testCSSAttrs("text-align_center");
+ testCSSAttrs("text-align_justify");
+ testCSSAttrs("text-align_inherit");
+
+ // CSS text-indent
+ testCSSAttrs("text-indent_em");
+ testCSSAttrs("text-indent_ex");
+ testCSSAttrs("text-indent_in");
+ testCSSAttrs("text-indent_cm");
+ testCSSAttrs("text-indent_mm");
+ testCSSAttrs("text-indent_pt");
+ testCSSAttrs("text-indent_pc");
+ testCSSAttrs("text-indent_px");
+ testCSSAttrs("text-indent_percent");
+ testCSSAttrs("text-indent_inherit");
+
+ // CSS margin
+ testCSSAttrs("margin_em");
+ testCSSAttrs("margin_ex");
+ testCSSAttrs("margin_in");
+ testCSSAttrs("margin_cm");
+ testCSSAttrs("margin_mm");
+ testCSSAttrs("margin_pt");
+ testCSSAttrs("margin_pc");
+ testCSSAttrs("margin_px");
+ testCSSAttrs("margin_percent");
+ testCSSAttrs("margin_auto");
+ testCSSAttrs("margin_inherit");
+
+ testCSSAttrs("margin-left");
+ testCSSAttrs("margin-right");
+ testCSSAttrs("margin-top");
+ testCSSAttrs("margin-bottom");
+
+ // Elements
+ testCSSAttrs("span");
+ testCSSAttrs("div");
+ testCSSAttrs("p");
+ testCSSAttrs("input");
+ testCSSAttrs("table");
+ testCSSAttrs("tr");
+ testCSSAttrs("td");
+
+ // no CSS-based object attributes
+ testAbsentCSSAttrs(getAccessible("listitem").firstChild);
+
+ gQueue = new eventQueue();
+ gQueue.push(new removeElm("div"));
+ gQueue.invoke(); // SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(doTest);
+ </script>
+</head>
+<body>
+
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=439566"
+ title="Include the css display property as an IAccessible2 object attribute">
+ Mozilla Bug 439566
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=460932"
+ title="text-indent and text-align should really be object attribute">
+ Mozilla Bug 460932
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=689540"
+ title="Expose IA2 margin- object attributes">
+ Mozilla Bug 689540
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=714579"
+ title="Don't use GetComputedStyle for object attribute calculation">
+ Mozilla Bug 714579
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=729831"
+ title="Don't expose CSS-based object attributes on not in tree accessible and accessible having no DOM element">
+ Mozilla Bug 729831
+ </a>
+
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+
+ <div id="display_block" role="img"
+ style="display: block;">display: block</div>
+ <div id="display_inline" role="img"
+ style="display: inline;">display: inline</div>
+ <div id="display_inline-block" role="img"
+ style="display: inline-block;">display: inline-block</div>
+ <div id="display_list-item" role="img"
+ style="display: list-item;">display: list-item</div>
+ <div id="display_table" role="img"
+ style="display: table;">display: table</div>
+ <div id="display_inline-table" role="img"
+ style="display: inline-table;">display: inline-table</div>
+ <div id="display_table-row-group" role="img"
+ style="display: table-row-group;">display: table-row-group</div>
+ <div id="display_table-column" role="img"
+ style="display: table-column;">display: table-column</div>
+ <div id="display_table-column-group" role="img"
+ style="display: table-column-group;">display: table-column-group</div>
+ <div id="display_table-header-group" role="img"
+ style="display: table-header-group;">display: table-header-group</div>
+ <div id="display_table-footer-group" role="img"
+ style="display: table-footer-group;">display: table-footer-group</div>
+ <div id="display_table-row" role="img"
+ style="display: table-row;">display: table-row</div>
+ <div id="display_table-cell" role="img"
+ style="display: table-cell;">display: table-cell</div>
+ <div id="display_table-caption" role="img"
+ style="display: table-caption;">display: table-caption</div>
+
+ <p id="text-align_left" style="text-align: left;">text-align: left</p>
+ <p id="text-align_right" style="text-align: right;">text-align: right</p>
+ <p id="text-align_center" style="text-align: center;">text-align: center</p>
+ <p id="text-align_justify" style="text-align: justify;">text-align: justify</p>
+ <p id="text-align_inherit" style="text-align: inherit;">text-align: inherit</p>
+
+ <p id="text-indent_em" style="text-indent: 0.5em;">text-indent: 0.5em</p>
+ <p id="text-indent_ex" style="text-indent: 1ex;">text-indent: 1ex</p>
+ <p id="text-indent_in" style="text-indent: 0.5in;">text-indent: 0.5in</p>
+ <p id="text-indent_cm" style="text-indent: 2cm;">text-indent: 2cm</p>
+ <p id="text-indent_mm" style="text-indent: 10mm;">text-indent: 10mm</p>
+ <p id="text-indent_pt" style="text-indent: 30pt;">text-indent: 30pt</p>
+ <p id="text-indent_pc" style="text-indent: 2pc;">text-indent: 2pc</p>
+ <p id="text-indent_px" style="text-indent: 5px;">text-indent: 5px</p>
+ <p id="text-indent_percent" style="text-indent: 10%;">text-indent: 10%</p>
+ <p id="text-indent_inherit" style="text-indent: inherit;">text-indent: inherit</p>
+
+ <p id="margin_em" style="margin: 0.5em;">margin: 0.5em</p>
+ <p id="margin_ex" style="margin: 1ex;">margin: 1ex</p>
+ <p id="margin_in" style="margin: 0.5in;">margin: 0.5in</p>
+ <p id="margin_cm" style="margin: 2cm;">margin: 2cm</p>
+ <p id="margin_mm" style="margin: 10mm;">margin: 10mm</p>
+ <p id="margin_pt" style="margin: 30pt;">margin: 30pt</p>
+ <p id="margin_pc" style="margin: 2pc;">margin: 2pc</p>
+ <p id="margin_px" style="margin: 5px;">margin: 5px</p>
+ <p id="margin_percent" style="margin: 10%;">margin: 10%</p>
+ <p id="margin_auto" style="margin: auto;">margin: auto</p>
+ <p id="margin_inherit" style="margin: inherit;">margin: inherit</p>
+
+ <p id="margin-left" style="margin-left: 11px;">margin-left: 11px</p>
+ <p id="margin-right" style="margin-right: 21px;">margin-right</p>
+ <p id="margin-top" style="margin-top: 31px;">margin-top: 31px</p>
+ <p id="margin-bottom" style="margin-bottom: 41px;">margin-bottom: 41px</p>
+
+ <span id="span" role="group">It's span</span>
+ <div id="div">It's div</div>
+ <p id="p">It's paragraph"</p>
+ <input id="input"/>
+ <table id="table" style="margin: 2px; text-align: center; text-indent: 10%;">
+ <tr id="tr" role="group">
+ <td id="td">td</td>
+ </tr>
+ </table>
+
+ <ul>
+ <li id="listitem">item
+ </ul>
+</body>
+</html>
diff --git a/accessible/tests/mochitest/attributes/test_obj_group.html b/accessible/tests/mochitest/attributes/test_obj_group.html
new file mode 100644
index 0000000000..f245d485c7
--- /dev/null
+++ b/accessible/tests/mochitest/attributes/test_obj_group.html
@@ -0,0 +1,564 @@
+<html>
+
+<head>
+ <title>Group attributes tests</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="../attributes.js"></script>
+ <script type="application/javascript"
+ src="../events.js"></script>
+
+ <script type="application/javascript">
+ function doTest() {
+ // ////////////////////////////////////////////////////////////////////////
+ // HTML select with no size attribute.
+ testGroupAttrs("opt1-nosize", 1, 4);
+ testGroupAttrs("opt2-nosize", 2, 4);
+ testGroupAttrs("opt3-nosize", 3, 4);
+ testGroupAttrs("opt4-nosize", 4, 4);
+
+ // Container should have item count and not hierarchical
+ testGroupParentAttrs(getAccessible("opt1-nosize").parent, 4, false);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // HTML select
+ testGroupAttrs("opt1", 1, 2);
+ testGroupAttrs("opt2", 2, 2);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // HTML select with optgroup
+ testGroupAttrs("select2_opt3", 1, 2, 1);
+ testGroupAttrs("select2_opt4", 2, 2, 1);
+ testGroupAttrs("select2_opt1", 1, 2, 2);
+ testGroupAttrs("select2_opt2", 2, 2, 2);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // HTML input@type="radio" within form
+ testGroupAttrs("radio1", 1, 2);
+ testGroupAttrs("radio2", 2, 2);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // HTML input@type="radio" within document
+ testGroupAttrs("radio3", 1, 2);
+ testGroupAttrs("radio4", 2, 2);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // Hidden HTML input@type="radio"
+ testGroupAttrs("radio5", 1, 1);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // HTML ul/ol
+ testGroupAttrs("li1", 1, 3);
+ testGroupAttrs("li2", 2, 3);
+ testGroupAttrs("li3", 3, 3);
+
+ // ul should have item count and not hierarchical
+ testGroupParentAttrs("ul", 3, false);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // HTML ul/ol (nested lists)
+
+ testGroupAttrs("li4", 1, 3, 1);
+ testGroupAttrs("li5", 2, 3, 1);
+ testGroupAttrs("li6", 3, 3, 1);
+ // ol with nested list should have 1st level item count and be hierarchical
+ testGroupParentAttrs("ol", 3, true);
+
+ testGroupAttrs("n_li4", 1, 3, 2);
+ testGroupAttrs("n_li5", 2, 3, 2);
+ testGroupAttrs("n_li6", 3, 3, 2);
+ // nested ol should have item count and be hierarchical
+ testGroupParentAttrs("ol_nested", 3, true);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // ARIA list
+ testGroupAttrs("li7", 1, 3);
+ testGroupAttrs("li8", 2, 3);
+ testGroupAttrs("li9", 3, 3);
+ // simple flat aria list
+ testGroupParentAttrs("aria-list_1", 3, false);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // ARIA list (nested lists: list -> listitem -> list -> listitem)
+ testGroupAttrs("li10", 1, 3, 1);
+ testGroupAttrs("li11", 2, 3, 1);
+ testGroupAttrs("li12", 3, 3, 1);
+ // aria list with nested list
+ testGroupParentAttrs("aria-list_2", 3, true);
+
+ testGroupAttrs("n_li10", 1, 3, 2);
+ testGroupAttrs("n_li11", 2, 3, 2);
+ testGroupAttrs("n_li12", 3, 3, 2);
+ // nested aria list.
+ testGroupParentAttrs("aria-list_2_1", 3, true);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // ARIA list (nested lists: list -> listitem -> group -> listitem)
+ testGroupAttrs("lgt_li1", 1, 2, 1);
+ testGroupAttrs("lgt_li1_nli1", 1, 2, 2);
+ testGroupAttrs("lgt_li1_nli2", 2, 2, 2);
+ testGroupAttrs("lgt_li2", 2, 2, 1);
+ testGroupAttrs("lgt_li2_nli1", 1, 2, 2);
+ testGroupAttrs("lgt_li2_nli2", 2, 2, 2);
+ // aria list with nested list
+ testGroupParentAttrs("aria-list_3", 2, true);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // ARIA menu (menuitem, separator, menuitemradio and menuitemcheckbox)
+ testGroupAttrs("menu_item1", 1, 2);
+ testGroupAttrs("menu_item2", 2, 2);
+ testGroupAttrs("menu_item1.1", 1, 2);
+ testGroupAttrs("menu_item1.2", 2, 2);
+ testGroupAttrs("menu_item1.3", 1, 3);
+ testGroupAttrs("menu_item1.4", 2, 3);
+ testGroupAttrs("menu_item1.5", 3, 3);
+ // menu bar item count
+ testGroupParentAttrs("menubar", 2, false);
+ // Bug 1492529. Menu should have total number of items 5 from both sets,
+ // but only has the first 2 item set.
+ todoAttr("menu", "child-item-count", "5");
+
+ // ////////////////////////////////////////////////////////////////////////
+ // ARIA tab
+ testGroupAttrs("tab_1", 1, 3);
+ testGroupAttrs("tab_2", 2, 3);
+ testGroupAttrs("tab_3", 3, 3);
+ // tab list tab count
+ testGroupParentAttrs("tablist_1", 3, false);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // ARIA radio
+ testGroupAttrs("r1", 1, 3);
+ testGroupAttrs("r2", 2, 3);
+ testGroupAttrs("r3", 3, 3);
+ // explicit aria radio group
+ testGroupParentAttrs("rg1", 3, false);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // ARIA tree
+ testGroupAttrs("ti1", 1, 3, 1);
+ testGroupAttrs("ti2", 1, 2, 2);
+ testGroupAttrs("ti3", 2, 2, 2);
+ testGroupAttrs("ti4", 2, 3, 1);
+ testGroupAttrs("ti5", 1, 3, 2);
+ testGroupAttrs("ti6", 2, 3, 2);
+ testGroupAttrs("ti7", 3, 3, 2);
+ testGroupAttrs("ti8", 3, 3, 1);
+ testGroupParentAttrs("tree_1", 3, true);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // ARIA tree (tree -> treeitem -> group -> treeitem)
+ testGroupAttrs("tree2_ti1", 1, 2, 1);
+ testGroupAttrs("tree2_ti1a", 1, 2, 2);
+ testGroupAttrs("tree2_ti1b", 2, 2, 2);
+ testGroupAttrs("tree2_ti2", 2, 2, 1);
+ testGroupAttrs("tree2_ti2a", 1, 2, 2);
+ testGroupAttrs("tree2_ti2b", 2, 2, 2);
+ testGroupParentAttrs("tree_2", 2, true);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // ARIA tree (tree -> treeitem, group -> treeitem)
+ testGroupAttrs("tree3_ti1", 1, 2, 1);
+ testGroupAttrs("tree3_ti1a", 1, 2, 2);
+ testGroupAttrs("tree3_ti1b", 2, 2, 2);
+ testGroupAttrs("tree3_ti2", 2, 2, 1);
+ testGroupAttrs("tree3_ti2a", 1, 2, 2);
+ testGroupAttrs("tree3_ti2b", 2, 2, 2);
+ testGroupParentAttrs("tree_3", 2, true);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // ARIA grid
+ testGroupAttrs("grid_row1", 1, 2);
+ testAbsentAttrs("grid_cell1", {"posinset": "", "setsize": ""});
+ testAbsentAttrs("grid_cell2", {"posinset": "", "setsize": ""});
+
+ testGroupAttrs("grid_row2", 2, 2);
+ testAbsentAttrs("grid_cell3", {"posinset": "", "setsize": ""});
+ testAbsentAttrs("grid_cell4", {"posinset": "", "setsize": ""});
+ testGroupParentAttrs("grid", 2, false);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // ARIA treegrid
+ testGroupAttrs("treegrid_row1", 1, 2, 1);
+ testAbsentAttrs("treegrid_cell1", {"posinset": "", "setsize": ""});
+ testAbsentAttrs("treegrid_cell2", {"posinset": "", "setsize": ""});
+
+ testGroupAttrs("treegrid_row2", 1, 1, 2);
+ testAbsentAttrs("treegrid_cell3", {"posinset": "", "setsize": ""});
+ testAbsentAttrs("treegrid_cell4", {"posinset": "", "setsize": ""});
+
+ testGroupAttrs("treegrid_row3", 2, 2, 1);
+ testAbsentAttrs("treegrid_cell5", {"posinset": "", "setsize": ""});
+ testAbsentAttrs("treegrid_cell6", {"posinset": "", "setsize": ""});
+
+ testGroupParentAttrs("treegrid", 2, true);
+ // row child item count provided by parent grid's aria-colcount
+ testGroupParentAttrs("treegrid_row1", 4, false);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // HTML headings
+ testGroupAttrs("h1", 0, 0, 1);
+ testGroupAttrs("h2", 0, 0, 2);
+ testGroupAttrs("h3", 0, 0, 3);
+ testGroupAttrs("h4", 0, 0, 4);
+ testGroupAttrs("h5", 0, 0, 5);
+ testGroupAttrs("h6", 0, 0, 6);
+ testGroupAttrs("ariaHeadingNoLevel", 0, 0, 2);
+ // No child item counts or "tree" flag for parent of headings
+ testAbsentAttrs("headings", {"child-item-count": "", "tree": ""});
+
+ // ////////////////////////////////////////////////////////////////////////
+ // ARIA combobox
+ testGroupAttrs("combo1_opt1", 1, 4);
+ testGroupAttrs("combo1_opt2", 2, 4);
+ testGroupAttrs("combo1_opt3", 3, 4);
+ testGroupAttrs("combo1_opt4", 4, 4);
+ testGroupParentAttrs("combo1", 4, false);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // ARIA table
+ testGroupAttrs("table_cell", 3, 4);
+ testGroupAttrs("table_row", 2, 2);
+
+ // grid child item count provided by aria-rowcount
+ testGroupParentAttrs("table", 2, false);
+ // row child item count provided by parent grid's aria-colcount
+ testGroupParentAttrs("table_row", 4, false);
+
+ // Attributes calculated even when row is wrapped in a div.
+ testGroupAttrs("wrapped_row_1", 1, 2);
+ testGroupAttrs("wrapped_row_2", 2, 2);
+
+ // ////////////////////////////////////////////////////////////////////////
+ // ARIA list constructed by ARIA owns
+ testGroupAttrs("t1_li1", 1, 3);
+ testGroupAttrs("t1_li2", 2, 3);
+ testGroupAttrs("t1_li3", 3, 3);
+ testGroupParentAttrs("aria-list_4", 3, false);
+
+ // Test group attributes of ARIA comments
+ testGroupAttrs("comm_single_1", 1, 2, 1);
+ testGroupAttrs("comm_single_2", 2, 2, 1);
+ testGroupAttrs("comm_nested_1", 1, 3, 1);
+ testGroupAttrs("comm_nested_1_1", 1, 2, 2);
+ testGroupAttrs("comm_nested_1_2", 2, 2, 2);
+ testGroupAttrs("comm_nested_2", 2, 3, 1);
+ testGroupAttrs("comm_nested_2_1", 1, 1, 2);
+ testGroupAttrs("comm_nested_2_1_1", 1, 1, 3);
+ testGroupAttrs("comm_nested_3", 3, 3, 1);
+
+ // Test that group position information updates after deleting node.
+ testGroupAttrs("tree4_ti1", 1, 2, 1);
+ testGroupAttrs("tree4_ti2", 2, 2, 1);
+ testGroupParentAttrs("tree4", 2, true);
+
+ var tree4element = document.getElementById("tree4_ti1");
+ var tree4acc = getAccessible("tree4");
+ tree4element.remove();
+ waitForEvent(EVENT_REORDER, tree4acc, function() {
+ testGroupAttrs("tree4_ti2", 1, 1, 1);
+ testGroupParentAttrs("tree4", 1, true);
+ SimpleTest.finish();
+ });
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(doTest);
+ </script>
+</head>
+<body>
+
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=468418"
+ title="Expose level for nested lists in HTML">
+ Mozilla Bug 468418
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=844023"
+ title="group info might not be properly updated when flat trees mutate">
+ Bug 844023
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=864224"
+ title="Support nested ARIA listitems structured by role='group'">
+ Bug 864224
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=907682"
+ title=" HTML:option group position is not correct when select is collapsed">
+ Mozilla Bug 907682
+ </a>
+
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+
+ <select>
+ <option id="opt1-nosize">option1</option>
+ <option id="opt2-nosize">option2</option>
+ <option id="opt3-nosize">option3</option>
+ <option id="opt4-nosize">option4</option>
+ </select>
+
+ <select size="4">
+ <option id="opt1">option1</option>
+ <option id="opt2">option2</option>
+ </select>
+
+ <select size="4">
+ <optgroup id="select2_optgroup" label="group">
+ <option id="select2_opt1">option1</option>
+ <option id="select2_opt2">option2</option>
+ </optgroup>
+ <option id="select2_opt3">option3</option>
+ <option id="select2_opt4">option4</option>
+ </select>
+
+ <form>
+ <input type="radio" id="radio1" name="group1"/>
+ <input type="radio" id="radio2" name="group1"/>
+ </form>
+
+ <input type="radio" id="radio3" name="group2"/>
+ <input type="radio" id="radio4" name="group2"/>
+
+ <ul id="ul">
+ <li id="li1">Oranges</li>
+ <li id="li2">Apples</li>
+ <li id="li3">Bananas</li>
+ </ul>
+
+ <ol id="ol">
+ <li id="li4">Oranges</li>
+ <li id="li5">Apples</li>
+ <li id="li6">Bananas
+ <ul id="ol_nested">
+ <li id="n_li4">Oranges</li>
+ <li id="n_li5">Apples</li>
+ <li id="n_li6">Bananas</li>
+ </ul>
+ </li>
+ </ol>
+
+ <span role="list" id="aria-list_1">
+ <span role="listitem" id="li7">Oranges</span>
+ <span role="listitem" id="li8">Apples</span>
+ <span role="listitem" id="li9">Bananas</span>
+ </span>
+
+ <span role="list" id="aria-list_2">
+ <span role="listitem" id="li10">Oranges</span>
+ <span role="listitem" id="li11">Apples</span>
+ <span role="listitem" id="li12">Bananas
+ <span role="list" id="aria-list_2_1">
+ <span role="listitem" id="n_li10">Oranges</span>
+ <span role="listitem" id="n_li11">Apples</span>
+ <span role="listitem" id="n_li12">Bananas</span>
+ </span>
+ </span>
+ </span>
+
+ <div role="list" id="aria-list_3">
+ <div role="listitem" id="lgt_li1">Item 1
+ <div role="group">
+ <div role="listitem" id="lgt_li1_nli1">Item 1A</div>
+ <div role="listitem" id="lgt_li1_nli2">Item 1B</div>
+ </div>
+ </div>
+ <div role="listitem" id="lgt_li2">Item 2
+ <div role="group">
+ <div role="listitem" id="lgt_li2_nli1">Item 2A</div>
+ <div role="listitem" id="lgt_li2_nli2">Item 2B</div>
+ </div>
+ </div>
+ </div>
+
+ <ul role="menubar" id="menubar">
+ <li role="menuitem" aria-haspopup="true" id="menu_item1">File
+ <ul role="menu" id="menu">
+ <li role="menuitem" id="menu_item1.1">New</li>
+ <li role="menuitem" id="menu_item1.2">Open…</li>
+ <li role="separator">-----</li>
+ <li role="menuitem" id="menu_item1.3">Item</li>
+ <li role="menuitemradio" id="menu_item1.4">Radio</li>
+ <li role="menuitemcheckbox" id="menu_item1.5">Checkbox</li>
+ </ul>
+ </li>
+ <li role="menuitem" aria-haspopup="false" id="menu_item2">Help</li>
+ </ul>
+
+ <ul id="tablist_1" role="tablist">
+ <li id="tab_1" role="tab">Crust</li>
+ <li id="tab_2" role="tab">Veges</li>
+ <li id="tab_3" role="tab">Carnivore</li>
+ </ul>
+
+ <ul id="rg1" role="radiogroup">
+ <li id="r1" role="radio" aria-checked="false">Thai</li>
+ <li id="r2" role="radio" aria-checked="false">Subway</li>
+ <li id="r3" role="radio" aria-checked="false">Jimmy Johns</li>
+ </ul>
+
+ <table role="tree" id="tree_1">
+ <tr role="presentation">
+ <td role="treeitem" aria-expanded="true" aria-level="1"
+ id="ti1">vegetables</td>
+ </tr>
+ <tr role="presentation">
+ <td role="treeitem" aria-level="2" id="ti2">cucumber</td>
+ </tr>
+ <tr role="presentation">
+ <td role="treeitem" aria-level="2" id="ti3">carrot</td>
+ </tr>
+ <tr role="presentation">
+ <td role="treeitem" aria-expanded="false" aria-level="1"
+ id="ti4">cars</td>
+ </tr>
+ <tr role="presentation">
+ <td role="treeitem" aria-level="2" id="ti5">mercedes</td>
+ </tr>
+ <tr role="presentation">
+ <td role="treeitem" aria-level="2" id="ti6">BMW</td>
+ </tr>
+ <tr role="presentation">
+ <td role="treeitem" aria-level="2" id="ti7">Audi</td>
+ </tr>
+ <tr role="presentation">
+ <td role="treeitem" aria-level="1" id="ti8">people</td>
+ </tr>
+ </table>
+
+ <ul role="tree" id="tree_2">
+ <li role="treeitem" id="tree2_ti1">Item 1
+ <ul role="group">
+ <li role="treeitem" id="tree2_ti1a">Item 1A</li>
+ <li role="treeitem" id="tree2_ti1b">Item 1B</li>
+ </ul>
+ </li>
+ <li role="treeitem" id="tree2_ti2">Item 2
+ <ul role="group">
+ <li role="treeitem" id="tree2_ti2a">Item 2A</li>
+ <li role="treeitem" id="tree2_ti2b">Item 2B</li>
+ </ul>
+ </li>
+ </div>
+
+ <div role="tree" id="tree_3">
+ <div role="treeitem" id="tree3_ti1">Item 1</div>
+ <div role="group">
+ <li role="treeitem" id="tree3_ti1a">Item 1A</li>
+ <li role="treeitem" id="tree3_ti1b">Item 1B</li>
+ </div>
+ <div role="treeitem" id="tree3_ti2">Item 2</div>
+ <div role="group">
+ <div role="treeitem" id="tree3_ti2a">Item 2A</div>
+ <div role="treeitem" id="tree3_ti2b">Item 2B</div>
+ </div>
+ </div>
+
+ <!-- IMPORTANT: Need to have no whitespace between elements in this tree. -->
+ <div role="tree" id="tree4"><div role="treeitem"
+ id="tree4_ti1">Item 1</div><div role="treeitem"
+ id="tree4_ti2">Item 2</div></div>
+
+ <table role="grid" id="grid">
+ <tr role="row" id="grid_row1">
+ <td role="gridcell" id="grid_cell1">cell1</td>
+ <td role="gridcell" id="grid_cell2">cell2</td>
+ </tr>
+ <tr role="row" id="grid_row2">
+ <td role="gridcell" id="grid_cell3">cell3</td>
+ <td role="gridcell" id="grid_cell4">cell4</td>
+ </tr>
+ </table>
+
+ <div role="treegrid" id="treegrid" aria-colcount="4">
+ <div role="row" aria-level="1" id="treegrid_row1">
+ <div role="gridcell" id="treegrid_cell1">cell1</div>
+ <div role="gridcell" id="treegrid_cell2">cell2</div>
+ </div>
+ <div role="row" aria-level="2" id="treegrid_row2">
+ <div role="gridcell" id="treegrid_cell3">cell1</div>
+ <div role="gridcell" id="treegrid_cell4">cell2</div>
+ </div>
+ <div role="row" id="treegrid_row3">
+ <div role="gridcell" id="treegrid_cell5">cell1</div>
+ <div role="gridcell" id="treegrid_cell6">cell2</div>
+ </div>
+ </div>
+
+ <div id="headings">
+ <h1 id="h1">heading1</h1>
+ <h2 id="h2">heading2</h2>
+ <h3 id="h3">heading3</h3>
+ <h4 id="h4">heading4</h4>
+ <h5 id="h5">heading5</h5>
+ <h6 id="h6">heading6</h6>
+ <div id="ariaHeadingNoLevel" role="heading">ariaHeadingNoLevel</div>
+ </div>
+
+ <ul id="combo1" role="combobox">Password
+ <li id="combo1_opt1" role="option">Xyzzy</li>
+ <li id="combo1_opt2" role="option">Plughs</li>
+ <li id="combo1_opt3" role="option">Shazaam</li>
+ <li id="combo1_opt4" role="option">JoeSentMe</li>
+ </ul>
+
+ <form>
+ <input type="radio" style="display: none;" name="group3">
+ <input type="radio" id="radio5" name="group3">
+ </form>
+
+ <div role="table" aria-colcount="4" aria-rowcount="2" id="table">
+ <div role="row" id="table_row" aria-rowindex="2">
+ <div role="cell" id="table_cell" aria-colindex="3">cell</div>
+ </div>
+ </div>
+
+ <div role="grid" aria-readonly="true">
+ <div tabindex="-1">
+ <div role="row" id="wrapped_row_1">
+ <div role="gridcell">cell content</div>
+ </div>
+ </div>
+ <div tabindex="-1">
+ <div role="row" id="wrapped_row_2">
+ <div role="gridcell">cell content</div>
+ </div>
+ </div>
+ </div>
+
+ <div role="list" aria-owns="t1_li1 t1_li2 t1_li3" id="aria-list_4">
+ <div role="listitem" id="t1_li2">Apples</div>
+ <div role="listitem" id="t1_li1">Oranges</div>
+ </div>
+ <div role="listitem" id="t1_li3">Bananas</div>
+
+ <!-- ARIA comments, 1 level, group pos and size calculation -->
+ <article>
+ <p id="comm_single_1" role="comment">Comment 1</p>
+ <p id="comm_single_2" role="comment">Comment 2</p>
+ </article>
+
+ <!-- Nested comments -->
+ <article>
+ <div id="comm_nested_1" role="comment"><p>Comment 1 level 1</p>
+ <div id="comm_nested_1_1" role="comment"><p>Comment 1 level 2</p></div>
+ <div id="comm_nested_1_2" role="comment"><p>Comment 2 level 2</p></div>
+ </div>
+ <div id="comm_nested_2" role="comment"><p>Comment 2 level 1</p>
+ <div id="comm_nested_2_1" role="comment"><p>Comment 3 level 2</p>
+ <div id="comm_nested_2_1_1" role="comment"><p>Comment 1 level 3</p></div>
+ </div>
+ </div>
+ <div id="comm_nested_3" role="comment"><p>Comment 3 level 1</p></div>
+ </article>
+</body>
+</html>
diff --git a/accessible/tests/mochitest/attributes/test_obj_group.xhtml b/accessible/tests/mochitest/attributes/test_obj_group.xhtml
new file mode 100644
index 0000000000..0eda4b6f2d
--- /dev/null
+++ b/accessible/tests/mochitest/attributes/test_obj_group.xhtml
@@ -0,0 +1,215 @@
+<?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 Group Attributes ('level', 'setsize', 'posinset') Test.">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+ <script type="application/javascript"
+ src="../common.js" />
+ <script type="application/javascript"
+ src="../events.js" />
+ <script type="application/javascript"
+ src="../attributes.js" />
+
+ <script type="application/javascript">
+ <![CDATA[
+ function openMenu(aID)
+ {
+ this.menuNode = getNode(aID);
+
+ this.eventSeq = [
+ new invokerChecker(EVENT_FOCUS, this.menuNode)
+ ];
+
+ this.invoke = function openMenu_invoke()
+ {
+ this.menuNode.open = true;
+ }
+
+ this.finalCheck = function openMenu_finalCheck()
+ {
+ testGroupAttrs("menu_item1.1", 1, 1);
+ testGroupAttrs("menu_item1.2", 1, 3);
+ testGroupAttrs("menu_item1.4", 2, 3);
+ testGroupAttrs("menu_item2", 3, 3);
+ }
+
+ this.getID = function openMenu_getID()
+ {
+ return "open menu " + prettyName(aID);
+ }
+ }
+
+ function openSubMenu(aID)
+ {
+ this.menuNode = getNode(aID);
+
+ this.eventSeq = [
+ new invokerChecker(EVENT_FOCUS, this.menuNode)
+ ];
+
+ this.invoke = function openSubMenu_invoke()
+ {
+ this.menuNode.open = true;
+ }
+
+ this.finalCheck = function openSubMenu_finalCheck()
+ {
+ testGroupAttrs("menu_item2.1", 1, 2, 1);
+ testGroupAttrs("menu_item2.2", 2, 2, 1);
+ }
+
+ this.getID = function openSubMenu_getID()
+ {
+ return "open submenu " + prettyName(aID);
+ }
+ }
+
+ //gA11yEventDumpToConsole = true; // debug stuff
+
+ var gQueue = null;
+ function doTest()
+ {
+ //////////////////////////////////////////////////////////////////////////
+ // xul:listbox (bug 417317)
+ testGroupAttrs("listitem1", 1, 4);
+ testGroupAttrs("listitem2", 2, 4);
+ testGroupAttrs("listitem3", 3, 4);
+ testGroupAttrs("listitem4", 4, 4);
+
+ //////////////////////////////////////////////////////////////////////////
+ // xul:tab
+ testGroupAttrs("tab1", 1, 2);
+ testGroupAttrs("tab2", 2, 2);
+
+ //////////////////////////////////////////////////////////////////////////
+ // xul:radio
+ testGroupAttrs("radio1", 1, 2);
+ testGroupAttrs("radio2", 2, 2);
+
+ //////////////////////////////////////////////////////////////////////////
+ // xul:menulist
+ testGroupAttrs("menulist1.1", 1);
+ testGroupAttrs("menulist1.2", 2);
+ testGroupAttrs("menulist1.3", 3);
+ testGroupAttrs("menulist1.4", 4);
+
+ //////////////////////////////////////////////////////////////////////////
+ // ARIA menu (bug 441888)
+ testGroupAttrs("aria-menuitem", 1, 3);
+ testGroupAttrs("aria-menuitemcheckbox", 2, 3);
+ testGroupAttrs("aria-menuitemradio", 3, 3);
+ testGroupAttrs("aria-menuitem2", 1, 1);
+
+ //////////////////////////////////////////////////////////////////////////
+ // xul:menu (bug 443881)
+ gQueue = new eventQueue();
+ gQueue.push(new openMenu("menu_item1"));
+ gQueue.push(new openSubMenu("menu_item2"));
+ gQueue.invoke(); // 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=417317"
+ title="Certain types of LISTITEM accessibles no longer get attributes set like 'x of y', regression from fix for bug 389926">
+ Mozilla Bug 417317
+ </a><br/>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=443881"
+ title="take into account separators in xul menus when group attributes are calculating">
+ Mozilla Bug 443881
+ </a><br/>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=441888"
+ title="ARIA checked menu items are not included in the total list of menu items">
+ Mozilla Bug 441888
+ </a><br/>
+
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+ <pre id="test">
+ </pre>
+ </body>
+
+ <vbox flex="1">
+
+ <richlistbox>
+ <richlistitem id="listitem1"/>
+ <richlistitem id="listitem2"><label value="listitem2"/></richlistitem>
+ <richlistitem id="listitem3"/>
+ <richlistitem id="listitem4"><label value="listitem4"/></richlistitem>
+ </richlistbox>
+
+ <menubar>
+ <menu label="item1" id="menu_item1">
+ <menupopup>
+ <menuitem label="item1.1" id="menu_item1.1"/>
+ <menuseparator/>
+ <menuitem label="item1.2" id="menu_item1.2"/>
+ <menuitem label="item1.3" hidden="true"/>
+ <menuitem label="item1.4" id="menu_item1.4"/>
+ <menu label="item2" id="menu_item2">
+ <menupopup>
+ <menuitem label="item2.1" id="menu_item2.1"/>
+ <menuitem label="item2.2" id="menu_item2.2"/>
+ </menupopup>
+ </menu>
+ </menupopup>
+ </menu>
+ </menubar>
+
+ <tabbox>
+ <tabs>
+ <tab id="tab1" label="tab1"/>
+ <tab id="tab2" label="tab3"/>
+ </tabs>
+ <tabpanels>
+ <tabpanel/>
+ <tabpanel/>
+ </tabpanels>
+ </tabbox>
+
+ <radiogroup>
+ <radio id="radio1" label="radio1"/>
+ <radio id="radio2" label="radio2"/>
+ </radiogroup>
+
+ <menulist id="menulist1" label="Vehicle">
+ <menupopup>
+ <menuitem id="menulist1.1" label="Car"/>
+ <menuitem id="menulist1.2" label="Taxi"/>
+ <menuitem id="menulist1.3" label="Bus" selected="true"/>
+ <menuitem id="menulist1.4" label="Train"/>
+ </menupopup>
+ </menulist>
+
+ <vbox>
+ <description role="menuitem" id="aria-menuitem"
+ value="conventional menuitem"/>
+ <description role="menuitemcheckbox" id="aria-menuitemcheckbox"
+ value="conventional checkbox menuitem"/>
+ <description role="menuitem" hidden="true"/>
+ <description role="menuitemradio" id="aria-menuitemradio"
+ value="conventional radio menuitem"/>
+ <description role="separator"
+ value="conventional separator"/>
+ <description role="menuitem" id="aria-menuitem2"
+ value="conventional menuitem"/>
+ </vbox>
+
+ </vbox>
+ </hbox>
+</window>
+
diff --git a/accessible/tests/mochitest/attributes/test_obj_group_tree.xhtml b/accessible/tests/mochitest/attributes/test_obj_group_tree.xhtml
new file mode 100644
index 0000000000..287ee7989e
--- /dev/null
+++ b/accessible/tests/mochitest/attributes/test_obj_group_tree.xhtml
@@ -0,0 +1,84 @@
+<?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="Accessible XUL tree attributes tests">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+ <script type="application/javascript"
+ src="../treeview.js" />
+
+ <script type="application/javascript"
+ src="../common.js" />
+ <script type="application/javascript"
+ src="../attributes.js" />
+ <script type="application/javascript"
+ src="../events.js" />
+
+ <script type="application/javascript">
+ <![CDATA[
+ ////////////////////////////////////////////////////////////////////////////
+ // Test
+
+ function doTest()
+ {
+ var treeNode = getNode("tree");
+
+ var tree = getAccessible(treeNode);
+ var treeitem1 = tree.firstChild.nextSibling;
+ testGroupAttrs(treeitem1, 1, 4, 1);
+
+ var treeitem2 = treeitem1.nextSibling;
+ testGroupAttrs(treeitem2, 2, 4, 1);
+
+ var treeitem3 = treeitem2.nextSibling;
+ testGroupAttrs(treeitem3, 1, 2, 2);
+
+ var treeitem4 = treeitem3.nextSibling;
+ testGroupAttrs(treeitem4, 2, 2, 2);
+
+ var treeitem5 = treeitem4.nextSibling;
+ testGroupAttrs(treeitem5, 3, 4, 1);
+
+ var treeitem6 = treeitem5.nextSibling;
+ testGroupAttrs(treeitem6, 4, 4, 1);
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addA11yXULTreeLoadEvent(doTest, "tree", new nsTreeTreeView());
+ ]]>
+ </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=503727"
+ title="Reorganize implementation of XUL tree accessibility">
+ Mozilla Bug 503727
+ </a><br/>
+ <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>
+
+ <vbox id="debug"/>
+ </vbox>
+ </hbox>
+
+</window>
+
diff --git a/accessible/tests/mochitest/attributes/test_tag.html b/accessible/tests/mochitest/attributes/test_tag.html
new file mode 100644
index 0000000000..b57cc2dca8
--- /dev/null
+++ b/accessible/tests/mochitest/attributes/test_tag.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML landmark tests</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="../role.js"></script>
+ <script type="application/javascript"
+ src="../attributes.js"></script>
+
+ <script type="application/javascript">
+
+ function doTest() {
+ // And some AT may look for this
+ testAttrs("nav", {"tag": "nav"}, true);
+ testAttrs("header", {"tag": "header"}, true);
+ testAttrs("footer", {"tag": "footer"}, true);
+ testAttrs("article", {"tag": "article"}, true);
+ testAttrs("aside", {"tag": "aside"}, true);
+ testAttrs("section", {"tag": "section"}, true);
+ testAttrs("main", {"tag": "article"}, true);
+ testAttrs("form", {"tag": "article"}, true);
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(doTest);
+ </script>
+</head>
+<body>
+
+ <a target="_blank"
+ title="Provide mappings for html5 <nav> <header> <footer> <article>"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=593368">
+ Bug 593368
+ </a><br/>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=613502"
+ title="Map <article> like we do aria role article">
+ Bug 613502
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=610650"
+ title="Change implementation of HTML5 landmark elements to conform">
+ Bug 610650
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=614310"
+ title="Map section to pane (like role=region)">
+ Mozilla Bug 614310
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=734982"
+ title="Map ARIA role FORM">
+ Bug 734982
+ </a>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+
+ <nav id="nav">a nav</nav>
+ <header id="header">a header</header>
+ <footer id="footer">a footer</footer>
+ <aside id="aside">by the way I am an aside</aside>
+ <section id="section">a section</section>
+
+ <article id="article">an article</article>
+ <article id="main" role="main">a main area</article>
+ <article id="form" role="form">a form area</article>
+
+</body>
+</html>
diff --git a/accessible/tests/mochitest/attributes/test_xml-roles.html b/accessible/tests/mochitest/attributes/test_xml-roles.html
new file mode 100644
index 0000000000..ff71f0da3a
--- /dev/null
+++ b/accessible/tests/mochitest/attributes/test_xml-roles.html
@@ -0,0 +1,267 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>XML roles tests</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="../role.js"></script>
+ <script type="application/javascript"
+ src="../attributes.js"></script>
+
+ <script type="application/javascript">
+
+ function doTest() {
+ // Some AT may look for this
+ testAttrs("nav", {"xml-roles": "navigation"}, true);
+ testAttrs("header", {"xml-roles": "banner"}, true);
+ testAbsentAttrs("article_header", {"xml-roles": "banner"});
+ testAbsentAttrs("main_header", {"xml-roles": "banner"});
+ testAbsentAttrs("section_header", {"xml-roles": "banner"});
+ testAttrs("footer", {"xml-roles": "contentinfo"}, true);
+ testAbsentAttrs("article_footer", {"xml-roles": "contentinfo"});
+ testAbsentAttrs("main_footer", {"xml-roles": "contentinfo"});
+ testAbsentAttrs("section_footer", {"xml-roles": "contentinfo"});
+ testAttrs("aside", {"xml-roles": "complementary"}, true);
+ testAbsentAttrs("section", {"xml-roles": "region"});
+ testAttrs("main", {"xml-roles": "main"}, true); // // ARIA override
+ testAttrs("form", {"xml-roles": "form"}, true);
+ testAttrs("feed", {"xml-roles": "feed"}, true);
+ testAttrs("article", {"xml-roles": "article"}, true);
+ testAttrs("main_element", {"xml-roles": "main"}, true);
+ testAttrs("figure", {"xml-roles": "figure"}, true);
+
+ testAttrs("search", {"xml-roles": "searchbox"}, true);
+
+ testAttrs("code", {"xml-roles": "code"}, true);
+
+ testAttrs("open-1", {"xml-roles": "open-fence"}, true);
+ testAttrs("open-2", {"xml-roles": "open-fence"}, true);
+ testAttrs("open-3", {"xml-roles": "open-fence"}, true);
+ testAttrs("open-4", {"xml-roles": "open-fence"}, true);
+ testAttrs("open-5", {"xml-roles": "open-fence"}, true);
+ testAttrs("open-6", {"xml-roles": "open-fence"}, true);
+ testAttrs("open-7", {"xml-roles": "open-fence"}, true);
+
+ testAttrs("sep-1", {"xml-roles": "separator"}, true);
+ testAttrs("sep-2", {"xml-roles": "separator"}, true);
+ testAttrs("sep-3", {"xml-roles": "separator"}, true);
+ testAttrs("sep-4", {"xml-roles": "separator"}, true);
+ testAttrs("sep-5", {"xml-roles": "separator"}, true);
+ testAttrs("sep-6", {"xml-roles": "separator"}, true);
+ testAttrs("sep-7", {"xml-roles": "separator"}, true);
+
+ testAttrs("close-1", {"xml-roles": "close-fence"}, true);
+ testAttrs("close-2", {"xml-roles": "close-fence"}, true);
+ testAttrs("close-3", {"xml-roles": "close-fence"}, true);
+ testAttrs("close-4", {"xml-roles": "close-fence"}, true);
+ testAttrs("close-5", {"xml-roles": "close-fence"}, true);
+ testAttrs("close-6", {"xml-roles": "close-fence"}, true);
+ testAttrs("close-7", {"xml-roles": "close-fence"}, true);
+
+ testAttrs("num", {"xml-roles": "numerator"}, true);
+ testAttrs("den", {"xml-roles": "denominator"}, true);
+
+ testAttrs("sub-1", {"xml-roles": "subscript"}, true);
+ testAttrs("sub-2", {"xml-roles": "subscript"}, true);
+ testAttrs("sub-3", {"xml-roles": "subscript"}, true);
+ testAttrs("sup-1", {"xml-roles": "superscript"}, true);
+ testAttrs("sup-2", {"xml-roles": "superscript"}, true);
+ testAttrs("sup-3", {"xml-roles": "superscript"}, true);
+ testAttrs("sup-4", {"xml-roles": "superscript"}, true);
+ testAttrs("presub-1", {"xml-roles": "presubscript"}, true);
+ testAttrs("presub-2", {"xml-roles": "presubscript"}, true);
+ testAttrs("presup-1", {"xml-roles": "presuperscript"}, true);
+
+ testAttrs("under-1", {"xml-roles": "underscript"}, true);
+ testAttrs("under-2", {"xml-roles": "underscript"}, true);
+ testAttrs("over-1", {"xml-roles": "overscript"}, true);
+ testAttrs("over-2", {"xml-roles": "overscript"}, true);
+
+ testAttrs("root-index-1", {"xml-roles": "root-index"}, true);
+
+ testAttrs("base-1", {"xml-roles": "base"}, true);
+ testAttrs("base-2", {"xml-roles": "base"}, true);
+ testAttrs("base-3", {"xml-roles": "base"}, true);
+ testAttrs("base-4", {"xml-roles": "base"}, true);
+ testAttrs("base-5", {"xml-roles": "base"}, true);
+ testAttrs("base-6", {"xml-roles": "base"}, true);
+ testAttrs("base-7", {"xml-roles": "base"}, true);
+ testAttrs("base-8", {"xml-roles": "base"}, true);
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addA11yLoadEvent(doTest);
+ </script>
+</head>
+<body>
+
+ <a target="_blank"
+ title="Provide mappings for html5 <nav> <header> <footer> <article>"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=593368">
+ Bug 593368
+ </a><br/>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=613502"
+ title="Map <article> like we do aria role article">
+ Bug 613502
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=610650"
+ title="Change implementation of HTML5 landmark elements to conform">
+ Bug 610650
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=614310"
+ title="Map section to pane (like role=region)">
+ Mozilla Bug 614310
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=734982"
+ title="Map ARIA role FORM">
+ Bug 734982
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=761891"
+ title="HTML5 article element should expose xml-roles:article object attribute">
+ Bug 761891
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=849624"
+ title="modify HTML5 header and footer accessibility API mapping">
+ Bug 849624
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=1121518"
+ title="ARIA 1.1: Support role 'searchbox'">
+ Bug 1121518
+ </a>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=1356049"
+ title="Map ARIA figure role">
+ Bug 1356049
+ </a>
+
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+
+ <nav id="nav">a nav</nav>
+ <header id="header">a header</header>
+ <footer id="footer">a footer</footer>
+ <article id="article_with_header_and_footer">
+ <header id="article_header">a header within an article</header>
+ <footer id="article_footer">a footer within an article</footer>
+ </article>
+ <main id="main_with_header_and_footer">
+ <header id="main_header">a header within a main</header>
+ <footer id="main_footer">a footer within a main</footer>
+ </main>
+ <section id="section_with_header_and_footer">
+ <header id="section_header">a header within an section</header>
+ <footer id="section_footer">a footer within an section</footer>
+ </section>
+ <aside id="aside">by the way I am an aside</aside>
+ <section id="section">a section</section>
+ <article id="main" role="main">a main area</article>
+ <article id="form" role="form">a form area</article>
+ <div id="feed" role="feed">a feed</div>
+ <article id="article">article</article>
+ <main id="main_element">another main area</main>
+ <div id="figure" role="figure">a figure</div>
+
+ <input id="search" type="search"/>
+
+ <div id="code" role="code"></div>
+
+ <!-- open-fence, separator, close-fence -->
+ <math><mo id="open-1">(</mo><mi>x</mi><mo id="sep-1">,</mo><mi>y</mi><mo id="close-1">)</mo></math>
+ <math><mrow><mo id="open-2">(</mo><mi>x</mi><mo id="sep-2">,</mo><mi>y</mi><mo id="close-2">)</mo></mrow></math>
+ <math><mstyle><mo id="open-3">(</mo><mi>x</mi><mo id="sep-3">,</mo><mi>y</mi><mo id="close-3">)</mo></mstyle></math>
+ <math><msqrt><mo id="open-4">(</mo><mi>x</mi><mo id="sep-4">,</mo><mi>y</mi><mo id="close-4">)</mo></msqrt></math>
+ <math><menclose><mo id="open-5">(</mo><mi>x</mi><mo id="sep-5">,</mo><mi>y</mi><mo id="close-5">)</mo></menclose></math>
+ <math><merror><mo id="open-6">(</mo><mi>x</mi><mo id="sep-6">,</mo><mi>y</mi><mo id="close-6">)</mo></merror></math>
+ <math><mtable><mtr><mtd><mo id="open-7">(</mo><mi>x</mi><mo id="sep-7">,</mo><mi>y</mi><mo id="close-7">)</mo></mtd></mtr></mtable></math>
+
+ <!-- numerator, denominator -->
+ <math>
+ <mfrac>
+ <mi id="num">a</mi>
+ <mi id="den">b</mi>
+ </mfrac>
+ </math>
+
+ <!-- subscript, superscript, presubscript, presuperscript -->
+ <math>
+ <msub>
+ <mi id="base-1">a</mi>
+ <mi id="sub-1">b</mi>
+ </msub>
+ </math>
+ <math>
+ <msup>
+ <mi id="base-2">a</mi>
+ <mi id="sup-1">b</mi>
+ </msup>
+ </math>
+ <math>
+ <msubsup>
+ <mi id="base-3">a</mi>
+ <mi id="sub-2">b</mi>
+ <mi id="sup-2">c</mi>
+ </msubsup>
+ </math>
+ <math>
+ <mmultiscripts>
+ <mi id="base-4">a</mi>
+ <mi id="sub-3">b</mi>
+ <mi id="sup-3">c</mi>
+ <none/>
+ <mi id="sup-4">d</mi>
+ <mprescripts/>
+ <mi id="presub-1">e</mi>
+ <none/>
+ <mi id="presub-2">f</mi>
+ <mi id="presup-1">g</mi>
+ </mmultiscripts>
+ </math>
+
+ <!-- underscript, overscript -->
+ <math>
+ <munder>
+ <mi id="base-5">a</mi>
+ <mi id="under-1">b</mi>
+ </munder>
+ </math>
+ <math>
+ <mover>
+ <mi id="base-6">a</mi>
+ <mi id="over-1">b</mi>
+ </mover>
+ </math>
+ <math>
+ <munderover>
+ <mi id="base-7">a</mi>
+ <mi id="under-2">b</mi>
+ <mi id="over-2">c</mi>
+ </munderover>
+ </math>
+
+ <!-- root-index -->
+ <math>
+ <mroot>
+ <mi id="base-8">a</mi>
+ <mi id="root-index-1">b</mi>
+ </mroot>
+ </math>
+
+</body>
+</html>