diff options
Diffstat (limited to '')
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> |