import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,67 @@
[DEFAULT]
support-files =
docload_wnd.html
focus.html
scroll.html
!/accessible/tests/mochitest/*.js
!/accessible/tests/mochitest/letters.gif
[test_aria_alert.html]
[test_aria_menu.html]
[test_aria_objattr.html]
[test_aria_owns.html]
[test_aria_statechange.html]
[test_attrs.html]
[test_bug1322593.html]
[test_bug1322593-2.html]
[test_caretmove.html]
[test_caretmove.xul]
[test_coalescence.html]
[test_contextmenu.html]
[test_descrchange.html]
[test_docload.html]
[test_docload.xul]
skip-if = buildapp == 'mulet'
[test_docload_aria.html]
[test_dragndrop.html]
[test_flush.html]
[test_focus_aria_activedescendant.html]
[test_focus_autocomplete.xul]
# Disabled on Linux and Windows due to frequent failures - bug 695019, bug 890795
skip-if = os == 'win' || os == 'linux'
[test_focus_browserui.xul]
[test_focus_canvas.html]
[test_focus_contextmenu.xul]
[test_focus_controls.html]
[test_focus_dialog.html]
[test_focus_doc.html]
[test_focus_general.html]
[test_focus_general.xul]
[test_focus_listcontrols.xul]
[test_focus_menu.xul]
[test_focus_name.html]
[test_focus_selects.html]
[test_focus_tabbox.xul]
[test_focus_tree.xul]
[test_fromUserInput.html]
[test_label.xul]
[test_menu.xul]
[test_mutation.html]
[test_mutation.xhtml]
[test_namechange.xul]
[test_namechange.html]
[test_scroll.xul]
[test_scroll_caret.xul]
[test_selection.html]
skip-if = buildapp == 'mulet' || os == 'mac'
[test_selection.xul]
skip-if = os == 'mac'
[test_selection_aria.html]
[test_statechange.html]
[test_text.html]
[test_text_alg.html]
[test_textattrchange.html]
[test_textselchange.html]
[test_tree.xul]
[test_valuechange.html]
skip-if = os == 'mac'

View file

@ -0,0 +1,39 @@
<html>
<head>
<title>Accessible events testing for document</title>
<script>
const STATE_BUSY = Components.interfaces.nsIAccessibleStates.STATE_BUSY;
var gService = null;
function waitForDocLoad()
{
if (!gService) {
gService = Components.classes["@mozilla.org/accessibilityService;1"].
getService(Components.interfaces.nsIAccessibilityService);
}
var accDoc = gService.getAccessibleFor(document);
var state = {};
accDoc.getState(state, {});
if (state.value & STATE_BUSY) {
window.setTimeout(waitForDocLoad, 0);
return;
}
hideIFrame();
}
function hideIFrame()
{
var iframe = document.getElementById("iframe");
gService.getAccessibleFor(iframe.contentDocument);
iframe.style.display = 'none';
}
</script>
</head>
<body onload="waitForDocLoad();">
<iframe id="iframe"></iframe>
</body>
</html>

View file

@ -0,0 +1,10 @@
<html>
<head>
<title>editable document</title>
</head>
<body contentEditable="true">
editable document
</body>
</html>

View file

@ -0,0 +1,181 @@
<html>
<head>
<title>nsIAccessible actions testing for anchors</title>
</head>
<body>
<p>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
</p>
<a name="link1">link1</a>
<p style="color: blue">
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
</p>
<h1 id="heading_1">heading 1</h1>
<p style="color: blue">
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
</p>
</body>
<html>

View file

@ -0,0 +1,92 @@
<html>
<head>
<title>ARIA alert event testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
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="../states.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
function showAlert(aID)
{
this.DOMNode = document.createElement("div");
this.invoke = function showAlert_invoke()
{
this.DOMNode.setAttribute("role", "alert");
this.DOMNode.setAttribute("id", aID);
var text = document.createTextNode("alert");
this.DOMNode.appendChild(text);
document.body.appendChild(this.DOMNode);
};
this.getID = function showAlert_getID()
{
return "Show ARIA alert " + aID;
};
}
function changeAlert(aID)
{
this.__defineGetter__("DOMNode", function() { return getNode(aID) });
this.invoke = function changeAlert_invoke()
{
this.DOMNode.textContent = "new alert";
}
this.getID = function showAlert_getID()
{
return "Change ARIA alert " + aID;
}
}
////////////////////////////////////////////////////////////////////////////
// Do tests
//gA11yEventDumpToConsole = true; // debuging
//enableLogging("tree,events,verbose");
var gQueue = null;
function doTests()
{
gQueue = new eventQueue(nsIAccessibleEvent.EVENT_ALERT);
gQueue.push(new showAlert("alert"));
gQueue.push(new changeAlert("alert"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=591199"
title="mochitest for bug 334386: fire alert event when ARIA alert is shown or new its children are inserted">
Mozilla Bug 591199
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
</html>

View file

@ -0,0 +1,285 @@
<html>
<head>
<title>ARIA menu events testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
const kViaDisplayStyle = 0;
const kViaVisibilityStyle = 1;
function focusMenu(aMenuBarID, aMenuID, aActiveMenuBarID)
{
this.eventSeq = [];
if (aActiveMenuBarID) {
this.eventSeq.push(new invokerChecker(EVENT_MENU_END,
getNode(aActiveMenuBarID)));
}
this.eventSeq.push(new invokerChecker(EVENT_MENU_START, getNode(aMenuBarID)));
this.eventSeq.push(new invokerChecker(EVENT_FOCUS, getNode(aMenuID)));
this.invoke = function focusMenu_invoke()
{
getNode(aMenuID).focus();
}
this.getID = function focusMenu_getID()
{
return "focus menu '" + aMenuID + "'";
}
}
function showMenu(aMenuID, aParentMenuID, aHow)
{
this.menuNode = getNode(aMenuID);
// Because of aria-owns processing we may have menupopup start fired before
// related show event.
this.eventSeq = [
new invokerChecker(EVENT_SHOW, this.menuNode),
new invokerChecker(EVENT_REORDER, getNode(aParentMenuID)),
new invokerChecker(EVENT_MENUPOPUP_START, this.menuNode)
];
this.invoke = function showMenu_invoke()
{
if (aHow == kViaDisplayStyle)
this.menuNode.style.display = "block";
else
this.menuNode.style.visibility = "visible";
};
this.getID = function showMenu_getID()
{
return "Show ARIA menu '" + aMenuID + "' by " +
(aHow == kViaDisplayStyle ? "display" : "visibility") +
" style tricks";
};
}
function closeMenu(aMenuID, aParentMenuID, aHow)
{
this.menuNode = getNode(aMenuID);
this.menu = null;
this.eventSeq = [
new invokerChecker(EVENT_HIDE, getMenu, this),
new invokerChecker(EVENT_MENUPOPUP_END, getMenu, this),
new invokerChecker(EVENT_REORDER, getNode(aParentMenuID))
];
this.invoke = function closeMenu_invoke()
{
// Store menu accessible reference while menu is still open.
this.menu = getAccessible(this.menuNode);
// Hide menu.
if (aHow == kViaDisplayStyle)
this.menuNode.style.display = "none";
else
this.menuNode.style.visibility = "hidden";
}
this.getID = function closeMenu_getID()
{
return "Close ARIA menu " + aMenuID + " by " +
(aHow == kViaDisplayStyle ? "display" : "visibility") +
" style tricks";
}
function getMenu(aThisObj)
{
return aThisObj.menu;
}
}
function focusInsideMenu(aMenuID, aMenuBarID)
{
this.eventSeq = [
new invokerChecker(EVENT_FOCUS, getNode(aMenuID))
];
this.unexpectedEventSeq = [
new invokerChecker(EVENT_MENU_END, getNode(aMenuBarID))
];
this.invoke = function focusInsideMenu_invoke()
{
getNode(aMenuID).focus();
}
this.getID = function focusInsideMenu_getID()
{
return "focus menu '" + aMenuID + "'";
}
}
function blurMenu(aMenuBarID)
{
var eventSeq = [
new invokerChecker(EVENT_MENU_END, getNode(aMenuBarID)),
new invokerChecker(EVENT_FOCUS, getNode("outsidemenu"))
];
this.__proto__ = new synthClick("outsidemenu", eventSeq);
this.getID = function blurMenu_getID()
{
return "blur menu";
}
}
////////////////////////////////////////////////////////////////////////////
// Do tests
//gA11yEventDumpToConsole = true; // debuging
//enableLogging("tree,events,verbose");
var gQueue = null;
function doTests()
{
gQueue = new eventQueue();
gQueue.push(new focusMenu("menubar2", "menu-help"));
gQueue.push(new focusMenu("menubar", "menu-file", "menubar2"));
gQueue.push(new showMenu("menupopup-file", "menu-file", kViaDisplayStyle));
gQueue.push(new closeMenu("menupopup-file", "menu-file", kViaDisplayStyle));
gQueue.push(new showMenu("menupopup-edit", "menu-edit", kViaVisibilityStyle));
gQueue.push(new closeMenu("menupopup-edit", "menu-edit", kViaVisibilityStyle));
gQueue.push(new focusInsideMenu("menu-edit", "menubar"));
gQueue.push(new blurMenu("menubar"));
gQueue.push(new focusMenu("menubar3", "mb3-mi-outside"));
gQueue.push(new showMenu("mb4-menu", document, kViaDisplayStyle));
gQueue.push(new focusMenu("menubar4", "mb4-item1"));
gQueue.push(new focusMenu("menubar5", "mb5-mi"));
gQueue.push(new synthFocus("mi6"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=606207"
title="Dojo dropdown buttons are broken">
Bug 606207
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=614829"
title="Menupopup end event isn't fired for ARIA menus">
Bug 614829
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=615189"
title="Clean up FireAccessibleFocusEvent">
Bug 615189
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=673958"
title="Rework accessible focus handling">
Bug 673958
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=933322"
title="menustart/end events are missing when aria-owns makes a menu hierarchy">
Bug 933322
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=934460"
title="menustart/end events may be missed when top level menuitem is focused">
Bug 934460
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=970005"
title="infinite long loop in a11y:FocusManager::ProcessFocusEvent">
Bug 970005
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="menubar" role="menubar">
<div id="menu-file" role="menuitem" tabindex="0">
File
<div id="menupopup-file" role="menu" style="display: none;">
<div id="menuitem-newtab" role="menuitem" tabindex="0">New Tab</div>
<div id="menuitem-newwindow" role="menuitem" tabindex="0">New Window</div>
</div>
</div>
<div id="menu-edit" role="menuitem" tabindex="0">
Edit
<div id="menupopup-edit" role="menu" style="visibility: hidden;">
<div id="menuitem-undo" role="menuitem" tabindex="0">Undo</div>
<div id="menuitem-redo" role="menuitem" tabindex="0">Redo</div>
</div>
</div>
</div>
<div id="menubar2" role="menubar">
<div id="menu-help" role="menuitem" tabindex="0">
Help
<div id="menupopup-help" role="menu" style="display: none;">
<div id="menuitem-about" role="menuitem" tabindex="0">About</div>
</div>
</div>
</div>
<div tabindex="0" id="outsidemenu">outsidemenu</div>
<!-- aria-owns relations -->
<div id="menubar3" role="menubar" aria-owns="mb3-mi-outside"></div>
<div id="mb3-mi-outside" role="menuitem" tabindex="0">Outside</div>
<div id="menubar4" role="menubar">
<div id="mb4_topitem" role="menuitem" aria-haspopup="true"
aria-owns="mb4-menu">Item</div>
</div>
<div id="mb4-menu" role="menu" style="display:none;">
<div role="menuitem" id="mb4-item1" tabindex="0">Item 1.1</div>
<div role="menuitem" tabindex="0">Item 1.2</div>
</div>
<!-- focus top-level menu item having haspopup -->
<div id="menubar5" role="menubar">
<div role="menuitem" aria-haspopup="true" id="mb5-mi" tabindex="0">
Item
<div role="menu" style="display:none;">
<div role="menuitem" tabindex="0">Item 1.1</div>
<div role="menuitem" tabindex="0">Item 1.2</div>
</div>
</div>
</div>
<!-- other aria-owns relations -->
<div id="mi6" tabindex="0" role="menuitem">aria-owned item</div>
<div aria-owns="mi6">Obla</div>
<div id="eventdump"></div>
</body>
</html>

View file

@ -0,0 +1,118 @@
<html>
<head>
<title>Accessible ARIA object attribute changes</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
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">
/**
* Do tests.
*/
var gQueue = null;
function updateAttribute(aID, aAttr, aValue)
{
this.node = getNode(aID);
this.accessible = getAccessible(this.node);
this.eventSeq = [
new objAttrChangedChecker(aID, aAttr),
];
this.invoke = function updateAttribute_invoke()
{
this.node.setAttribute(aAttr, aValue);
};
this.getID = function updateAttribute_getID()
{
return aAttr + " for " + aID + " " + aValue;
};
}
function updateARIAHidden(aID, aIsDefined, aChildId)
{
this.__proto__ = new updateAttribute(aID, "aria-hidden",
aIsDefined ? "true" : "false");
this.finalCheck = function updateARIAHidden()
{
if (aIsDefined) {
testAttrs(aID, {"hidden" : "true"}, true);
testAttrs(aChildId, {"hidden" : "true"}, true);
} else {
testAbsentAttrs(aID, { "hidden": "true"});
testAbsentAttrs(aChildId, { "hidden": "true"});
}
}
}
// Debug stuff.
// gA11yEventDumpID = "eventdump";
//gA11yEventDumpToConsole = true;
function doTests()
{
gQueue = new eventQueue();
gQueue.push(new updateARIAHidden("hideable", true, "hideable_child"));
gQueue.push(new updateARIAHidden("hideable", false, "hideable_child"));
gQueue.push(new updateAttribute("sortable", "aria-sort", "ascending"));
// For experimental ARIA extensions
gQueue.push(new updateAttribute("custom", "aria-blah", "true"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=581096"
title="Add support for aria-hidden">
Mozilla Bug 581096
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=640707"
title="Add event support for aria-sort">
Mozilla Bug 640707
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=640707"
title="Expand support for aria attribute change events">
Mozilla Bug 563862
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="eventdump"></div>
<div id="hideable"><div id="hideable_child">Hi</div><div>there</div></div>
<div id="sortable" role="columnheader" aria-sort="none">aria-sort</div>
<div id="custom" role="custom" aria-blah="false">Fat free cheese</div>
</body>
</html>

View file

@ -0,0 +1,129 @@
<html>
<head>
<title>Aria-owns targets shouldn't be on invalidation list so shouldn't have
show/hide events</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
////////////////////////////////////////////////////////////////////////////
// Do tests.
//gA11yEventDumpToConsole = true; // debug stuff
//enableLogging("tree,eventTree,verbose");
/**
* Aria-owns target shouldn't have a show event.
* Markup:
* <div id="t1_fc" aria-owns="t1_owns"></div>
* <span id="t1_owns"></div>
*/
function testAriaOwns()
{
this.parent = getNode("t1");
this.fc = document.createElement("div");
this.fc.setAttribute("id", "t1_fc");
this.owns = document.createElement("span");
this.owns.setAttribute("id", "t1_owns");
this.eventSeq = [
new invokerChecker(EVENT_SHOW, this.fc),
new unexpectedInvokerChecker(EVENT_SHOW, this.owns)
];
this.invoke = function testAriaOwns_invoke()
{
getNode("t1").appendChild(this.fc);
getNode("t1").appendChild(this.owns);
getNode("t1_fc").setAttribute("aria-owns", "t1_owns");
};
this.getID = function testAriaOwns_getID() {
return "Aria-owns target shouldn't have show event";
};
}
/**
* Target of both aria-owns and other aria attribute like aria-labelledby
* shouldn't have a show event.
* Markup:
* <div id="t2_fc" aria-owns="t1_owns"></div>
* <div id="t2_sc" aria-labelledby="t2_owns"></div>
* <span id="t2_owns"></div>
*/
function testAriaOwnsAndLabelledBy()
{
this.parent = getNode("t2");
this.fc = document.createElement("div");
this.fc.setAttribute("id", "t2_fc");
this.sc = document.createElement("div");
this.sc.setAttribute("id", "t2_sc");
this.owns = document.createElement("span");
this.owns.setAttribute("id", "t2_owns");
this.eventSeq = [
new invokerChecker(EVENT_SHOW, this.fc),
new invokerChecker(EVENT_SHOW, this.sc),
new unexpectedInvokerChecker(EVENT_SHOW, this.owns)
];
this.invoke = function testAriaOwns_invoke()
{
getNode("t2").appendChild(this.fc);
getNode("t2").appendChild(this.sc);
getNode("t2").appendChild(this.owns);
getNode("t2_fc").setAttribute("aria-owns", "t2_owns");
getNode("t2_sc").setAttribute("aria-labelledby", "t2_owns");
};
this.getID = function testAriaOwns_getID() {
return "Aria-owns and aria-labelledby target shouldn't have show event";
};
}
var gQueue = null;
function doTests()
{
gQueue = new eventQueue();
gQueue.push(new testAriaOwns());
gQueue.push(new testAriaOwnsAndLabelledBy());
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1296420"
title="Aria-owns targets shouldn't be on invalidation list so shouldn't
have show/hide events">
Mozilla Bug 1296420
</a><br>
<div id="testContainer">
<div id="t1"></div>
<div id="t2"></div>
</div>
</body>
</html>

View file

@ -0,0 +1,208 @@
<html>
<head>
<title>ARIA state change event testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
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="../states.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
/**
* Do tests.
*/
var gQueue = null;
//gA11yEventDumpID = "eventdump"; // debugging
//gA11yEventDumpToConsole = true; // debugging
function expandNode(aID, aIsExpanded)
{
this.DOMNode = getNode(aID);
this.eventSeq = [
new expandedStateChecker(aIsExpanded, this.DOMNode)
];
this.invoke = function expandNode_invoke()
{
this.DOMNode.setAttribute("aria-expanded",
(aIsExpanded ? "true" : "false"));
};
this.getID = function expandNode_getID()
{
return prettyName(aID) + " aria-expanded changed to '" + aIsExpanded + "'";
};
}
function busyify(aID, aIsBusy)
{
this.DOMNode = getNode(aID);
this.eventSeq = [
new stateChangeChecker(STATE_BUSY, kOrdinalState, aIsBusy, this.DOMNode)
];
this.invoke = function busyify_invoke()
{
this.DOMNode.setAttribute("aria-busy", (aIsBusy ? "true" : "false"));
};
this.getID = function busyify_getID()
{
return prettyName(aID) + " aria-busy changed to '" + aIsBusy + "'";
};
}
function setAttrOfMixedType(aID, aAttr, aState, aValue)
{
this.DOMNode = getNode(aID);
this.eventSeq = [
new stateChangeChecker(aState, kOrdinalState,
aValue == "true", this.DOMNode)
];
if (hasState(aID, STATE_MIXED) || aValue == "mixed") {
this.eventSeq.push(
new stateChangeChecker(STATE_MIXED, kOrdinalState,
aValue == "mixed", this.DOMNode)
);
}
this.invoke = function setAttrOfMixedType_invoke()
{
this.DOMNode.setAttribute(aAttr, aValue);
};
this.getID = function setAttrOfMixedType_getID()
{
return prettyName(aID) + " " + aAttr + " changed to '" + aValue + "'";
};
}
function setPressed(aID, aValue)
{
this.__proto__ =
new setAttrOfMixedType(aID, "aria-pressed", STATE_PRESSED, aValue);
}
function setChecked(aID, aValue)
{
this.__proto__ =
new setAttrOfMixedType(aID, "aria-checked", STATE_CHECKED, aValue);
}
function buildQueueForAttr(aList, aQueue, aID, aInvokerFunc)
{
for (var i = 0; i < aList.length; i++) {
for (var j = i + 1; j < aList.length; j++) {
// XXX: changes from/to "undefined"/"" shouldn't fire state change
// events, bug 472142.
aQueue.push(new aInvokerFunc(aID, aList[i]));
aQueue.push(new aInvokerFunc(aID, aList[j]));
}
}
}
function buildQueueForAttrOfMixedType(aQueue, aID, aInvokerFunc)
{
var list = [ "", "undefined", "false", "true", "mixed" ];
buildQueueForAttr(list, aQueue, aID, aInvokerFunc);
}
function buildQueueForAttrOfBoolType(aQueue, aID, aInvokerFunc)
{
var list = [ "", "undefined", "false", "true" ];
buildQueueForAttr(list, aQueue, aID, aInvokerFunc);
}
function doTests()
{
gQueue = new eventQueue();
gQueue.push(new expandNode("section", true));
gQueue.push(new expandNode("section", false));
gQueue.push(new expandNode("div", true));
gQueue.push(new expandNode("div", false));
gQueue.push(new busyify("aria_doc", true));
gQueue.push(new busyify("aria_doc", false));
buildQueueForAttrOfMixedType(gQueue, "pressable", setPressed);
buildQueueForAttrOfMixedType(gQueue, "pressable_native", setPressed);
buildQueueForAttrOfMixedType(gQueue, "checkable", setChecked);
buildQueueForAttrOfBoolType(gQueue, "checkableBool", setChecked);
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=551684"
title="No statechange event for aria-expanded on native HTML elements, is fired on ARIA widgets">
Mozilla Bug 551684
</a><br>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=648133"
title="fire state change event for aria-busy">
Mozilla Bug 648133
</a><br>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=467143"
title="mixed state change event is fired for focused accessible only">
Mozilla Bug 467143
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=989958"
title="Pressed state is not exposed on a button element with aria-pressed attribute">
Mozilla Bug 989958
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1136563"
title="Support ARIA 1.1 switch role">
Mozilla Bug 1136563
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="eventdump"></div>
<!-- aria-expanded -->
<div id="section" role="section" aria-expanded="false">expandable section</div>
<div id="div" aria-expanded="false">expandable native div</div>
<!-- aria-busy -->
<div id="aria_doc" role="document" tabindex="0">A document</div>
<!-- aria-pressed -->
<div id="pressable" role="button"></div>
<button id="pressable_native"></button>
<!-- aria-checked -->
<div id="checkable" role="checkbox"></div>
<div id="checkableBool" role="switch"></div>
</body>
</html>

View file

@ -0,0 +1,90 @@
<html>
<head>
<title>Event object attributes tests</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../attributes.js"></script>
<script type="application/javascript">
/**
* Test "event-from-input" object attribute.
*/
function eventFromInputChecker(aEventType, aID, aValue, aNoTargetID)
{
this.type = aEventType;
this.target = getAccessible(aID);
this.noTarget = getNode(aNoTargetID);
this.check = function checker_check(aEvent)
{
testAttrs(aEvent.accessible, { "event-from-input": aValue }, true);
var accessible = getAccessible(this.noTarget);
testAbsentAttrs(accessible, { "event-from-input": "" });
}
}
/**
* Do tests.
*/
var gQueue = null;
// gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true; // debug stuff
function doTests()
{
gQueue = new eventQueue();
var id = "textbox", noTargetId = "textarea";
var checker =
new eventFromInputChecker(EVENT_FOCUS, id, "false", noTargetId);
gQueue.push(new synthFocus(id, checker));
if (!MAC) { // Mac failure is bug 541093
var checker =
new eventFromInputChecker(EVENT_TEXT_CARET_MOVED, id, "true", noTargetId);
gQueue.push(new synthHomeKey(id, checker));
}
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=540285"
title="Event object attributes testing">
Mozilla Bug 540285
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<input id="textbox" value="hello">
<textarea id="textarea"></textarea>
<div id="eventdump"></div>
</body>
</html>

View file

@ -0,0 +1,83 @@
<html>
<head>
<title>Accessible mutation events testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
function changeMultipleElements()
{
this.node1 = getNode("span1");
this.node2 = getNode("span2");
this.eventSeq = [
new textChangeChecker("container", 0, 5, "hello", false, undefined, true),
new textChangeChecker("container", 6, 11, "world", false, undefined, true),
new orderChecker(),
new textChangeChecker("container", 0, 1, "a", true, undefined, true),
new textChangeChecker("container", 7, 8, "b", true, undefined, true)
];
this.invoke = function changeMultipleElements_invoke()
{
this.node1.textContent = "a";
this.node2.textContent = "b";
}
this.getID = function changeMultipleElements_invoke_getID()
{
return "Change the text content of multiple sibling divs";
}
}
////////////////////////////////////////////////////////////////////////////
// Do tests
// gA11yEventDumpToConsole = true; // debugging
var gQueue = null;
function doTests()
{
gQueue = new eventQueue();
gQueue.push(new changeMultipleElements());
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1322593"
title="missing text change events when multiple elements updated at once">
Mozilla Bug 1322593
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="container">
<span id="span1">hello</span>
<span>your</span>
<span id="span2">world</span>
</div>
</body>
</html>

View file

@ -0,0 +1,80 @@
<html>
<head>
<title>Accessible mutation events testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
function changeMultipleElements()
{
this.node1 = getNode("div1");
this.node2 = getNode("div2");
this.eventSeq = [
new textChangeChecker("div1", 0, 5, "hello", false, undefined, true),
new textChangeChecker("div2", 0, 5, "world", false, undefined, true),
new orderChecker(),
new textChangeChecker("div1", 0, 1, "a", true, undefined, true),
new textChangeChecker("div2", 0, 1, "b", true, undefined, true)
];
this.invoke = function changeMultipleElements_invoke()
{
this.node1.textContent = "a";
this.node2.textContent = "b";
}
this.getID = function changeMultipleElements_invoke_getID()
{
return "Change the text content of multiple sibling divs";
}
}
////////////////////////////////////////////////////////////////////////////
// Do tests
// gA11yEventDumpToConsole = true; // debugging
var gQueue = null;
function doTests()
{
gQueue = new eventQueue();
gQueue.push(new changeMultipleElements());
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1322593"
title="missing text change events when multiple elements updated at once">
Mozilla Bug 1322593
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="div1">hello</div>
<div id="div2">world</div>
</body>
</html>

View file

@ -0,0 +1,140 @@
<html>
<head>
<title>Accessible caret move events testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
/**
* Click checker.
*/
function clickChecker(aCaretOffset, aID, aExtraNodeOrID, aExtraCaretOffset)
{
this.__proto__ = new caretMoveChecker(aCaretOffset, aID);
this.extraNode = getNode(aExtraNodeOrID);
this.check = function clickChecker_check(aEvent)
{
this.__proto__.check(aEvent);
if (this.extraNode) {
var acc = getAccessible(this.extraNode, [nsIAccessibleText]);
is(acc.caretOffset, aExtraCaretOffset,
"Wrong caret offset for " + aExtraNodeOrID);
}
}
}
/**
* Do tests.
*/
var gQueue = null;
// gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true;
function doTests()
{
// test caret move events and caret offsets
gQueue = new eventQueue();
var id = "textbox";
gQueue.push(new synthFocus(id, new caretMoveChecker(5, id)));
gQueue.push(new synthSelectAll(id, new caretMoveChecker(5, id)));
gQueue.push(new synthClick(id, new caretMoveChecker(0, id)));
gQueue.push(new synthRightKey(id, new caretMoveChecker(1, id)));
id = "textarea";
gQueue.push(new synthClick(id, new caretMoveChecker(0, id)));
gQueue.push(new synthRightKey(id, new caretMoveChecker(1, id)));
gQueue.push(new synthDownKey(id, new caretMoveChecker(12, id)));
id = "textarea_wrapped";
gQueue.push(new setCaretOffset(id, 4, id));
gQueue.push(new synthLeftKey(id, new caretMoveChecker(4, id)));
id = "p";
gQueue.push(new synthClick(id, new caretMoveChecker(0, id)));
gQueue.push(new synthRightKey(id, new caretMoveChecker(1, id)));
gQueue.push(new synthDownKey(id, new caretMoveChecker(6, id)));
id = "p1_in_div";
gQueue.push(new synthClick(id, new clickChecker(0, id, "p2_in_div", -1)));
id = "p";
gQueue.push(new synthShiftTab(id, new caretMoveChecker(0, id)));
id = "textarea";
gQueue.push(new synthShiftTab(id, new caretMoveChecker(12, id)));
id = "p";
gQueue.push(new synthTab(id, new caretMoveChecker(0, id)));
// Set caret after a child of span element, i.e. after 'text' text.
gQueue.push(new moveCaretToDOMPoint("test1", getNode("test1_span"), 1,
4, "test1"));
gQueue.push(new moveCaretToDOMPoint("test2", getNode("test2_span"), 1,
4, "test2"));
// empty text element
gQueue.push(new moveCaretToDOMPoint("test3", getNode("test3"), 0,
0, "test3"));
gQueue.push(new moveCaretToDOMPoint("test4", getNode("test4_span"), 0,
0, "test4"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=454377"
title="Accessible caret move events testing">
Bug 454377
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=567571"
title="caret-moved events missing at the end of a wrapped line of text">
Bug 567571
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=824901"
title="HyperTextAccessible::DOMPointToHypertextOffset fails for node and offset equal to node child count">
Bug 824901
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<input id="textbox" value="hello"/>
<textarea id="textarea">text<br>text</textarea>
<p id="p" contentEditable="true"><span>text</span><br/>text</p>
<div id="div" contentEditable="true"><p id="p1_in_div">text</p><p id="p2_in_div">text</p></div>
<p contentEditable="true" id="test1"><span id="test1_span">text</span>ohoho</p>
<p contentEditable="true" id="test2"><span><span id="test2_span">text</span></span>ohoho</p>
<p contentEditable="true" id="test3"></p>
<p contentEditable="true" id="test4"><span id="test4_span"></span></p>
<textarea id="textarea_wrapped" cols="5">hey friend</textarea>
<div id="eventdump"></div>
</body>
</html>

View file

@ -0,0 +1,72 @@
<?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="Caret move event testing">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript">
/**
* Do tests.
*/
//gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true;
var gQueue = null;
function doTests()
{
if (MAC) {
todo(false, "Make these tests pass on OSX (bug 650294)");
SimpleTest.finish();
return;
}
gQueue = new eventQueue(EVENT_TEXT_CARET_MOVED);
var id = "textbox";
var input = getNode(id).inputField;
gQueue.push(new synthFocus(id, new caretMoveChecker(5, input)));
gQueue.push(new synthSelectAll(id, new caretMoveChecker(5, input)));
gQueue.push(new synthHomeKey(id, new caretMoveChecker(0, input)));
gQueue.push(new synthRightKey(id, new caretMoveChecker(1, input)));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</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=634240"
title="No caret move events are fired for XUL textbox accessible">
Mozilla Bug 634240
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<textbox id="textbox" value="hello"/>
<vbox id="eventdump"/>
</vbox>
</hbox>
</window>

View file

@ -0,0 +1,864 @@
<html>
<head>
<title>Accessible mutation events coalescence testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
////////////////////////////////////////////////////////////////////////////
// Invoker base classes
const kRemoveElm = 1;
const kHideElm = 2;
const kAddElm = 3;
const kShowElm = 4;
/**
* Base class to test of mutation events coalescence.
*/
function coalescenceBase(aChildAction, aParentAction,
aPerformActionOnChildInTheFirstPlace)
{
// Invoker interface
this.invoke = function coalescenceBase_invoke()
{
if (aPerformActionOnChildInTheFirstPlace) {
this.invokeAction(this.childNode, aChildAction);
this.invokeAction(this.parentNode, aParentAction);
} else {
this.invokeAction(this.parentNode, aParentAction);
this.invokeAction(this.childNode, aChildAction);
}
}
this.getID = function coalescenceBase_getID()
{
var childAction = this.getActionName(aChildAction) + " child";
var parentAction = this.getActionName(aParentAction) + " parent";
if (aPerformActionOnChildInTheFirstPlace)
return childAction + " and then " + parentAction;
return parentAction + " and then " + childAction;
}
this.finalCheck = function coalescenceBase_check()
{
if (this.getEventType(aChildAction) == EVENT_HIDE) {
testIsDefunct(this.child);
}
if (this.getEventType(aParentAction) == EVENT_HIDE) {
testIsDefunct(this.parent);
}
}
// Implementation details
this.invokeAction = function coalescenceBase_invokeAction(aNode, aAction)
{
switch (aAction) {
case kRemoveElm:
aNode.parentNode.removeChild(aNode);
break;
case kHideElm:
aNode.style.display = "none";
break;
case kAddElm:
if (aNode == this.parentNode)
this.hostNode.appendChild(this.parentNode);
else
this.parentNode.appendChild(this.childNode);
break;
case kShowElm:
aNode.style.display = "block";
break;
default:
return INVOKER_ACTION_FAILED;
}
}
this.getEventType = function coalescenceBase_getEventType(aAction)
{
switch (aAction) {
case kRemoveElm: case kHideElm:
return EVENT_HIDE;
case kAddElm: case kShowElm:
return EVENT_SHOW;
}
}
this.getActionName = function coalescenceBase_getActionName(aAction)
{
switch (aAction) {
case kRemoveElm:
return "remove";
case kHideElm:
return "hide";
case kAddElm:
return "add";
case kShowElm:
return "show";
default:
return "??";
}
}
this.initSequence = function coalescenceBase_initSequence()
{
// expected events
var eventType = this.getEventType(aParentAction);
this.eventSeq = [
new invokerChecker(eventType, this.parentNode),
new invokerChecker(EVENT_REORDER, this.hostNode)
];
// unexpected events
this.unexpectedEventSeq = [
new invokerChecker(this.getEventType(aChildAction), this.childNode),
new invokerChecker(EVENT_REORDER, this.parentNode)
];
}
}
/**
* Remove or hide mutation events coalescence testing.
*/
function removeOrHideCoalescenceBase(aChildID, aParentID,
aChildAction, aParentAction,
aPerformActionOnChildInTheFirstPlace)
{
this.__proto__ = new coalescenceBase(aChildAction, aParentAction,
aPerformActionOnChildInTheFirstPlace);
this.init = function removeOrHideCoalescenceBase_init()
{
this.childNode = getNode(aChildID);
this.parentNode = getNode(aParentID);
this.child = getAccessible(this.childNode);
this.parent = getAccessible(this.parentNode);
this.hostNode = this.parentNode.parentNode;
}
// Initalization
this.init();
this.initSequence();
}
////////////////////////////////////////////////////////////////////////////
// Invokers
/**
* Remove child node and then its parent node from DOM tree.
*/
function removeChildNParent(aChildID, aParentID)
{
this.__proto__ = new removeOrHideCoalescenceBase(aChildID, aParentID,
kRemoveElm, kRemoveElm,
true);
}
/**
* Remove parent node and then its child node from DOM tree.
*/
function removeParentNChild(aChildID, aParentID)
{
this.__proto__ = new removeOrHideCoalescenceBase(aChildID, aParentID,
kRemoveElm, kRemoveElm,
false);
}
/**
* Hide child node and then its parent node.
*/
function hideChildNParent(aChildID, aParentID)
{
this.__proto__ = new removeOrHideCoalescenceBase(aChildID, aParentID,
kHideElm, kHideElm,
true);
}
/**
* Hide parent node and then its child node.
*/
function hideParentNChild(aChildID, aParentID)
{
this.__proto__ = new removeOrHideCoalescenceBase(aChildID, aParentID,
kHideElm, kHideElm,
false);
}
/**
* Hide child node and then remove its parent node.
*/
function hideChildNRemoveParent(aChildID, aParentID)
{
this.__proto__ = new removeOrHideCoalescenceBase(aChildID, aParentID,
kHideElm, kRemoveElm,
true);
}
/**
* Hide parent node and then remove its child node.
*/
function hideParentNRemoveChild(aChildID, aParentID)
{
this.__proto__ = new removeOrHideCoalescenceBase(aChildID, aParentID,
kRemoveElm, kHideElm,
false);
}
/**
* Remove child node and then hide its parent node.
*/
function removeChildNHideParent(aChildID, aParentID)
{
this.__proto__ = new removeOrHideCoalescenceBase(aChildID, aParentID,
kRemoveElm, kHideElm,
true);
}
/**
* Remove parent node and then hide its child node.
*/
function removeParentNHideChild(aChildID, aParentID)
{
this.__proto__ = new removeOrHideCoalescenceBase(aChildID, aParentID,
kHideElm, kRemoveElm,
false);
}
/**
* Create and append parent node and create and append child node to it.
*/
function addParentNChild(aHostID, aPerformActionOnChildInTheFirstPlace)
{
this.init = function addParentNChild_init()
{
this.hostNode = getNode(aHostID);
this.parentNode = document.createElement("select");
this.childNode = document.createElement("option");
this.childNode.textContent = "testing";
}
this.__proto__ = new coalescenceBase(kAddElm, kAddElm,
aPerformActionOnChildInTheFirstPlace);
this.init();
this.initSequence();
}
/**
* Show parent node and show child node to it.
*/
function showParentNChild(aParentID, aChildID,
aPerformActionOnChildInTheFirstPlace)
{
this.init = function showParentNChild_init()
{
this.parentNode = getNode(aParentID);
this.hostNode = this.parentNode.parentNode;
this.childNode = getNode(aChildID);
}
this.__proto__ = new coalescenceBase(kShowElm, kShowElm,
aPerformActionOnChildInTheFirstPlace);
this.init();
this.initSequence();
}
/**
* Create and append child node to the DOM and then show parent node.
*/
function showParentNAddChild(aParentID,
aPerformActionOnChildInTheFirstPlace)
{
this.init = function showParentNAddChild_init()
{
this.parentNode = getNode(aParentID);
this.hostNode = this.parentNode.parentNode;
this.childNode = document.createElement("option");
this.childNode.textContent = "testing";
}
this.__proto__ = new coalescenceBase(kAddElm, kShowElm,
aPerformActionOnChildInTheFirstPlace);
this.init();
this.initSequence();
}
/**
* Remove children and parent
*/
function removeGrandChildrenNHideParent(aChild1Id, aChild2Id, aParentId)
{
this.child1 = getNode(aChild1Id);
this.child2 = getNode(aChild2Id);
this.parent = getNode(aParentId);
this.eventSeq = [
new invokerChecker(EVENT_HIDE, getAccessible(aParentId)),
new invokerChecker(EVENT_REORDER, getNode(aParentId).parentNode),
new unexpectedInvokerChecker(EVENT_HIDE, getAccessible(aChild1Id)),
new unexpectedInvokerChecker(EVENT_HIDE, getAccessible(aChild2Id)),
new unexpectedInvokerChecker(EVENT_REORDER, getAccessible(aParentId))
];
this.invoke = function removeGrandChildrenNHideParent_invoke()
{
this.child1.parentNode.removeChild(this.child1);
this.child2.parentNode.removeChild(this.child2);
this.parent.hidden = true;
}
this.getID = function removeGrandChildrenNHideParent_getID() {
return "remove grand children of different parents and then hide their grand parent";
}
}
/**
* Remove a child, and then its parent.
*/
function test3()
{
this.o = getAccessible("t3_o");
this.ofc = getAccessible("t3_o").firstChild;
this.eventSeq = [
new invokerChecker(EVENT_HIDE, this.o),
new invokerChecker(EVENT_REORDER, "t3_lb"),
new unexpectedInvokerChecker(EVENT_HIDE, this.ofc),
new unexpectedInvokerChecker(EVENT_REORDER, this.o)
];
this.invoke = function test3_invoke()
{
getNode("t3_o").textContent = "";
getNode("t3_lb").removeChild(getNode("t3_o"));
}
this.finalCheck = function test3_finalCheck()
{
testIsDefunct(this.o);
testIsDefunct(this.ofc);
}
this.getID = function test3_getID() {
return "remove a child, and then its parent";
}
}
/**
* Remove children, and then a parent of 2nd child.
*/
function test4()
{
this.o1 = getAccessible("t4_o1");
this.o1fc = this.o1.firstChild;
this.o2 = getAccessible("t4_o2");
this.o2fc = this.o2.firstChild;
this.eventSeq = [
new invokerChecker(EVENT_HIDE, this.o1fc),
new invokerChecker(EVENT_HIDE, this.o2),
new invokerChecker(EVENT_REORDER, "t4_lb"),
new unexpectedInvokerChecker(EVENT_HIDE, this.o2fc),
new unexpectedInvokerChecker(EVENT_REORDER, this.o1),
new unexpectedInvokerChecker(EVENT_REORDER, this.o2)
];
this.invoke = function test4_invoke()
{
getNode("t4_o1").textContent = "";
getNode("t4_o2").textContent = "";
getNode("t4_lb").removeChild(getNode("t4_o2"));
}
this.finalCheck = function test4_finalCheck()
{
testIsDefunct(this.o1fc);
testIsDefunct(this.o2);
testIsDefunct(this.o2fc);
}
this.getID = function test4_getID() {
return "remove children, and then a parent of 2nd child";
}
}
/**
* Remove a child, remove a parent sibling, remove the parent
*/
function test5()
{
this.o = getAccessible("t5_o");
this.ofc = this.o.firstChild;
this.b = getAccessible("t5_b");
this.lb = getAccessible("t5_lb");
this.eventSeq = [
new invokerChecker(EVENT_HIDE, this.b),
new invokerChecker(EVENT_HIDE, this.o),
new invokerChecker(EVENT_REORDER, "t5"),
new unexpectedInvokerChecker(EVENT_HIDE, this.ofc),
new unexpectedInvokerChecker(EVENT_REORDER, this.o),
new unexpectedInvokerChecker(EVENT_REORDER, this.lb)
];
this.invoke = function test5_invoke()
{
getNode("t5_o").textContent = "";
getNode("t5").removeChild(getNode("t5_b"));
getNode("t5_lb").removeChild(getNode("t5_o"));
}
this.finalCheck = function test5_finalCheck()
{
testIsDefunct(this.ofc);
testIsDefunct(this.o);
testIsDefunct(this.b);
}
this.getID = function test5_getID() {
return "remove a child, remove a parent sibling, remove the parent";
}
}
/**
* Insert accessibles with a child node moved by aria-owns
* Markup:
* <div id="t6_fc">
* <div id="t6_owns"></div>
* </div>
* <div id="t6_sc" aria-owns="t6_owns"></div>
*/
function test6()
{
this.parent = getNode("t6");
this.fc = document.createElement("div");
this.fc.setAttribute("id", "t6_fc");
this.owns = document.createElement("div");
this.owns.setAttribute("id", "t6_owns");
this.sc = document.createElement("div");
this.sc.setAttribute("id", "t6_sc");
this.eventSeq = [
new invokerChecker(EVENT_SHOW, this.fc),
new invokerChecker(EVENT_SHOW, this.sc),
new invokerChecker(EVENT_REORDER, this.parent),
new unexpectedInvokerChecker(EVENT_REORDER, this.fc),
new unexpectedInvokerChecker(EVENT_REORDER, this.sc),
new unexpectedInvokerChecker(EVENT_HIDE, this.owns),
new unexpectedInvokerChecker(EVENT_SHOW, this.owns)
];
this.invoke = function test6_invoke()
{
getNode("t6").appendChild(this.fc);
getNode("t6_fc").appendChild(this.owns);
getNode("t6").appendChild(this.sc);
getNode("t6_sc").setAttribute("aria-owns", "t6_owns");
};
this.getID = function test6_getID() {
return "Insert accessibles with a child node moved by aria-owns";
};
}
/**
* Insert text nodes under direct and grand children, and then hide
* their container by means of aria-owns.
*
* Markup:
* <div id="t7_moveplace" aria-owns="t7_c"></div>
* <div id="t7_c">
* <div id="t7_c_directchild">ha</div>
* <div><div id="t7_c_grandchild">ha</div></div>
* </div>
*/
function test7()
{
this.eventSeq = [
new invokerChecker(EVENT_HIDE, getNode('t7_c')),
new invokerChecker(EVENT_SHOW, getNode('t7_c')),
new invokerChecker(EVENT_REORDER, getNode('t7')),
new unexpectedInvokerChecker(EVENT_REORDER, getNode('t7_c_directchild')),
new unexpectedInvokerChecker(EVENT_REORDER, getNode('t7_c_grandchild')),
new unexpectedInvokerChecker(EVENT_SHOW, () => getNode('t7_c_directchild').firstChild),
new unexpectedInvokerChecker(EVENT_SHOW, () => getNode('t7_c_grandchild').firstChild)
];
this.invoke = function test7_invoke()
{
getNode('t7_c_directchild').textContent = 'ha';
getNode('t7_c_grandchild').textContent = 'ha';
getNode('t7_moveplace').setAttribute('aria-owns', 't7_c');
};
this.getID = function test7_getID() {
return "Show child accessibles and then hide their container";
};
}
/**
* Move a node by aria-owns from right to left in the tree, so that
* the eventing looks this way:
* reorder for 't8_c1'
* hide for 't8_c1_child'
* show for 't8_c2_moved'
* reorder for 't8_c2'
* hide for 't8_c2_moved'
*
* The hide event should be delivered before the paired show event.
*/
function test8()
{
this.eventSeq = [
new invokerChecker(EVENT_HIDE, getNode('t8_c1_child')),
new invokerChecker(EVENT_HIDE, 't8_c2_moved'),
new invokerChecker(EVENT_SHOW, 't8_c2_moved'),
new invokerChecker(EVENT_REORDER, 't8_c2'),
new invokerChecker(EVENT_REORDER, 't8_c1'),
];
this.invoke = function test8_invoke()
{
// Remove a node from 't8_c1' container to give the event tree a
// desired structure (the 't8_c1' container node goes first in the event
// tree)
getNode('t8_c1_child').remove();
// then move 't8_c2_moved' from 't8_c2' to 't8_c1'.
getNode('t8_c1').setAttribute('aria-owns', 't8_c2_moved');
};
this.getID = function test8_getID() {
return "Move a node by aria-owns to left within the tree";
};
}
/**
* Move 't9_c3_moved' node under 't9_c2_moved', and then move 't9_c2_moved'
* node by aria-owns (same as test10 but has different aria-owns
* ordering), the eventing looks same way as in test10:
* reorder for 't9_c1'
* hide for 't9_c1_child'
* show for 't9_c2_moved'
* reorder for 't9_c2'
* hide for 't9_c2_child'
* hide for 't9_c2_moved'
* reorder for 't9_c3'
* hide for 't9_c3_moved'
*
* The hide events for 't9_c2_moved' and 't9_c3_moved' should be delivered
* before the show event for 't9_c2_moved'.
*/
function test9()
{
this.eventSeq = [
new invokerChecker(EVENT_HIDE, getNode('t9_c1_child')),
new invokerChecker(EVENT_HIDE, getNode('t9_c2_child')),
new invokerChecker(EVENT_HIDE, 't9_c3_moved'),
new invokerChecker(EVENT_HIDE, 't9_c2_moved'),
new invokerChecker(EVENT_SHOW, 't9_c2_moved'),
new invokerChecker(EVENT_REORDER, 't9_c3'),
new invokerChecker(EVENT_REORDER, 't9_c2'),
new invokerChecker(EVENT_REORDER, 't9_c1'),
new unexpectedInvokerChecker(EVENT_SHOW, 't9_c3_moved')
];
this.invoke = function test9_invoke()
{
// Remove child nodes from 't9_c1' and 't9_c2' containers to give
// the event tree a needed structure ('t9_c1' and 't9_c2' nodes go
// first in the event tree),
getNode('t9_c1_child').remove();
getNode('t9_c2_child').remove();
// then do aria-owns magic.
getNode('t9_c2_moved').setAttribute('aria-owns', 't9_c3_moved');
getNode('t9_c1').setAttribute('aria-owns', 't9_c2_moved');
};
this.getID = function test9_getID() {
return "Move node #1 by aria-owns and then move node #2 into node #1";
};
}
/**
* Move a node 't10_c3_moved' by aria-owns under a node 't10_c2_moved',
* moved by under 't10_1', so that the eventing looks this way:
* reorder for 't10_c1'
* hide for 't10_c1_child'
* show for 't10_c2_moved'
* reorder for 't10_c2'
* hide for 't10_c2_child'
* hide for 't10_c2_moved'
* reorder for 't10_c3'
* hide for 't10_c3_moved'
*
* The hide events for 't10_c2_moved' and 't10_c3_moved' should be delivered
* before the show event for 't10_c2_moved'.
*/
function test10()
{
this.eventSeq = [
new invokerChecker(EVENT_HIDE, getNode('t10_c1_child')),
new invokerChecker(EVENT_HIDE, getNode('t10_c2_child')),
new invokerChecker(EVENT_HIDE, getNode('t10_c2_moved')),
new invokerChecker(EVENT_HIDE, getNode('t10_c3_moved')),
new invokerChecker(EVENT_SHOW, getNode('t10_c2_moved')),
new invokerChecker(EVENT_REORDER, 't10_c2'),
new invokerChecker(EVENT_REORDER, 't10_c1'),
new invokerChecker(EVENT_REORDER, 't10_c3')
];
this.invoke = function test10_invoke()
{
// Remove child nodes from 't10_c1' and 't10_c2' containers to give
// the event tree a needed structure ('t10_c1' and 't10_c2' nodes go first
// in the event tree),
getNode('t10_c1_child').remove();
getNode('t10_c2_child').remove();
// then do aria-owns stuff.
getNode('t10_c1').setAttribute('aria-owns', 't10_c2_moved');
getNode('t10_c2_moved').setAttribute('aria-owns', 't10_c3_moved');
};
this.getID = function test10_getID() {
return "Move a node by aria-owns into a node moved by aria-owns to left within the tree";
};
}
/**
* Move a node by aria-owns from right to left in the tree, and then
* move its parent too by aria-owns. No hide event should be fired for
* original node.
*/
function test11()
{
this.eventSeq = [
new invokerChecker(EVENT_HIDE, getNode('t11_c1_child')),
new invokerChecker(EVENT_HIDE, getNode('t11_c2')),
new orderChecker(),
new asyncInvokerChecker(EVENT_SHOW, 't11_c2_child'),
new asyncInvokerChecker(EVENT_SHOW, 't11_c2'),
new orderChecker(),
new invokerChecker(EVENT_REORDER, 't11'),
new unexpectedInvokerChecker(EVENT_HIDE, 't11_c2_child'),
new unexpectedInvokerChecker(EVENT_REORDER, 't11_c1'),
new unexpectedInvokerChecker(EVENT_REORDER, 't11_c2'),
new unexpectedInvokerChecker(EVENT_REORDER, 't11_c3')
];
this.invoke = function test11_invoke()
{
// Remove a node from 't11_c1' container to give the event tree a
// desired structure (the 't11_c1' container node goes first in
// the event tree),
getNode('t11_c1_child').remove();
// then move 't11_c2_moved' from 't11_c2' to 't11_c1', and then move
// 't11_c2' to 't11_c3'.
getNode('t11_c1').setAttribute('aria-owns', 't11_c2_child');
getNode('t11_c3').setAttribute('aria-owns', 't11_c2');
};
this.getID = function test11_getID() {
return "Move a node by aria-owns to left within the tree";
};
}
////////////////////////////////////////////////////////////////////////////
// Do tests.
gA11yEventDumpToConsole = true; // debug stuff
//enableLogging("eventTree");
var gQueue = null;
function doTests()
{
gQueue = new eventQueue();
gQueue.push(new removeChildNParent("option1", "select1"));
gQueue.push(new removeParentNChild("option2", "select2"));
gQueue.push(new hideChildNParent("option3", "select3"));
gQueue.push(new hideParentNChild("option4", "select4"));
gQueue.push(new hideChildNRemoveParent("option5", "select5"));
gQueue.push(new hideParentNRemoveChild("option6", "select6"));
gQueue.push(new removeChildNHideParent("option7", "select7"));
gQueue.push(new removeParentNHideChild("option8", "select8"));
gQueue.push(new addParentNChild("testContainer", false));
gQueue.push(new addParentNChild("testContainer", true));
gQueue.push(new showParentNChild("select9", "option9", false));
gQueue.push(new showParentNChild("select10", "option10", true));
gQueue.push(new showParentNAddChild("select11", false));
gQueue.push(new showParentNAddChild("select12", true));
gQueue.push(new removeGrandChildrenNHideParent("t1_child1", "t1_child2", "t1_parent"));
gQueue.push(new test3());
gQueue.push(new test4());
gQueue.push(new test5());
gQueue.push(new test6());
gQueue.push(new test7());
gQueue.push(new test8());
gQueue.push(new test9());
gQueue.push(new test10());
gQueue.push(new test11());
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=513213"
title="coalesce events when new event is appended to the queue">
Mozilla Bug 513213
</a><br>
<a target="_blank"
title="Rework accessible tree update code"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
Mozilla Bug 570275
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="testContainer">
<select id="select1">
<option id="option1">option</option>
</select>
<select id="select2">
<option id="option2">option</option>
</select>
<select id="select3">
<option id="option3">option</option>
</select>
<select id="select4">
<option id="option4">option</option>
</select>
<select id="select5">
<option id="option5">option</option>
</select>
<select id="select6">
<option id="option6">option</option>
</select>
<select id="select7">
<option id="option7">option</option>
</select>
<select id="select8">
<option id="option8">option</option>
</select>
<select id="select9" style="display: none">
<option id="option9" style="display: none">testing</option>
</select>
<select id="select10" style="display: none">
<option id="option10" style="display: none">testing</option>
</select>
<select id="select11" style="display: none"></select>
<select id="select12" style="display: none"></select>
</div>
<div id="testContainer2">
<div id="t1_parent">
<div id="t1_mid1"><div id="t1_child1"></div></div>
<div id="t1_mid2"><div id="t1_child2"></div></div>
</div>
</div>
<div id="t3">
<div role="listbox" id="t3_lb">
<div role="option" id="t3_o">opt</div>
</div>
</div>
<div id="t4">
<div role="listbox" id="t4_lb">
<div role="option" id="t4_o1">opt1</div>
<div role="option" id="t4_o2">opt2</div>
</div>
</div>
<div id="t5">
<div role="button" id="t5_b">btn</div>
<div role="listbox" id="t5_lb">
<div role="option" id="t5_o">opt</div>
</div>
</div>
<div id="t6">
</div>
<div id="t7">
<div id="t7_moveplace"></div>
<div id="t7_c">
<div><div id="t7_c_grandchild"></div></div>
<div id="t7_c_directchild"></div>
</div>
</div>
<div id="t8">
<div id="t8_c1"><div id="t8_c1_child"></div></div>
<div id="t8_c2">
<div id="t8_c2_moved"></div>
</div>
</div>
<div id="t9">
<div id="t9_c1"><div id="t9_c1_child"></div></div>
<div id="t9_c2">
<div id="t9_c2_child"></div>
<div id="t9_c2_moved"></div>
</div>
<div id="t9_c3">
<div id="t9_c3_moved"></div>
</div>
</div>
<div id="t10">
<div id="t10_c1"><div id="t10_c1_child"></div></div>
<div id="t10_c2">
<div id="t10_c2_child"></div>
<div id="t10_c2_moved"></div>
</div>
<div id="t10_c3">
<div id="t10_c3_moved"></div>
</div>
</div>
<div id="t11">
<div id="t11_c1"><div id="t11_c1_child"></div></div>
<div id="t11_c2"><div id="t11_c2_child"></div></div>
<div id="t11_c3"></div>
</div>
</body>
</html>

View file

@ -0,0 +1,139 @@
<html>
<head>
<title>Context menu tests</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
////////////////////////////////////////////////////////////////////////////
// Invokers
function showContextMenu(aID)
{
this.DOMNode = getNode(aID);
this.eventSeq = [
new invokerChecker(EVENT_MENUPOPUP_START, getContextMenuNode()),
];
this.invoke = function showContextMenu_invoke()
{
synthesizeMouse(this.DOMNode, 4, 4, { type: "contextmenu", button: 2 });
}
this.getID = function showContextMenu_getID()
{
return "show context menu";
}
}
function selectMenuItem()
{
this.eventSeq = [
new invokerChecker(EVENT_FOCUS, getFocusedMenuItem)
];
this.invoke = function selectMenuItem_invoke()
{
synthesizeKey("VK_DOWN", { });
}
this.getID = function selectMenuItem_getID()
{
return "select first menuitem";
}
}
function closeContextMenu(aID)
{
this.eventSeq = [
new invokerChecker(EVENT_MENUPOPUP_END,
getAccessible(getContextMenuNode()))
];
this.invoke = function closeContextMenu_invoke()
{
synthesizeKey("VK_ESCAPE", { });
}
this.getID = function closeContextMenu_getID()
{
return "close context menu";
}
}
function getContextMenuNode()
{
return getRootAccessible().DOMDocument.
getElementById("contentAreaContextMenu");
}
function getFocusedMenuItem()
{
var menu = getAccessible(getAccessible(getContextMenuNode()));
for (var idx = 0; idx < menu.childCount; idx++) {
var item = menu.getChildAt(idx);
if (hasState(item, STATE_FOCUSED))
return getAccessible(item);
}
return null;
}
////////////////////////////////////////////////////////////////////////////
// Do tests
var gQueue = null;
//gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true;
function doTests()
{
gQueue = new eventQueue();
gQueue.push(new showContextMenu("input"));
gQueue.push(new selectMenuItem());
gQueue.push(new closeContextMenu());
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=580535"
title="Broken accessibility in context menus">
Mozilla Bug 580535
</a><br>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<input id="input">
<div id="eventdump"></div>
</body>
</html>

View file

@ -0,0 +1,85 @@
<html>
<head>
<title>Accessible description change event testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript">
////////////////////////////////////////////////////////////////////////////
// Invokers
function setAttr(aID, aAttr, aValue, aChecker)
{
this.eventSeq = [ aChecker ];
this.invoke = function setAttr_invoke()
{
getNode(aID).setAttribute(aAttr, aValue);
}
this.getID = function setAttr_getID()
{
return "set attr '" + aAttr + "', value '" + aValue + "'";
}
}
////////////////////////////////////////////////////////////////////////////
// Do tests
//gA11yEventDumpToConsole = true; // debuggin
var gQueue = null;
function doTests()
{
gQueue = new eventQueue();
gQueue.push(new setAttr("tst1", "aria-describedby", "display",
new invokerChecker(EVENT_DESCRIPTION_CHANGE, "tst1")));
gQueue.push(new setAttr("tst1", "title", "title",
new unexpectedInvokerChecker(EVENT_DESCRIPTION_CHANGE, "tst1")));
gQueue.push(new setAttr("tst2", "title", "title",
new invokerChecker(EVENT_NAME_CHANGE, "tst2")));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=991969"
title="Event not fired when description changes">
Bug 991969
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<button id="tst1">btn1</button>
<button id="tst2">btn2</button>
<div id="eventdump"></div>
</body>
</html>

View file

@ -0,0 +1,360 @@
<html>
<head>
<title>Accessible events testing for document</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
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="../states.js"></script>
<script type="application/javascript">
// Front end stuff sometimes likes to stuff things in the hidden window(s)
// in which case there's accessibles for that content.
Components.utils.import("resource://gre/modules/Services.jsm");
// Force the creation of an accessible for the hidden window's document.
var doc = Services.appShell.hiddenDOMWindow.document;
gAccService.getAccessibleFor(doc);
// The private hidden window will be lazily created that's why we need to do
// it here *before* loading '../events.js' or else we'll have a duplicate
// reorder event.
var privateDoc = Services.appShell.hiddenPrivateDOMWindow.document;
// Force the creation of an accessible for the private hidden window's doc.
gAccService.getAccessibleFor(privateDoc);
</script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
////////////////////////////////////////////////////////////////////////////
// Invokers
function changeIframeSrc(aIdentifier, aURL)
{
this.DOMNode = getNode(aIdentifier);
this.eventSeq = [
new invokerChecker(EVENT_REORDER, getAccessible(this.DOMNode)),
new asyncInvokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, getIframeDoc)
];
this.invoke = function changeIframeSrc_invoke()
{
this.DOMNode.src = aURL;
}
this.finalCheck = function changeIframeSrc_finalCheck()
{
var accTree = {
role: ROLE_INTERNAL_FRAME,
children: [
{
role: ROLE_DOCUMENT,
name: aURL == "about:" ? "About:" : aURL
}
]
};
testAccessibleTree(this.DOMNode, accTree);
}
this.getID = function changeIframeSrc_getID()
{
return "change iframe src on " + aURL;
}
function getIframeDoc()
{
return getAccessible(getNode(aIdentifier).contentDocument);
}
}
const kHide = 1;
const kShow = 2;
const kRemove = 3;
function morphIFrame(aIdentifier, aAction)
{
this.DOMNode = getNode(aIdentifier);
this.IFrameContainerDOMNode = this.DOMNode.parentNode;
this.eventSeq = [];
var checker = null;
if (aAction == kShow)
checker = new invokerChecker(EVENT_SHOW, this.DOMNode);
else
checker = new invokerChecker(EVENT_HIDE, this.DOMNode);
this.eventSeq.push(checker);
var reorderChecker =
new invokerChecker(EVENT_REORDER, this.IFrameContainerDOMNode);
this.eventSeq.push(reorderChecker);
this.invoke = function morphIFrame_invoke()
{
if (aAction == kHide) {
this.DOMNode.style.display = "none";
} else if (aAction == kShow) {
this.DOMNode.style.display = "block";
} else {
this.IFrameContainerDOMNode.removeChild(this.DOMNode);
}
}
this.finalCheck = function morphIFrame_finalCheck()
{
var accTree = {
role: ROLE_SECTION,
children: (aAction == kHide || aAction == kRemove) ? [ ] :
[
{
role: ROLE_INTERNAL_FRAME,
children: [
{ role: ROLE_DOCUMENT }
]
}
]
};
testAccessibleTree(this.IFrameContainerDOMNode, accTree);
}
this.getID = function morphIFrame_getID()
{
if (aAction == kRemove)
return "remove iframe";
return "change display style of iframe to " +
((aAction == kHide) ? "none" : "block");
}
}
function makeIFrameVisible(aID)
{
this.DOMNode = getNode(aID);
this.eventSeq = [
new invokerChecker(EVENT_REORDER, this.DOMNode.parentNode)
];
this.invoke = function makeIFrameVisible_invoke()
{
this.DOMNode.style.visibility = "visible";
}
this.getID = function makeIFrameVisible_getID()
{
return "The accessible for DOM document loaded before it's shown shouldn't have busy state.";
}
}
function openDialogWnd(aURL)
{
// Get application root accessible.
var docAcc = getAccessible(document);
while (docAcc) {
this.mRootAcc = docAcc;
try {
docAcc = docAcc.parent;
} catch (e) {
ok(false, "Can't get parent for " + prettyName(docAcc));
throw e;
}
}
this.eventSeq = [
new invokerChecker(EVENT_REORDER, this.mRootAcc)
];
this.invoke = function openDialogWnd_invoke()
{
this.mDialog = window.openDialog(aURL);
}
this.finalCheck = function openDialogWnd_finalCheck()
{
this.finalCheckImpl();
}
this.finalCheckImpl = function openDialogWnd_finalCheckImpl()
{
var accTree = {
role: ROLE_APP_ROOT,
children: [
{
role: ROLE_CHROME_WINDOW
},
{
role: ROLE_CHROME_WINDOW
},
{
role: ROLE_CHROME_WINDOW
},
{
role: ROLE_CHROME_WINDOW
}
]
};
testAccessibleTree(this.mRootAcc, accTree);
var dlgDoc = this.mDialog.document;
ok(isAccessibleInCache(dlgDoc),
"The document accessible for '" + aURL + "' is not in cache!");
this.mDialog.close();
// close() is asynchronous.
SimpleTest.executeSoon(function() {
ok(!isAccessibleInCache(dlgDoc),
"The document accessible for '" + aURL + "' is in cache still!");
});
}
this.getID = function openDialogWnd_getID()
{
return "open dialog '" + aURL + "'";
}
}
function openWndShutdownDoc()
{
this.__proto__ =
new openDialogWnd("../events/docload_wnd.html");
var thisObj = this;
var docChecker = {
type: EVENT_HIDE,
get target()
{
var iframe = this.invoker.mDialog.document.getElementById("iframe");
this.invoker.iframeDoc = iframe.contentDocument;
return iframe;
},
get targetDescr()
{
return "inner iframe of docload_wnd.html document";
},
invoker: thisObj
};
this.eventSeq.push(docChecker);
this.finalCheck = function openWndShutdownDoc_finalCheck()
{
// After timeout after event hide for iframe was handled the document
// accessible for iframe's document is in cache still.
ok(!isAccessibleInCache(this.iframeDoc),
"The document accessible for iframe is in cache still after iframe hide!");
this.finalCheckImpl();
// After the window is closed all alive subdocument accessibles should
// be shut down.
ok(!isAccessibleInCache(this.iframeDoc),
"The document accessible for iframe is in cache still!");
}
}
////////////////////////////////////////////////////////////////////////////
// Do tests
var gQueue = null;
// Debug stuff.
// gA11yEventDumpID = "eventdump";
//gA11yEventDumpToConsole = true;
function doTests()
{
gQueue = new eventQueue();
gQueue.push(new changeIframeSrc("iframe", "about:"));
gQueue.push(new changeIframeSrc("iframe", "about:buildconfig"));
gQueue.push(new morphIFrame("iframe", kHide));
gQueue.push(new morphIFrame("iframe", kShow));
gQueue.push(new morphIFrame("iframe", kRemove));
gQueue.push(new makeIFrameVisible("iframe2"));
gQueue.push(new openDialogWnd("about:"));
gQueue.push(new openWndShutdownDoc());
gQueue.onFinish = doLastCallTests;
gQueue.invoke(); // Will call SimpleTest.finish();
}
function doLastCallTests()
{
//////////////////////////////////////////////////////////////////////////
// makeIFrameVisible() test, part2
// The document shouldn't have busy state (the DOM document was loaded
// before its accessible was created). Do this test lately to make sure
// the content of document accessible was created initially, prior to this
// the document accessible keeps busy state. The initial creation happens
// asynchronously after document creation, there are no events we could
// use to catch it.
var iframeDoc = getAccessible("iframe2").firstChild;
testStates(iframeDoc, 0, 0, STATE_BUSY);
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=420845"
title="Fire event_reorder on any embedded frames/iframes whos document has just loaded">
Mozilla Bug 420845
</a><br>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=506206"
title="Fire event_reorder application root accessible">
Mozilla Bug 506206
</a><br>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=566103"
title="Reorganize accessible document handling">
Mozilla Bug 566103
</a><br>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=571459"
title="Shutdown document accessible when presshell goes away">
Mozilla Bug 571459
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=658185"
title="The DOM document loaded before it's shown shouldn't have busy state">
Mozilla Bug 658185
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=754165"
title="Fire document load events on iframes too">
Mozilla Bug 754165
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="testContainer"><iframe id="iframe"></iframe></div>
<div id="testContainer2"><iframe id="iframe2" src="about:" style="visibility: hidden;"></iframe></div>
<div id="eventdump"></div>
</body>
</html>

View file

@ -0,0 +1,243 @@
<?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 Loading Document Events Test.">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../browser.js"></script>
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Invoker checkers.
function stateBusyChecker(aIsEnabled)
{
this.type = EVENT_STATE_CHANGE;
this.__defineGetter__("target", currentTabDocument);
this.check = function stateBusyChecker_check(aEvent)
{
var event = null;
try {
var event = aEvent.QueryInterface(nsIAccessibleStateChangeEvent);
} catch (e) {
ok(false, "State change event was expected");
}
if (!event)
return;
is(event.state, STATE_BUSY, "Wrong state of statechange event.");
is(event.isEnabled, aIsEnabled,
"Wrong value of state of statechange event");
testStates(event.accessible, (aIsEnabled ? STATE_BUSY : 0), 0,
(aIsEnabled ? 0 : STATE_BUSY), 0);
}
}
function documentReloadChecker(aIsFromUserInput)
{
this.type = EVENT_DOCUMENT_RELOAD;
this.__defineGetter__("target", currentTabDocument);
this.check = function documentReloadChecker_check(aEvent)
{
is(aEvent.isFromUserInput, aIsFromUserInput,
"Wrong value of isFromUserInput");
}
}
////////////////////////////////////////////////////////////////////////////
// Invokers.
/**
* Load URI.
*/
function loadURIInvoker(aURI)
{
this.invoke = function loadURIInvoker_invoke()
{
tabBrowser().loadURI(aURI);
}
this.eventSeq = [
// We don't expect state change event for busy true since things happen
// quickly and it's coalesced.
new asyncInvokerChecker(EVENT_REORDER, currentBrowser),
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, currentTabDocument),
new stateBusyChecker(false)
];
this.getID = function loadURIInvoker_getID()
{
return "load uri " + aURI;
}
}
/**
* Load the document having sub document. No document loading events for
* nested document.
*/
function loadNestedDocURIInvoker(aNestedDocURI)
{
this.__proto__ = new loadURIInvoker(aNestedDocURI);
// Remove reorder event checker since the event is likely coalesced by
// reorder event on Firefox UI (refer to bug 759670 for details).
this.eventSeq.shift();
this.unexpectedEventSeq = [
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, getNestedDoc),
new invokerChecker(EVENT_STATE_CHANGE, getNestedDoc)
];
function getNestedDoc()
{
var iframeNodes = currentTabDocument().getElementsByTagName("iframe");
return iframeNodes && iframeNodes.length > 0 ?
iframeNodes[0].firstChild : null;
}
}
/**
* Reload the page by F5 (isFromUserInput flag is true).
*/
function userReloadInvoker()
{
this.invoke = function userReloadInvoker_invoke()
{
synthesizeKey("VK_F5", {}, browserWindow());
}
this.eventSeq = [
new documentReloadChecker(true),
new asyncInvokerChecker(EVENT_REORDER, currentBrowser),
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, currentTabDocument),
new stateBusyChecker(false)
];
this.getID = function userReloadInvoker_getID()
{
return "user reload page";
}
}
/**
* Reload the page (isFromUserInput flag is false).
*/
function reloadInvoker()
{
this.invoke = function reloadInvoker_invoke()
{
tabBrowser().reload();
}
this.eventSeq = [
new documentReloadChecker(false),
new asyncInvokerChecker(EVENT_REORDER, currentBrowser),
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, currentTabDocument),
new stateBusyChecker(false)
];
this.getID = function reloadInvoker_getID()
{
return "reload page";
}
}
/**
* Load wrong URI what results in error page loading.
*/
function loadErrorPageInvoker(aURL, aURLDescr)
{
this.invoke = function loadErrorPageInvoker_invoke()
{
tabBrowser().loadURI(aURL);
}
this.eventSeq = [
// We don't expect state change for busy true, load stopped events since
// things happen quickly and it's coalesced.
new asyncInvokerChecker(EVENT_REORDER, currentBrowser),
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, currentTabDocument),
new stateBusyChecker(false)
];
this.getID = function loadErrorPageInvoker_getID()
{
return "load error page: '" + aURLDescr + "'";
}
}
////////////////////////////////////////////////////////////////////////////
// Tests
//gA11yEventDumpToConsole = true; // debug
//gA11yEventDumpFeature = "parentchain:reorder";
var gQueue = null;
function doTests()
{
gQueue = new eventQueue();
var dataURL =
"data:text/html,<html><body><iframe src='http://example.com'></iframe></body></html>";
gQueue.push(new loadNestedDocURIInvoker(dataURL));
gQueue.push(new loadURIInvoker("about:"));
gQueue.push(new userReloadInvoker());
gQueue.push(new loadURIInvoker("about:mozilla"));
gQueue.push(new reloadInvoker());
gQueue.push(new loadErrorPageInvoker("www.wronguri.wronguri",
"Server not found"));
gQueue.push(new loadErrorPageInvoker("https://nocert.example.com:443",
"Untrusted Connection"));
gQueue.onFinish = function() { closeBrowserWindow(); }
gQueue.invoke();
}
SimpleTest.waitForExplicitFinish();
openBrowserWindow(doTests);
]]>
</script>
<vbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=566103"
title=" reorganize accessible document handling">
Mozilla Bug 566103
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=754165"
title="Fire document load events on iframes too">
Mozilla Bug 754165
</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox id="eventdump"></vbox>
</vbox>
</window>

View file

@ -0,0 +1,83 @@
<html>
<head>
<title>Accessible events testing for ARIA document</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
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="../states.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
////////////////////////////////////////////////////////////////////////////
// Invokers
function showARIADialog(aID)
{
this.dialogNode = getNode(aID);
this.eventSeq = [
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, this.dialogNode)
];
this.invoke = function showARIADialog_invoke()
{
this.dialogNode.style.display = "block";
}
this.getID = function showARIADialog_getID()
{
return "show ARIA dialog";
}
}
////////////////////////////////////////////////////////////////////////////
// Do tests
var gQueue = null;
// Debug stuff.
//gA11yEventDumpToConsole = true;
function doTests()
{
gQueue = new eventQueue();
gQueue.push(new showARIADialog("dialog"));
gQueue.push(new showARIADialog("document"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=759833"
title="ARIA documents should fire document loading events">
Mozilla Bug 759833
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div role="dialog" id="dialog" style="display: none;">It's a dialog</div>
<div role="document" id="document" style="display: none;">It's a document</div>
</body>
</html>

View file

@ -0,0 +1,110 @@
<html>
<head>
<title>Accessible drag and drop event testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../attributes.js"></script>
<script type="application/javascript">
/**
* Do tests.
*/
var gQueue = null;
// aria grabbed invoker
function changeGrabbed(aNodeOrID, aGrabValue)
{
this.DOMNode = getNode(aNodeOrID);
this.invoke = function changeGrabbed_invoke() {
if (aGrabValue != undefined) {
this.DOMNode.setAttribute("aria-grabbed", aGrabValue);
}
}
this.check = function changeGrabbed_check() {
testAttrs(aNodeOrID, {"grabbed" : aGrabValue}, true);
}
this.getID = function changeGrabbed_getID() {
return prettyName(aNodeOrID) + " aria-grabbed changed";
}
}
// aria dropeffect invoker
function changeDropeffect(aNodeOrID, aDropeffectValue)
{
this.DOMNode = getNode(aNodeOrID);
this.invoke = function changeDropeffect_invoke() {
if (aDropeffectValue != undefined) {
this.DOMNode.setAttribute("aria-dropeffect", aDropeffectValue);
}
}
this.check = function changeDropeffect_check() {
testAttrs(aNodeOrID, {"dropeffect" : aDropeffectValue}, true);
}
this.getID = function changeDropeffect_getID() {
return prettyName(aNodeOrID) + " aria-dropeffect changed";
}
}
function doTests()
{
// Test aria attribute mutation events
gQueue = new eventQueue(nsIAccessibleEvent.EVENT_OBJECT_ATTRIBUTE_CHANGED);
var id="grabbable";
gQueue.push(new changeGrabbed(id, "true"));
gQueue.push(new changeGrabbed(id, "false"));
todo(false, "uncomment this test when 472142 is fixed.");
//gQueue.push(new changeGrabbed(id, "undefined"));
var id="dropregion";
gQueue.push(new changeDropeffect(id, "copy"));
gQueue.push(new changeDropeffect(id, "execute"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=510441"
title="Add support for nsIAccessibleEvent::OBJECT_ATTRIBUTE_CHANGED">
Mozilla Bug 510441
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="eventdump"></div>
<!-- ARIA grabbed -->
<div id="grabbable" role="button" aria-grabbed="foo">button</div>
<!-- ARIA dropeffect -->
<div id="dropregion" role="region" aria-dropeffect="none">button</div>
</body>
</html>

View file

@ -0,0 +1,77 @@
<html>
<head>
<title>Flush delayed events testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
SimpleTest.expectAssertions(0, 1);
var gFocusHandler = {
handleEvent: function(aEvent) {
switch (this.count) {
case 0:
is(aEvent.DOMNode, getNode("input1"),
"Focus event for input1 was expected!");
getAccessible("input2").takeFocus();
break;
case 1:
is(aEvent.DOMNode, getNode("input2"),
"Focus event for input2 was expected!");
unregisterA11yEventListener(EVENT_FOCUS, gFocusHandler);
SimpleTest.finish();
break;
default:
ok(false, "Wrong focus event!");
}
this.count++;
},
count: 0
};
function doTests()
{
registerA11yEventListener(EVENT_FOCUS, gFocusHandler);
getAccessible("input1").takeFocus();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=477551"
title="DocAccessible::FlushPendingEvents isn't robust">
Mozilla Bug 477551
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<input id="input1">
<input id="input2">
</body>
</html>

View file

@ -0,0 +1,120 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=429547
-->
<head>
<title>aria-activedescendant focus tests</title>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
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="../states.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
//gA11yEventDumpToConsole = true; // debugging
function changeARIAActiveDescendant(aID, aItemID)
{
this.eventSeq = [
new focusChecker(aItemID)
];
this.invoke = function changeARIAActiveDescendant_invoke()
{
getNode(aID).setAttribute("aria-activedescendant", aItemID);
}
this.getID = function changeARIAActiveDescendant_getID()
{
return "change aria-activedescendant on " + aItemID;
}
}
function insertItemNFocus(aID, aNewItemID)
{
this.eventSeq = [
new invokerChecker(EVENT_SHOW, aNewItemID),
new focusChecker(aNewItemID)
];
this.invoke = function insertItemNFocus_invoke()
{
var container = getNode(aID);
var itemNode = document.createElement("div");
itemNode.setAttribute("id", aNewItemID);
itemNode.textContent = aNewItemID;
container.appendChild(itemNode);
container.setAttribute("aria-activedescendant", aNewItemID);
}
this.getID = function insertItemNFocus_getID()
{
return "insert new node and focus it with ID: " + aNewItemID;
}
}
var gQueue = null;
function doTest()
{
gQueue = new eventQueue();
gQueue.push(new synthFocus("listbox", new focusChecker("item1")));
gQueue.push(new changeARIAActiveDescendant("listbox", "item2"));
gQueue.push(new changeARIAActiveDescendant("listbox", "item3"));
gQueue.push(new synthFocus("combobox_entry", new focusChecker("combobox_entry")));
gQueue.push(new changeARIAActiveDescendant("combobox", "combobox_option2"));
todo(false, "No focus for inserted element, bug 687011");
//gQueue.push(new insertItemNFocus("listbox", "item4"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=429547"
title="Support aria-activedescendant usage in nsIAccesible::TakeFocus()">
Mozilla Bug 429547
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=761102"
title="Focus may be missed when ARIA active-descendant is changed on active composite widget">
Mozilla Bug 761102
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div role="listbox" aria-activedescendant="item1" id="listbox" tabindex="1"
aria-owns="item3">
<div role="listitem" id="item1">item1</div>
<div role="listitem" id="item2">item2</div>
</div>
<div role="listitem" id="item3">item3</div>
<div role="combobox" id="combobox">
<input id="combobox_entry">
<ul>
<li role="option" id="combobox_option1">option1</li>
<li role="option" id="combobox_option2">option2</li>
</ul>
</div>
</body>
</html>

View file

@ -0,0 +1,518 @@
<?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"?>
<!-- Firefox searchbar -->
<?xml-stylesheet href="chrome://browser/content/browser.css"
type="text/css"?>
<!-- SeaMonkey searchbar -->
<?xml-stylesheet href="chrome://navigator/content/navigator.css"
type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Accessible focus event testing">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../role.js" />
<script type="application/javascript"
src="../states.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript"
src="../autocomplete.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Hacky stuffs
// This is the hacks needed to use a searchbar without browser.js.
function getBrowser()
{
return {
mCurrentBrowser: { engines: new Array() }
};
}
var BrowserSearch = {
updateOpenSearchBadge: function() {}
};
////////////////////////////////////////////////////////////////////////////
// Invokers
function loadFormAutoComplete(aIFrameID)
{
this.iframeNode = getNode(aIFrameID);
this.iframe = getAccessible(aIFrameID);
this.eventSeq = [
new invokerChecker(EVENT_REORDER, this.iframe)
];
this.invoke = function loadFormAutoComplete_invoke()
{
var url = "data:text/html,<html><body><form id='form'>" +
"<input id='input' name='a11ytest-formautocomplete'>" +
"</form></body></html>";
this.iframeNode.setAttribute("src", url);
}
this.getID = function loadFormAutoComplete_getID()
{
return "load form autocomplete page";
}
}
function initFormAutoCompleteBy(aIFrameID, aAutoCompleteValue)
{
this.iframe = getAccessible(aIFrameID);
this.eventSeq = [
new invokerChecker(EVENT_REORDER, this.iframe)
];
this.invoke = function initFormAutoCompleteBy_invoke()
{
var iframeDOMDoc = getIFrameDOMDoc(aIFrameID);
var inputNode = iframeDOMDoc.getElementById("input");
inputNode.value = aAutoCompleteValue;
var formNode = iframeDOMDoc.getElementById("form");
formNode.submit();
}
this.getID = function initFormAutoCompleteBy_getID()
{
return "init form autocomplete by '" + aAutoCompleteValue + "'";
}
}
function loadHTML5ListAutoComplete(aIFrameID)
{
this.iframeNode = getNode(aIFrameID);
this.iframe = getAccessible(aIFrameID);
this.eventSeq = [
new invokerChecker(EVENT_REORDER, this.iframe)
];
this.invoke = function loadHTML5ListAutoComplete_invoke()
{
var url = "data:text/html,<html><body>" +
"<datalist id='cities'><option>hello</option><option>hi</option></datalist>" +
"<input id='input' list='cities'>" +
"</body></html>";
this.iframeNode.setAttribute("src", url);
}
this.getID = function loadHTML5ListAutoComplete_getID()
{
return "load HTML5 list autocomplete page";
}
}
function removeChar(aID, aCheckerOrEventSeq)
{
this.__proto__ = new synthAction(aID, aCheckerOrEventSeq);
this.invoke = function removeChar_invoke()
{
synthesizeKey("VK_LEFT", { shiftKey: true });
synthesizeKey("VK_DELETE", {});
}
this.getID = function removeChar_getID()
{
return "remove char on " + prettyName(aID);
}
}
function replaceOnChar(aID, aChar, aCheckerOrEventSeq)
{
this.__proto__ = new synthAction(aID, aCheckerOrEventSeq);
this.invoke = function replaceOnChar_invoke()
{
this.DOMNode.select();
synthesizeKey(aChar, {});
}
this.getID = function replaceOnChar_getID()
{
return "replace on char '" + aChar + "' for" + prettyName(aID);
}
}
function focusOnMouseOver(aIDFunc, aIDFuncArg)
{
this.eventSeq = [ new focusChecker(aIDFunc, aIDFuncArg) ];
this.invoke = function focusOnMouseOver_invoke()
{
this.id = aIDFunc.call(null, aIDFuncArg);
this.node = getNode(this.id);
this.window = this.node.ownerDocument.defaultView;
if (this.node.localName == "tree") {
var tree = getAccessible(this.node);
var accessible = getAccessible(this.id);
if (tree != accessible) {
var itemX = {}, itemY = {}, treeX = {}, treeY = {};
accessible.getBounds(itemX, itemY, {}, {});
tree.getBounds(treeX, treeY, {}, {});
this.x = itemX.value - treeX.value;
this.y = itemY.value - treeY.value;
}
}
// Generate mouse move events in timeouts until autocomplete popup list
// doesn't have it, the reason is do that because autocomplete popup
// ignores mousemove events firing in too short range.
synthesizeMouse(this.node, this.x, this.y, { type: "mousemove" });
this.doMouseMoveFlood(this);
}
this.finalCheck = function focusOnMouseOver_getID()
{
this.isFlooding = false;
}
this.getID = function focusOnMouseOver_getID()
{
return "mouse over on " + prettyName(aIDFunc.call(null, aIDFuncArg));
}
this.doMouseMoveFlood = function focusOnMouseOver_doMouseMoveFlood(aThis)
{
synthesizeMouse(aThis.node, aThis.x + 1, aThis.y + 1,
{ type: "mousemove" }, aThis.window);
if (aThis.isFlooding)
aThis.window.setTimeout(aThis.doMouseMoveFlood, 0, aThis);
}
this.id = null;
this.node = null;
this.window = null;
this.isFlooding = true;
this.x = 1;
this.y = 1;
}
function selectByClick(aIDFunc, aIDFuncArg,
aFocusTargetFunc, aFocusTargetFuncArg)
{
this.eventSeq = [ new focusChecker(aFocusTargetFunc, aFocusTargetFuncArg) ];
this.invoke = function selectByClick_invoke()
{
var id = aIDFunc.call(null, aIDFuncArg);
var node = getNode(id);
var targetWindow = node.ownerDocument.defaultView;
var x = 0, y = 0;
if (node.localName == "tree") {
var tree = getAccessible(node);
var accessible = getAccessible(id);
if (tree != accessible) {
var itemX = {}, itemY = {}, treeX = {}, treeY = {};
accessible.getBounds(itemX, itemY, {}, {});
tree.getBounds(treeX, treeY, {}, {});
x = itemX.value - treeX.value;
y = itemY.value - treeY.value;
}
}
synthesizeMouseAtCenter(node, {}, targetWindow);
}
this.getID = function selectByClick_getID()
{
return "select by click " + prettyName(aIDFunc.call(null, aIDFuncArg));
}
}
////////////////////////////////////////////////////////////////////////////
// Target getters
function getItem(aItemObj)
{
var autocomplete = aItemObj.autocomplete;
var autocompleteNode = aItemObj.autocompleteNode;
// XUL searchbar
if (autocompleteNode.localName == "searchbar") {
var popupNode = autocompleteNode._popup;
if (popupNode) {
var list = getAccessible(popupNode);
return list.getChildAt(aItemObj.index);
}
}
// XUL autocomplete
var popupNode = autocompleteNode.popup;
if (!popupNode) {
// HTML form autocomplete
var controller = Components.classes["@mozilla.org/autocomplete/controller;1"].
getService(Components.interfaces.nsIAutoCompleteController);
popupNode = controller.input.popup.QueryInterface(nsIDOMNode);
}
if (popupNode) {
if ("richlistbox" in popupNode) {
var list = getAccessible(popupNode.richlistbox);
return list.getChildAt(aItemObj.index);
}
var list = getAccessible(popupNode.tree);
return list.getChildAt(aItemObj.index + 1);
}
}
function getTextEntry(aID)
{
// For form autocompletes the autocomplete widget and text entry widget
// is the same widget, for XUL autocompletes the text entry is a first
// child.
var localName = getNode(aID).localName;
// XUL autocomplete
if (localName == "textbox")
return getAccessible(aID).firstChild;
// HTML form autocomplete
if (localName == "input")
return getAccessible(aID);
// XUL searchbar
if (localName == "searchbar")
return getAccessible(getNode(aID).textbox.inputField);
return null;
}
function itemObj(aID, aIdx)
{
this.autocompleteNode = getNode(aID);
this.autocomplete = this.autocompleteNode.localName == "searchbar" ?
getAccessible(this.autocompleteNode.textbox) :
getAccessible(this.autocompleteNode);
this.index = aIdx;
}
function getIFrameDOMDoc(aIFrameID)
{
return getNode(aIFrameID).contentDocument;
}
////////////////////////////////////////////////////////////////////////////
// Test helpers
function queueAutoCompleteTests(aID)
{
// focus autocomplete text entry
gQueue.push(new synthFocus(aID, new focusChecker(getTextEntry, aID)));
// open autocomplete popup
gQueue.push(new synthDownKey(aID, new nofocusChecker()));
// select second option ('hi' option), focus on it
gQueue.push(new synthUpKey(aID,
new focusChecker(getItem, new itemObj(aID, 1))));
// choose selected option, focus on text entry
gQueue.push(new synthEnterKey(aID, new focusChecker(getTextEntry, aID)));
// remove char, autocomplete popup appears
gQueue.push(new removeChar(aID, new nofocusChecker()));
// select first option ('hello' option), focus on it
gQueue.push(new synthDownKey(aID,
new focusChecker(getItem, new itemObj(aID, 0))));
// mouse move on second option ('hi' option), focus on it
gQueue.push(new focusOnMouseOver(getItem, new itemObj(aID, 1)));
// autocomplete popup updated (no selected item), focus on textentry
gQueue.push(new synthKey(aID, "e", null, new focusChecker(getTextEntry, aID)));
// select first option ('hello' option), focus on it
gQueue.push(new synthDownKey(aID,
new focusChecker(getItem, new itemObj(aID, 0))));
// popup gets hidden, focus on textentry
gQueue.push(new synthRightKey(aID, new focusChecker(getTextEntry, aID)));
// popup gets open, no focus
gQueue.push(new synthOpenComboboxKey(aID, new nofocusChecker()));
// select first option again ('hello' option), focus on it
gQueue.push(new synthDownKey(aID,
new focusChecker(getItem, new itemObj(aID, 0))));
// no option is selected, focus on text entry
gQueue.push(new synthUpKey(aID, new focusChecker(getTextEntry, aID)));
// close popup, no focus
gQueue.push(new synthEscapeKey(aID, new nofocusChecker()));
// autocomplete popup appears (no selected item), focus stays on textentry
gQueue.push(new replaceOnChar(aID, "h", new nofocusChecker()));
// mouse move on first option ('hello' option), focus on it
gQueue.push(new focusOnMouseOver(getItem, new itemObj(aID, 0)));
// click first option ('hello' option), popup closes, focus on text entry
gQueue.push(new selectByClick(getItem, new itemObj(aID, 0), getTextEntry, aID));
}
////////////////////////////////////////////////////////////////////////////
// Tests
//gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true; // debug stuff
var gInitQueue = null;
function initTests()
{
if (SEAMONKEY || MAC) {
todo(false, "Skipping this test on SeaMonkey ftb. (Bug 718237), and on Mac (bug 746177)");
shutdownAutoComplete();
SimpleTest.finish();
return;
}
gInitQueue = new eventQueue();
gInitQueue.push(new loadFormAutoComplete("iframe"));
gInitQueue.push(new initFormAutoCompleteBy("iframe", "hello"));
gInitQueue.push(new initFormAutoCompleteBy("iframe", "hi"));
gInitQueue.push(new loadHTML5ListAutoComplete("iframe2"));
gInitQueue.onFinish = function initQueue_onFinish()
{
SimpleTest.executeSoon(doTests);
return DO_NOT_FINISH_TEST;
}
gInitQueue.invoke();
}
var gQueue = null;
function doTests()
{
// Test focus events.
gQueue = new eventQueue();
////////////////////////////////////////////////////////////////////////////
// tree popup autocomplete tests
queueAutoCompleteTests("autocomplete");
////////////////////////////////////////////////////////////////////////////
// richlistbox popup autocomplete tests
queueAutoCompleteTests("richautocomplete");
////////////////////////////////////////////////////////////////////////////
// HTML form autocomplete tests
queueAutoCompleteTests(getIFrameDOMDoc("iframe").getElementById("input"));
////////////////////////////////////////////////////////////////////////////
// HTML5 list autocomplete tests
queueAutoCompleteTests(getIFrameDOMDoc("iframe2").getElementById("input"));
////////////////////////////////////////////////////////////////////////////
// searchbar tests
// focus searchbar, focus on text entry
gQueue.push(new synthFocus("searchbar",
new focusChecker(getTextEntry, "searchbar")));
// open search engine popup, no focus
gQueue.push(new synthOpenComboboxKey("searchbar", new nofocusChecker()));
// select first item, focus on it
gQueue.push(new synthDownKey("searchbar",
new focusChecker(getItem, new itemObj("searchbar", 0))));
// mouse over on second item, focus on it
gQueue.push(new focusOnMouseOver(getItem, new itemObj("searchbar", 1)));
// press enter key, focus on text entry
gQueue.push(new synthEnterKey("searchbar",
new focusChecker(getTextEntry, "searchbar")));
// click on search button, open popup, focus goes to document
var searchBtn = getAccessible(getNode("searchbar").searchButton);
gQueue.push(new synthClick(searchBtn, new focusChecker(document)));
// select first item, focus on it
gQueue.push(new synthDownKey("searchbar",
new focusChecker(getItem, new itemObj("searchbar", 0))));
// close popup, focus goes on document
gQueue.push(new synthEscapeKey("searchbar", new focusChecker(document)));
gQueue.onFinish = function()
{
// unregister 'test-a11y-search' autocomplete search
shutdownAutoComplete();
}
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
// Register 'test-a11y-search' autocomplete search.
// XPFE AutoComplete needs to register early.
initAutoComplete([ "hello", "hi" ],
[ "Beep beep'm beep beep yeah", "Baby you can drive my car" ]);
addA11yLoadEvent(initTests);
]]>
</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=383759"
title="Focus event inconsistent for search box autocomplete">
Mozilla Bug 383759
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=673958"
title="Rework accessible focus handling">
Mozilla Bug 673958
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=559766"
title="Add accessibility support for @list on HTML input and for HTML datalist">
Mozilla Bug 559766
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<textbox id="autocomplete" type="autocomplete"
autocompletesearch="test-a11y-search"/>
<textbox id="richautocomplete" type="autocomplete"
autocompletesearch="test-a11y-search"
autocompletepopup="richpopup"/>
<panel id="richpopup" type="autocomplete-richlistbox" noautofocus="true"/>
<iframe id="iframe"/>
<iframe id="iframe2"/>
<searchbar id="searchbar"/>
<vbox id="eventdump"/>
</vbox>
</hbox>
</window>

View file

@ -0,0 +1,149 @@
<?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 Loading Document Events Test.">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../browser.js"></script>
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Helpers
function inputInDocument()
{
var tabdoc = currentTabDocument();
return tabdoc.getElementById("input");
}
////////////////////////////////////////////////////////////////////////////
// Invokers
function loadURI(aURI)
{
this.invoke = function loadURI_invoke()
{
tabBrowser().loadURI(aURI);
}
this.eventSeq = [
new focusChecker(currentTabDocument)
];
this.getID = function loadURI_getID()
{
return "load uri " + aURI;
}
}
function goBack()
{
this.invoke = function goBack_invoke()
{
tabBrowser().goBack();
}
this.eventSeq = [
new focusChecker(inputInDocument)
];
this.getID = function goBack_getID()
{
return "go back one page in history ";
}
}
////////////////////////////////////////////////////////////////////////////
// Testing
var gInputDocURI = "data:text/html,<html><input id='input'></html>";
var gButtonDocURI = "data:text/html,<html><input id='input' type='button' value='button'></html>";
//gA11yEventDumpToConsole = true; // debug
var gQueue = null;
function doTests()
{
gQueue = new eventQueue();
var tabDocument = currentTabDocument();
var input = inputInDocument();
// move focus to input inside tab document
gQueue.push(new synthTab(tabDocument, new focusChecker(input),
browserWindow()));
// open new url, focus moves to new document
gQueue.push(new loadURI(gButtonDocURI));
// back one page in history, moves moves on input of tab document
gQueue.push(new goBack());
// open new tab, focus moves to urlbar
gQueue.push(new synthKey(tabDocument, "t", { accelKey: true, window: browserWindow() },
new focusChecker(urlbarInput)));
// close open tab, focus goes on input of tab document
gQueue.push(new synthKey(tabDocument, "w", { accelKey: true, window: browserWindow() },
new focusChecker(inputInDocument)));
gQueue.onFinish = function()
{
closeBrowserWindow();
}
gQueue.invoke();
}
if (navigator.oscpu.startsWith("Windows NT 6.1") || navigator.oscpu.startsWith("Windows NT 6.2")) {
todo(false, "fix the leak!");
} else {
SimpleTest.waitForExplicitFinish();
openBrowserWindow(doTests, gInputDocURI);
}
]]>
</script>
<vbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=644452"
title="Focus not set when switching to cached document with back or forward if anything other than the document was last focused">
Mozilla Bug 644452
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=665412"
title="Broken focus when returning to editable text field after closing a tab while focused in the Navigation toolbar">
Mozilla Bug 665412
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=673958"
title="Rework accessible focus handling">
Mozilla Bug 673958
</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox id="eventdump"></vbox>
</vbox>
</window>

View file

@ -0,0 +1,61 @@
<html>
<head>
<title>Accessible focus testing in canvas subdom</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript">
//gA11yEventDumpToConsole = true;
var gQueue = null;
function doTests()
{
gQueue = new eventQueue();
gQueue.push(new synthFocus("button"));
gQueue.push(new synthTab("button", new focusChecker("textbox")));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
title="Expose content in Canvas element"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=495912">
Mozilla Bug 495912
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<canvas>
<input id="button" type="button">
<input id="textbox">
</canvas>
<div id="eventdump"></div>
</body>
</html>

View file

@ -0,0 +1,99 @@
<?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="Context nenu focus testing">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../role.js" />
<script type="application/javascript"
src="../states.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript">
//gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true; // debug stuff
var winLowerThanVista = navigator.platform.indexOf("Win") == 0;
if (winLowerThanVista) {
var version = Components.classes["@mozilla.org/system-info;1"]
.getService(Components.interfaces.nsIPropertyBag2)
.getProperty("version");
version = parseFloat(version);
winLowerThanVista = !(version >= 6.0);
}
var gQueue = null;
function doTests()
{
// bug 746183 - Whole file times out on OS X
if (MAC || winLowerThanVista) {
todo(false, "Reenable on mac after fixing bug 746183!");
SimpleTest.finish();
return;
}
// Test focus events.
gQueue = new eventQueue();
gQueue.push(new synthFocus("button"));
gQueue.push(new synthContextMenu("button",
new invokerChecker(EVENT_MENUPOPUP_START, "contextmenu")));
gQueue.push(new synthEscapeKey("contextmenu", new focusChecker("button")));
gQueue.push(new synthContextMenu("button",
new invokerChecker(EVENT_MENUPOPUP_START, "contextmenu")));
gQueue.push(new synthDownKey("contextmenu", new focusChecker("item1")));
gQueue.push(new synthDownKey("item1", new focusChecker("item2")));
gQueue.push(new synthRightKey("item2", new focusChecker("item2.1")));
if (WIN) {
todo(false, "synthEscapeKey for item2.1 and item2 disabled due to bug 691580");
} else {
gQueue.push(new synthEscapeKey("item2.1", new focusChecker("item2")));
gQueue.push(new synthEscapeKey("item2", new focusChecker("button")));
}
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</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=673958"
title="Rework accessible focus handling">
Mozilla Bug 673958
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<button id="button" context="contextmenu" label="button"/>
<menupopup id="contextmenu">
<menuitem id="item1" label="item1"/>
<menu id="item2" label="item2">
<menupopup>
<menuitem id="item2.1" label="item2.1"/>
</menupopup>
</menu>
</menupopup>
<vbox id="eventdump"/>
</vbox>
</hbox>
</window>

View file

@ -0,0 +1,75 @@
<html>
<head>
<title>Accessible focus testing on HTML controls</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript">
//gA11yEventDumpToConsole = true;
var gQueue = null;
function doTests()
{
gQueue = new eventQueue(EVENT_FOCUS);
gQueue.push(new synthFocus("textbox"));
gQueue.push(new synthFocus("textarea"));
gQueue.push(new synthFocus("button1"));
gQueue.push(new synthFocus("button2"));
gQueue.push(new synthFocus("checkbox"));
gQueue.push(new synthFocus("radio1"));
gQueue.push(new synthDownKey("radio1", new focusChecker("radio2")));
// no focus events for checkbox or radio inputs when they are checked
// programmatically
gQueue.push(new changeCurrentItem("checkbox"));
gQueue.push(new changeCurrentItem("radio1"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=673958"
title="Rework accessible focus handling">
Mozilla Bug 673958
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<input id="textbox">
<textarea id="textarea"></textarea>
<input id="button1" type="button" value="button">
<button id="button2">button</button>
<input id="checkbox" type="checkbox">
<input id="radio1" type="radio" name="radiogroup">
<input id="radio2" type="radio" name="radiogroup">
<div id="eventdump"></div>
</body>
</html>

View file

@ -0,0 +1,164 @@
<html>
<head>
<title>Accessible focus testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript">
function openCloseDialog(aID)
{
this.eventSeq = [
new focusChecker(getNode(aID))
];
this.invoke = function openCloseDialog_invoke()
{
var wnd = window.open("focus.html");
wnd.close();
}
this.getID = function openCloseDialog_getID()
{
return "Open close dialog while focus on " + prettyName(aID);
}
}
var gDialogWnd = null;
function getDialogDocument()
{
return gDialogWnd.document;
}
function openDialog(aID)
{
this.eventSeq = [
new focusChecker(getDialogDocument)
];
this.invoke = function openDialog_invoke()
{
gDialogWnd = window.open("focus.html");
}
this.getID = function openDialog_getID()
{
return "Open dialog while focus on " + prettyName(aID);
}
}
function closeDialog(aID)
{
this.eventSeq = [
new focusChecker(aID)
];
this.invoke = function closeDialog_invoke()
{
gDialogWnd.close();
}
this.getID = function closeDialog_getID()
{
return "Close dialog while focus on " + prettyName(aID);
}
}
function showNFocusAlertDialog()
{
this.ID = "alertdialog";
this.DOMNode = getNode(this.ID);
this.invoke = function showNFocusAlertDialog_invoke()
{
document.getElementById(this.ID).style.display = 'block';
document.getElementById(this.ID).focus();
}
this.eventSeq = [
new invokerChecker(EVENT_SHOW, this.DOMNode),
new focusChecker(this.DOMNode)
];
this.getID = function showNFocusAlertDialog_getID()
{
return "Show and focus alert dialog " + prettyName(this.ID);
}
}
/**
* Do tests.
*/
//gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true;
var gQueue = null;
function doTests()
{
gQueue = new eventQueue(EVENT_FOCUS);
gQueue.push(new synthFocus("button"));
gQueue.push(new openDialog("button"));
gQueue.push(new closeDialog("button"));
var frameNode = getNode("editabledoc");
gQueue.push(new synthFocusOnFrame(frameNode));
gQueue.push(new openCloseDialog(frameNode.contentDocument));
gQueue.push(new showNFocusAlertDialog());
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=551679"
title="focus is not fired for focused document when switching between windows">
Mozilla Bug 551679
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=580464"
title="Accessible focus incorrect after JS focus() but correct after switching apps or using menu bar">
Mozilla Bug 580464
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<button id="button">button</button>
<iframe id="editabledoc" src="focus.html"></iframe>
<div id="alertdialog" style="display: none" tabindex="-1" role="alertdialog" aria-labelledby="title2" aria-describedby="desc2">
<div id="title2">Blah blah</div>
<div id="desc2">Woof woof woof.</div>
<button>Close</button>
</div>
<div id="eventdump"></div>
</body>
</html>

View file

@ -0,0 +1,95 @@
<html>
<head>
<title>Accessible document focus event testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript">
var gQueue = null;
//var gA11yEventDumpID = "eventdump";
//gA11yEventDumpToConsole = true;
function doTests()
{
// setup
var frameDoc = document.getElementById("iframe").contentDocument;
frameDoc.designMode = "on";
var frameDocAcc = getAccessible(frameDoc, [nsIAccessibleDocument]);
var buttonAcc = getAccessible("b1");
var frame2Doc = document.getElementById("iframe2").contentDocument;
var frame2Input = frame2Doc.getElementById("input");
var frame2DocAcc = getAccessible(frame2Doc);
var frame2InputAcc = getAccessible(frame2Input);
// Test focus events.
gQueue = new eventQueue();
// try to give focus to contentEditable frame twice to cover bug 512059
gQueue.push(new synthFocus(buttonAcc));
gQueue.push(new synthTab(frameDocAcc, new focusChecker(frameDocAcc)));
gQueue.push(new synthFocus(buttonAcc));
gQueue.push(new synthTab(frameDocAcc, new focusChecker(frameDocAcc)));
// focus on not editable document
gQueue.push(new synthFocus(frame2InputAcc));
gQueue.push(new synthShiftTab(frame2DocAcc, new focusChecker(frame2DocAcc)));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=512058"
title="Can't set focus to designMode document via accessibility APIs">
Mozilla Bug 512058
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=512059"
title="Accessibility focus event never fired for designMode document after the first focus">
Mozilla Bug 512059
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=618046"
title="No focus change event when Shift+Tab at top of screen">
Mozilla Bug 618046
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="eventdump"></div>
<div id="testContainer">
<button id="b1">a button</button>
<iframe id="iframe" src="about:blank"></iframe>
<button id="b2">a button</button>
<iframe id="iframe2" src="data:text/html,<html><input id='input'></html>"></iframe>
</div>
</body>
</html>

View file

@ -0,0 +1,179 @@
<html>
<head>
<title>Accessible focus testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript">
function focusElmWhileSubdocIsFocused(aID)
{
this.DOMNode = getNode(aID);
this.invoke = function focusElmWhileSubdocIsFocused_invoke()
{
this.DOMNode.focus();
}
this.eventSeq = [
new focusChecker(this.DOMNode)
];
this.unexpectedEventSeq = [
new invokerChecker(EVENT_FOCUS, this.DOMNode.ownerDocument)
];
this.getID = function focusElmWhileSubdocIsFocused_getID()
{
return "Focus element while subdocument is focused " + prettyName(aID);
}
}
function imageMapChecker(aID)
{
var node = getNode(aID);
this.type = EVENT_FOCUS;
this.match = function imageMapChecker_match(aEvent)
{
return aEvent.DOMNode == node;
}
}
function topMenuChecker()
{
this.type = EVENT_FOCUS;
this.match = function topMenuChecker_match(aEvent)
{
return aEvent.accessible.role == ROLE_PARENT_MENUITEM;
}
}
function contextMenuChecker()
{
this.type = EVENT_MENUPOPUP_START;
this.match = function contextMenuChecker_match(aEvent)
{
return aEvent.accessible.role == ROLE_MENUPOPUP;
}
}
function focusContextMenuItemChecker()
{
this.__proto__ = new focusChecker();
this.match = function focusContextMenuItemChecker_match(aEvent)
{
return aEvent.accessible.role == ROLE_MENUITEM;
}
}
/**
* Do tests.
*/
//gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true;
var gQueue = null;
function doTests()
{
var frameDoc = document.getElementById("iframe").contentDocument;
var editableDoc = document.getElementById('editabledoc').contentDocument;
editableDoc.designMode = 'on';
gQueue = new eventQueue();
gQueue.push(new synthFocus("editablearea"));
gQueue.push(new synthFocus("navarea"));
gQueue.push(new synthTab("navarea", new focusChecker(frameDoc)));
gQueue.push(new focusElmWhileSubdocIsFocused("link"));
gQueue.push(new synthTab(editableDoc, new focusChecker(editableDoc)));
if (WIN || LINUX) {
// Alt key is used to active menubar and focus menu item on Windows,
// other platforms requires setting a ui.key.menuAccessKeyFocuses
// preference.
gQueue.push(new toggleTopMenu(editableDoc, new topMenuChecker()));
gQueue.push(new toggleTopMenu(editableDoc, new focusChecker(editableDoc)));
}
gQueue.push(new synthContextMenu(editableDoc, new contextMenuChecker()));
gQueue.push(new synthDownKey(editableDoc, new focusContextMenuItemChecker()));
gQueue.push(new synthEscapeKey(editableDoc, new focusChecker(editableDoc)));
if (SEAMONKEY) {
todo(false, "shift tab from editable document fails on (Windows) SeaMonkey! (Bug 718235)");
} else {
if (LINUX || MAC)
todo(false, "shift tab from editable document fails on linux and Mac, bug 746519!");
else
gQueue.push(new synthShiftTab("link", new focusChecker("link")));
} // ! SEAMONKEY
gQueue.push(new synthFocus("a", new imageMapChecker("a")));
gQueue.push(new synthFocus("b", new imageMapChecker("b")));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=352220"
title="Inconsistent focus events when returning to a document frame">
Mozilla Bug 352220
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=550338"
title="Broken focus when returning to editable documents from menus">
Mozilla Bug 550338
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=673958"
title="Rework accessible focus handling">
Mozilla Bug 673958
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=961696"
title="Accessible object:state-changed:focused events for imagemap links are broken">
Mozilla Bug 961696
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="editablearea" contentEditable="true">editable area</div>
<div id="navarea" tabindex="0">navigable area</div>
<iframe id="iframe" src="data:text/html,<html></html>"></iframe>
<a id="link" href="">link</a>
<iframe id="editabledoc" src="about:blank"></iframe>
<map name="atoz_map">
<area id="a" coords="0,0,13,14" shape="rect">
<area id="b" coords="17,0,30,14" shape="rect">
</map>
<img width="447" height="15" usemap="#atoz_map" src="../letters.gif">
<div id="eventdump"></div>
</body>
</html>

View file

@ -0,0 +1,179 @@
<?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 focus event testing">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../role.js" />
<script type="application/javascript"
src="../states.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript">
function getColorBtn(aBtnObj)
{
var colorpicker = aBtnObj.colorpicker;
var container = colorpicker.firstChild;
var btn = container.getChildAt(aBtnObj.btnIndex);
return btn;
}
//gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true; // debug stuff
var gQueue = null;
function doTests()
{
// Test focus events.
gQueue = new eventQueue();
gQueue.push(new synthFocus("textbox",
new focusChecker(getNode("textbox").inputField)));
gQueue.push(new synthFocus("textbox_multiline",
new focusChecker(getNode("textbox_multiline").inputField)));
gQueue.push(new synthFocus("scale"));
gQueue.push(new synthFocusOnFrame("editabledoc"));
gQueue.push(new synthFocus("radioclothes",
new focusChecker("radiosweater")));
gQueue.push(new synthDownKey("radiosweater",
new focusChecker("radiojacket")));
gQueue.push(new synthFocus("checkbox"));
gQueue.push(new synthFocus("button"));
gQueue.push(new synthFocus("checkbutton"));
gQueue.push(new synthFocus("radiobutton"));
// focus menubutton
gQueue.push(new synthFocus("menubutton"));
// click menubutton, open popup, focus stays on menu button
gQueue.push(new synthClick("menubutton", new nofocusChecker()));
// select first menu item ("item 1"), focus on menu item
gQueue.push(new synthDownKey("menubutton", new focusChecker("mb_item1")));
// choose select menu item, focus gets back to menubutton
gQueue.push(new synthEnterKey("mb_item1", new focusChecker("menubutton")));
// press enter to open popup, focus stays on menubutton
gQueue.push(new synthEnterKey("menubutton", new nofocusChecker()));
// select second menu item ("item 2"), focus on menu item
gQueue.push(new synthUpKey("menubutton", new focusChecker("mb_item2")));
// clicking on button having associated popup doesn't change a focus
gQueue.push(new synthClick("popupbutton", new nofocusChecker()));
// select first menu item ("item 1"), focus on menu item
gQueue.push(new synthDownKey("popupbutton", new focusChecker("bp_item1")));
// choose select menu item, focus gets back to menubutton
gQueue.push(new synthEnterKey("bp_item1", new focusChecker("menubutton")));
// show popup again for the next test
gQueue.push(new synthClick("popupbutton", new nofocusChecker()));
if (!MAC) {
// click menubutton of the 'menubutton' button while popup of button open.
gQueue.push(new synthClick("mbb", new focusChecker("mbb"), { where: "right" }));
// close popup, focus stays on menubutton, fire focus event
gQueue.push(new synthEscapeKey("mbb", new focusChecker("mbb")));
// click menubutton, open popup, focus stays on menubutton
gQueue.push(new synthClick("mbb", new nofocusChecker(), { where: "right" }));
// select first menu item ("item 1"), focus on menu item
gQueue.push(new synthDownKey("mbb", new focusChecker("mbb_item1")));
// choose select menu item, focus gets back to menubutton
gQueue.push(new synthEnterKey("mbb_item1", new focusChecker("mbb")));
// open popup, focus stays on menubutton
gQueue.push(new synthOpenComboboxKey("mbb", new nofocusChecker()));
// select second menu item ("item 2"), focus on menu item
gQueue.push(new synthUpKey("menubutton", new focusChecker("mbb_item2")));
// click on menu item of menubutton menu, focus menubutton
gQueue.push(new synthClick("mbb_item2", new focusChecker("mbb")));
} else {
todo(false, "mbb tests time out on OS X, fix bug 746970 and reenable!");
}
// focus colorpicker button
gQueue.push(new synthFocus("colorpicker"));
// click on button, open popup, focus goes to current color button
var btnObj = { colorpicker: getAccessible("colorpicker"), btnIndex: 0 };
var checker = new focusChecker(getColorBtn, btnObj);
gQueue.push(new synthClick("colorpicker", checker));
// select sibling color button, focus on it
btnObj = { colorpicker: getAccessible("colorpicker"), btnIndex: 1 };
var checker = new focusChecker(getColorBtn, btnObj);
gQueue.push(new synthRightKey("colorpicker", checker));
// choose selected color button, close popup, focus on colorpicker button
gQueue.push(new synthEnterKey("colorpicker", new focusChecker("colorpicker")));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</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=492518"
title="xul:slider accessible of xul:scale is accessible illegally">
Mozilla Bug 492518
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=552368"
title=" fire focus event on document accessible whenever the root or body element is focused">
Mozilla Bug 552368
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<textbox id="textbox" value="hello"/>
<textbox id="textbox_multiline" multiline="true" value="hello"/>
<scale id="scale" min="0" max="9" value="5"/>
<iframe id="editabledoc" src="focus.html"/>
<radiogroup id="radioclothes">
<radio id="radiosweater" label="radiosweater"/>
<radio id="radiocap" label="radiocap" disabled="true"/>
<radio id="radiojacket" label="radiojacket"/>
</radiogroup>
<checkbox id="checkbox" label="checkbox"/>
<button id="button" label="button"/>
<button id="checkbutton" type="checkbox" label="checkbutton"/>
<button id="radiobutton" type="radio" group="rbgroup" label="radio1"/>
<button id="menubutton" type="menu" label="menubutton">
<menupopup>
<menuitem id="mb_item1" label="item1"/>
<menuitem id="mb_item2" label="item2"/>
</menupopup>
</button>
<button id="mbb" type="menu-button" label="menubutton button">
<menupopup>
<menuitem id="mbb_item1" label="item1"/>
<menuitem id="mbb_item2" label="item2"/>
</menupopup>
</button>
<colorpicker id="colorpicker" type="button" label="color picker"
color="#FFFFFF"/>
<popupset>
<menupopup id="backpopup" position="after_start">
<menuitem id="bp_item1" label="Page 1"/>
<menuitem id="bp_item2" label="Page 2"/>
</menupopup>
</popupset>
<button id="popupbutton" label="Pop Me Up" popup="backpopup"/>
<vbox id="eventdump"/>
</vbox>
</hbox>
</window>

View file

@ -0,0 +1,189 @@
<?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 focus event testing">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../role.js" />
<script type="application/javascript"
src="../states.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript">
//gA11yEventDumpID = "eventdump"; // debug stuff
gA11yEventDumpToConsole = true; // debug stuff
var gQueue = null;
function doTests()
{
// Test focus events.
gQueue = new eventQueue();
gQueue.push(new synthFocus("listbox", new focusChecker("lb_item1")));
gQueue.push(new synthDownKey("lb_item1", new focusChecker("lb_item2")));
gQueue.push(new synthTab("lb_item2", new focusChecker("mslb_item1")));
gQueue.push(new synthDownKey("mslb_item1", new focusChecker("mslb_item2"), { shiftKey: true }));
gQueue.push(new synthTab("mslb_item2", new focusChecker("emptylistbox")));
gQueue.push(new synthFocus("mcolumnlistbox", new focusChecker("mclb_item1")));
gQueue.push(new synthDownKey("mclb_item1", new focusChecker("mclb_item2")));
gQueue.push(new synthFocus("headerlistbox", new focusChecker("hlb_item1")));
gQueue.push(new synthDownKey("hlb_item1", new focusChecker("hlb_item2")));
gQueue.push(new synthFocus("richlistbox", new focusChecker("rlb_item1")));
gQueue.push(new synthDownKey("rlb_item1", new focusChecker("rlb_item2")));
gQueue.push(new synthFocus("multiselrichlistbox", new focusChecker("msrlb_item1")));
gQueue.push(new synthDownKey("msrlb_item1", new focusChecker("msrlb_item2"), { shiftKey: true }));
gQueue.push(new synthFocus("emptyrichlistbox", new focusChecker("emptyrichlistbox")));
gQueue.push(new synthFocus("menulist"));
gQueue.push(new synthClick("menulist", new focusChecker("ml_tangerine")));
gQueue.push(new synthDownKey("ml_tangerine", new focusChecker("ml_marmalade")));
gQueue.push(new synthEscapeKey("ml_marmalade", new focusChecker("menulist")));
if (!MAC) {
// On Windows, items get selected during navigation.
let expectedItem = WIN ? "ml_tangerine" : "ml_marmalade";
gQueue.push(new synthDownKey("menulist", new nofocusChecker(expectedItem)));
gQueue.push(new synthOpenComboboxKey("menulist", new focusChecker(expectedItem)));
gQueue.push(new synthEnterKey(expectedItem, new focusChecker("menulist")));
} else {
todo(false, "Bug 746531 - timeouts of last three menulist tests on OS X");
}
var textentry = getAccessible("emenulist").firstChild;
gQueue.push(new synthFocus("emenulist", new focusChecker(textentry)));
gQueue.push(new synthDownKey(textentry, new nofocusChecker("eml_tangerine")));
gQueue.push(new synthUpKey(textentry, new focusChecker("eml_marmalade")));
gQueue.push(new synthEnterKey("eml_marmalade", new focusChecker(textentry)));
gQueue.push(new synthOpenComboboxKey("emenulist", new focusChecker("eml_marmalade")));
gQueue.push(new synthEscapeKey("eml_marmalade", new focusChecker(textentry)));
// no focus events for unfocused list controls when current item is
// changed.
gQueue.push(new synthFocus("emptylistbox"));
gQueue.push(new changeCurrentItem("listbox", "lb_item1"));
gQueue.push(new changeCurrentItem("richlistbox", "rlb_item1"));
if (!MAC) {
gQueue.push(new changeCurrentItem("menulist", WIN ? "ml_marmalade" : "ml_tangerine"));
}
gQueue.push(new changeCurrentItem("emenulist", "eml_tangerine"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</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=433418"
title="Accessibles for focused HTML Select elements are not getting focused state">
Mozilla Bug 433418
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=474893"
title="List controls should fire a focus event on the selected child when tabbing or when the selected child changes while the list is focused">
Mozilla Bug 474893
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=552368"
title=" fire focus event on document accessible whenever the root or body element is focused">
Mozilla Bug 552368
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<listbox id="listbox" rows="3">
<listitem id="lb_item1" label="item1"/>
<listitem id="lb_item2" label="item1"/>
</listbox>
<listbox id="multisellistbox" rows="3" seltype="multiple">
<listitem id="mslb_item1" label="item1"/>
<listitem id="mslb_item2" label="item1"/>
</listbox>
<listbox id="emptylistbox" rows="3"/>
<listbox id="mcolumnlistbox" rows="3">
<listcols>
<listcol/>
<listcol/>
</listcols>
<listitem id="mclb_item1">
<listcell label="George"/>
<listcell label="House Painter"/>
</listitem>
<listitem id="mclb_item2">
<listcell label="Mary Ellen"/>
<listcell label="Candle Maker"/>
</listitem>
</listbox>
<listbox id="headerlistbox" rows="3">
<listhead>
<listheader label="Name"/>
<listheader label="Occupation"/>
</listhead>
<listcols>
<listcol/>
<listcol flex="1"/>
</listcols>
<listitem id="hlb_item1">
<listcell label="George"/>
<listcell label="House Painter"/>
</listitem>
<listitem id="hlb_item2">
<listcell label="Mary Ellen"/>
<listcell label="Candle Maker"/>
</listitem>
</listbox>
<richlistbox id="richlistbox">
<richlistitem id="rlb_item1">
<description>A XUL Description!</description>
</richlistitem>
<richlistitem id="rlb_item2">
<button label="A XUL Button"/>
</richlistitem>
</richlistbox>
<richlistbox id="multiselrichlistbox" seltype="multiple">
<richlistitem id="msrlb_item1">
<description>A XUL Description!</description>
</richlistitem>
<richlistitem id="msrlb_item2">
<button label="A XUL Button"/>
</richlistitem>
</richlistbox>
<richlistbox id="emptyrichlistbox" seltype="multiple"/>
<menulist id="menulist">
<menupopup>
<menuitem id="ml_tangerine" label="tangerine trees"/>
<menuitem id="ml_marmalade" label="marmalade skies"/>
</menupopup>
</menulist>
<menulist id="emenulist" editable="true">
<menupopup>
<menuitem id="eml_tangerine" label="tangerine trees"/>
<menuitem id="eml_marmalade" label="marmalade skies"/>
</menupopup>
</menulist>
<vbox id="eventdump"/>
</vbox>
</hbox>
</window>

View file

@ -0,0 +1,119 @@
<?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="Menu focus testing">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../role.js" />
<script type="application/javascript"
src="../states.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript">
//gA11yEventDumpToConsole = true; // debug stuff
var gQueue = null;
function doTests()
{
// Test focus events.
gQueue = new eventQueue();
if (WIN) {
gQueue.push(new toggleTopMenu("fruit", new focusChecker("fruit")));
gQueue.push(new synthRightKey("fruit", new focusChecker("vehicle")));
gQueue.push(new synthEscapeKey("vehicle", new focusChecker(document)));
}
// mouse move activate items but no focus event until menubar is active
gQueue.push(new synthMouseMove("fruit", new nofocusChecker("apple")));
// mouseover and click on menuitem makes it active before menubar is
// active
gQueue.push(new synthClick("fruit", new focusChecker("fruit")));
// mouseover on menuitem when menubar is active
gQueue.push(new synthMouseMove("apple", new focusChecker("apple")));
// keydown on disabled menuitem (disabled items are skipped on linux)
if (WIN)
gQueue.push(new synthDownKey("apple", new focusChecker("orange")));
// menu and menuitem are both active
// XXX: intermitent failure because two focus events may be coalesced,
// think to workaround or fix this issue, when done enable queue invoker
// below and remove next two.
//gQueue.push(new synthRightKey("apple",
// [ new focusChecker("vehicle"),
// new focusChecker("cycle")]));
gQueue.push(new synthClick("vehicle", new focusChecker("vehicle")));
gQueue.push(new synthDownKey("cycle", new focusChecker("cycle")));
// open submenu
gQueue.push(new synthRightKey("cycle", new focusChecker("tricycle")));
// move to first menu in cycle, DOMMenuItemActive is fired for fruit,
// cycle and apple menuitems (bug 685191)
todo(false, "focus is fired for 'cycle' menuitem");
//gQueue.push(new synthRightKey("vehicle", new focusChecker("apple")));
// click menuitem to close menu, focus gets back to document
gQueue.push(new synthClick("tricycle", new focusChecker(document)));
//enableLogging("focus,DOMEvents,tree"); // logging for bug708927
//gQueue.onFinish = function() { disableLogging(); }
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</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=673958"
title="Rework accessible focus handling">
Mozilla Bug 673958
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<menubar>
<menu id="fruit" label="Fruit">
<menupopup>
<menuitem id="apple" label="Apple"/>
<menuitem id="orange" label="Orange" disabled="true"/>
</menupopup>
</menu>
<menu id="vehicle" label="Vehicle">
<menupopup>
<menu id="cycle" label="cycle">
<menupopup>
<menuitem id="tricycle" label="tricycle"/>
</menupopup>
</menu>
<menuitem id="car" label="Car" disabled="true"/>
</menupopup>
</menu>
</menubar>
<vbox id="eventdump"/>
</vbox>
</hbox>
</window>

View file

@ -0,0 +1,122 @@
<html>
<head>
<title>Accessible name testing on focus</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
/**
* Checker for invokers.
*/
function actionChecker(aID, aDescription)
{
this.__proto__ = new invokerChecker(EVENT_FOCUS, aID);
this.check = function actionChecker_check(aEvent)
{
var target = aEvent.accessible;
is(target.description, aDescription,
"Wrong description for " + prettyName(target));
}
}
var gFocusHandler = {
handleEvent: function gFocusHandler_handleEvent(aEvent) {
var elm = aEvent.target;
if (elm.nodeType != nsIDOMNode.ELEMENT_NODE)
return;
gTooltipElm.style.display = "block";
elm.setAttribute("aria-describedby", "tooltip");
}
};
var gBlurHandler = {
handleEvent: function gBlurHandler_handleEvent(aEvent) {
gTooltipElm.style.display = "none";
var elm = aEvent.target;
if (elm.nodeType == nsIDOMNode.ELEMENT_NODE)
elm.removeAttribute("aria-describedby");
}
};
/**
* Do tests.
*/
// gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true;
var gQueue = null;
var gButtonElm = null;
var gTextboxElm = null;
var gTooltipElm = null;
function doTests()
{
gButtonElm = getNode("button");
gTextboxElm = getNode("textbox");
gTooltipElm = getNode("tooltip");
gButtonElm.addEventListener("focus", gFocusHandler, false);
gButtonElm.addEventListener("blur", gBlurHandler, false);
gTextboxElm.addEventListener("focus", gFocusHandler, false);
gTextboxElm.addEventListener("blur", gBlurHandler, false);
// The aria-describedby is changed on DOM focus. Accessible description
// should be updated when a11y focus is fired.
gQueue = new eventQueue(nsIAccessibleEvent.EVENT_FOCUS);
gQueue.onFinish = function()
{
gButtonElm.removeEventListener("focus", gFocusHandler, false);
gButtonElm.removeEventListener("blur", gBlurHandler, false);
gTextboxElm.removeEventListener("focus", gFocusHandler, false);
gTextboxElm.removeEventListener("blur", gBlurHandler, false);
}
var descr = "It's a tooltip";
gQueue.push(new synthFocus("button", new actionChecker("button", descr)));
gQueue.push(new synthTab("textbox", new actionChecker("textbox", descr)));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=520709"
title="mochitest to ensure name/description are updated on a11y focus if they were changed on DOM focus">
Mozilla Bug 520709
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="tooltip" style="display: none" aria-hidden="true">It's a tooltip</div>
<button id="button">button</button>
<input id="textbox">
<div id="eventdump"></div>
</body>
</html>

View file

@ -0,0 +1,118 @@
<html>
<head>
<title>Accessible focus testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript">
//gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true;
var gQueue = null;
function doTests()
{
// Bug 746534 - File causes crash or hang on OS X
if (MAC) {
todo(false, "Bug 746534 - test file causes crash or hang on OS X");
SimpleTest.finish();
return;
}
gQueue = new eventQueue();
// first item is focused until there's selection
gQueue.push(new synthFocus("list", new focusChecker("orange")));
// item is selected and stays focused
gQueue.push(new synthDownKey("list", new nofocusChecker()));
// last selected item is focused
gQueue.push(new synthDownKey("list", new focusChecker("apple"), { shiftKey: true }));
// no focus event if nothing is changed
gQueue.push(new synthDownKey("list", new nofocusChecker("apple")));
// current item is focused
gQueue.push(new synthUpKey("list", new focusChecker("orange"), { ctrlKey: true }));
// focus on empty list (no items to be focused)
gQueue.push(new synthTab("list", new focusChecker("emptylist")));
// current item is focused
gQueue.push(new synthShiftTab("emptylist", new focusChecker("orange")));
// collapsed combobox keeps a focus
gQueue.push(new synthFocus("combobox", new focusChecker("combobox")));
gQueue.push(new synthDownKey("combobox", new nofocusChecker("combobox")));
// selected item is focused for expanded combobox
gQueue.push(new synthOpenComboboxKey("combobox", new focusChecker("cb_apple")));
gQueue.push(new synthUpKey("combobox", new focusChecker("cb_orange")));
// collapsed combobx keeps a focus
gQueue.push(new synthEscapeKey("combobox", new focusChecker("combobox")));
// no focus events for unfocused list controls when current item is
// changed
gQueue.push(new synthFocus("emptylist"));
gQueue.push(new changeCurrentItem("list", "orange"));
gQueue.push(new changeCurrentItem("combobox", "cb_apple"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=433418"
title="Accessibles for focused HTML Select elements are not getting focused state">
Mozilla Bug 433418
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=474893"
title="List controls should fire a focus event on the selected child when tabbing or when the selected child changes while the list is focused">
Mozilla Bug 474893
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<select id="list" size="5" multiple="">
<option id="orange">Orange</option>
<option id="apple">Apple</option>
</select>
<select id="emptylist" size="5"></select>
<select id="combobox">
<option id="cb_orange">Orange</option>
<option id="cb_apple">Apple</option>
</select>
<div id="eventdump"></div>
</body>
</html>

View file

@ -0,0 +1,103 @@
<?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="Tabbox focus testing">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../role.js" />
<script type="application/javascript"
src="../states.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript">
//gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true; // debug stuff
var gQueue = null;
function doTests()
{
if (MAC) {
todo(false, "Tests disabled because of imminent failure.");
SimpleTest.finish();
return;
}
// Test focus events.
gQueue = new eventQueue();
var textbox = getNode("textbox").inputField;
gQueue.push(new synthClick("tab1", new focusChecker("tab1")));
gQueue.push(new synthTab("tab1", new focusChecker("checkbox1")));
gQueue.push(new synthKey("tab1", "VK_TAB", { ctrlKey: true },
new focusChecker(textbox)));
gQueue.push(new synthKey("tab2", "VK_TAB", { ctrlKey: true },
new focusChecker("tab3")));
gQueue.push(new synthKey("tab3", "VK_TAB", { ctrlKey: true },
new focusChecker("tab1")));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</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=370396"
title="Control+Tab to an empty tab panel in a tabbox causes focus to leave the tabbox">
Mozilla Bug 370396
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<tabbox>
<tabs>
<tab id="tab1" label="Tab1" selected="true"/>
<tab id="tab2" label="Tab2" />
<tab id="tab3" label="Tab3" />
</tabs>
<tabpanels>
<tabpanel orient="vertical">
<groupbox orient="vertical">
<checkbox id="checkbox1" label="Monday" width="75"/>
<checkbox label="Tuesday" width="75"/>
<checkbox label="Wednesday" width="75"/>
<checkbox label="Thursday" width="75"/>
<checkbox label="Friday" width="75"/>
<checkbox label="Saturday" width="75"/>
<checkbox label="Sunday" width="75"/>
</groupbox>
<spacer style="height: 10px" />
<label value="Label After checkboxes" />
</tabpanel>
<tabpanel orient="vertical">
<textbox id="textbox" />
</tabpanel>
<tabpanel orient="vertical">
<description>Tab 3 content</description>
</tabpanel>
</tabpanels>
</tabbox>
<vbox id="eventdump"/>
</vbox>
</hbox>
</window>

View file

@ -0,0 +1,122 @@
<?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="XUL tree focus testing">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<script type="application/javascript"
src="../treeview.js" />
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../role.js" />
<script type="application/javascript"
src="../states.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Invokers
function focusTree(aTreeID)
{
var checker = new focusChecker(getFirstTreeItem, aTreeID);
this.__proto__ = new synthFocus(aTreeID, [ checker ]);
}
function moveToNextItem(aTreeID)
{
var checker = new focusChecker(getSecondTreeItem, aTreeID);
this.__proto__ = new synthDownKey(aTreeID, [ checker ]);
}
////////////////////////////////////////////////////////////////////////////
// Helpers
function getTreeItemAt(aTreeID, aIdx)
{ return getAccessible(aTreeID).getChildAt(aIdx + 1); }
function getFirstTreeItem(aTreeID)
{ return getTreeItemAt(aTreeID, 0); }
function getSecondTreeItem(aTreeID)
{ return getTreeItemAt(aTreeID, 1); }
////////////////////////////////////////////////////////////////////////////
// Test
var gQueue = null;
//gA11yEventDumpID = "debug"; // debugging
//gA11yEventDumpToConsole = true; // debugging
function doTest()
{
gQueue = new eventQueue();
gQueue.push(new focusTree("tree"));
gQueue.push(new moveToNextItem("tree"));
gQueue.push(new synthFocus("emptytree"));
// no focus event for changed current item for unfocused tree
gQueue.push(new changeCurrentItem("tree", 0));
gQueue.invoke();
}
SimpleTest.waitForExplicitFinish();
addA11yXULTreeLoadEvent(doTest, "tree", new nsTableTreeView(5));
]]>
</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=386821"
title="Need better solution for firing delayed event against xul tree">
Mozilla Bug 386821
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=406308"
title="Don't fire accessible focus events if widget is not actually in focus, confuses screen readers">
Mozilla Bug 406308
</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox id="debug"/>
<tree id="tree" flex="1">
<treecols>
<treecol id="col1" flex="1" primary="true" label="column"/>
<treecol id="col2" flex="1" label="column 2"/>
</treecols>
<treechildren id="treechildren"/>
</tree>
<tree id="emptytree" flex="1">
<treecols>
<treecol id="emptytree_col1" flex="1" primary="true" label="column"/>
<treecol id="emptytree_col2" flex="1" label="column 2"/>
</treecols>
<treechildren id="emptytree_treechildren"/>
</tree>
</hbox>
</window>

View file

@ -0,0 +1,127 @@
<html>
<head>
<title>Testing of isFromUserInput in text events</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
/**
* Remove text data from HTML input.
*/
function removeTextFromInput(aID, aStart, aEnd, aText, aFromUser)
{
this.DOMNode = getNode(aID);
this.eventSeq = [
new textChangeChecker(aID, aStart, aEnd, aText, false, aFromUser)
];
this.invoke = function removeTextFromInput_invoke()
{
const nsIDOMNSEditableElement =
Components.interfaces.nsIDOMNSEditableElement;
this.DOMNode.focus();
this.DOMNode.setSelectionRange(aStart, aEnd);
synthesizeKey("VK_DELETE", {});
}
this.getID = function removeTextFromInput_getID()
{
return "Remove text from " + aStart + " to " + aEnd + " for " +
prettyName(aID);
}
}
/**
* Remove text data from text node.
*/
function removeTextFromContentEditable(aID, aStart, aEnd, aText, aFromUser)
{
this.DOMNode = getNode(aID);
this.eventSeq = [
new textChangeChecker(aID, aStart, aEnd, aText, false, aFromUser)
];
this.invoke = function removeTextFromContentEditable_invoke()
{
const nsIDOMNSEditableElement =
Components.interfaces.nsIDOMNSEditableElement;
this.DOMNode.focus();
this.textNode = getNode(aID).firstChild;
var selection = window.getSelection();
var range = document.createRange();
range.setStart(this.textNode, aStart);
range.setEnd(this.textNode, aEnd);
selection.addRange(range);
synthesizeKey("VK_DELETE", {});
}
this.getID = function removeTextFromContentEditable_getID()
{
return "Remove text from " + aStart + " to " + aEnd + " for " +
prettyName(aID);
}
}
////////////////////////////////////////////////////////////////////////////
// Do tests
// gA11yEventDumpID = "eventdump"; // debug stuff
var gQueue = null;
function doTests()
{
gQueue = new eventQueue();
// Focused editable text node
gQueue.push(new removeTextFromContentEditable("div", 0, 3, "hel", true));
// Focused editable HTML input
gQueue.push(new removeTextFromInput("input", 1, 2, "n", true));
gQueue.invoke(); // Will call SimpleTest.finish()
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=686909"
title="isFromUserInput flag on accessible text change events not correct">
Mozilla Bug 686909
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<div id="eventdump"></div>
<div id="div" contentEditable="true">hello</div>
<input id="input" value="input">
</body>
</html>

View file

@ -0,0 +1,177 @@
<?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="Tests: accessible XUL label/description events">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../role.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Invokers
const kRecreated = 0;
const kTextRemoved = 1;
const kTextChanged = 2;
const kNoValue = 0;
/**
* Set/remove @value attribute.
*/
function setValue(aID, aValue, aResult, aOldValue)
{
this.labelNode = getNode(aID);
this.eventSeq = [];
switch (aResult) {
case kRecreated:
this.eventSeq.push(new invokerChecker(EVENT_HIDE, this.labelNode));
this.eventSeq.push(new invokerChecker(EVENT_SHOW, this.labelNode));
break;
case kTextRemoved:
this.eventSeq.push(
new textChangeChecker(this.labelNode, 0, aOldValue.length,
aOldValue, false));
break;
case kTextChanged:
this.eventSeq.push(
new textChangeChecker(this.labelNode, 0, aOldValue.length,
aOldValue, false));
this.eventSeq.push(
new textChangeChecker(this.labelNode, 0, aValue.length,
aValue, true));
break;
}
this.invoke = function setValue_invoke()
{
if (aValue === kNoValue)
this.labelNode.removeAttribute("value");
else
this.labelNode.setAttribute("value", aValue);
}
this.finalCheck = function setValue_finalCheck()
{
var tree =
{ LABEL: [
{ TEXT_LEAF: [ ] }
] };
testAccessibleTree(aID, tree);
}
this.getID = function setValue_getID()
{
return "set @value='" + aValue + "' for label " + prettyName(aID);
}
}
/**
* Change @crop attribute.
*/
function setCrop(aID, aCropValue, aRemovedText, aInsertedText)
{
this.labelNode = getNode(aID);
this.width = this.labelNode.boxObject.width;
this.charWidth = this.width / this.labelNode.value.length;
this.eventSeq = [
new textChangeChecker(this.labelNode, 0, -1, aRemovedText, false),
new textChangeChecker(this.labelNode, 0, -1, aInsertedText, true)
];
this.invoke = function setCrop_invoke()
{
if (!this.labelNode.hasAttribute("crop"))
this.labelNode.width = Math.floor(this.width - 2 * this.charWidth);
this.labelNode.setAttribute("crop", aCropValue);
}
this.getID = function setCrop_finalCheck()
{
return "set crop " + aCropValue;
}
}
////////////////////////////////////////////////////////////////////////////
// Test
gA11yEventDumpToConsole = true;
var gQueue = null;
function doTest()
{
gQueue = new eventQueue();
gQueue.push(new setValue("label", "shiroka strana", kRecreated));
gQueue.push(new setValue("label", "?<>!+_", kTextChanged, "shiroka strana"));
gQueue.push(new setValue("label", "", kTextRemoved, "?<>!+_"));
gQueue.push(new setValue("label", kNoValue, kRecreated));
gQueue.push(new setValue("descr", "hello world", kRecreated));
gQueue.push(new setValue("descr", "si_ya", kTextChanged, "hello world"));
gQueue.push(new setValue("descr", "", kTextRemoved, "si_ya"));
gQueue.push(new setValue("descr", kNoValue, kRecreated));
if (MAC) {
// "valuetocro" -> "…etocro"
gQueue.push(new setCrop("croplabel", "left", "valu", "…"));
// "…etocro", "val…cro"
gQueue.push(new setCrop("croplabel", "center", "…eto", "val…"));
} else {
// "valuetocro" -> "…uetocro"
gQueue.push(new setCrop("croplabel", "left", "val", "…"));
// "…uetocro" -> "valu…cro"
gQueue.push(new setCrop("croplabel", "center", "…ueto", "valu…"));
}
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<hbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=396166"
title="xul:label@value accessible should implement nsIAccessibleText">
Bug 396166
</a>
<br/>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<label id="label">hello</label>
<description id="descr">hello</description>
<hbox>
<label id="croplabel" value="valuetocro"
style="font-family: monospace;"/>
</hbox>
</vbox>
</hbox>
</window>

View file

@ -0,0 +1,202 @@
<?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 menu events testing for XUL menu">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript">
function openFileMenu()
{
this.eventSeq = [
new invokerChecker(EVENT_MENU_START, getNode("menubar")),
new invokerChecker(EVENT_MENUPOPUP_START, getNode("menupopup-file"))
// new invokerChecker(EVENT_FOCUS, getNode("menuitem-newtab")) intermitent failure
];
this.invoke = function openFileMenu_invoke()
{
synthesizeKey("F", { altKey: true, shiftKey: true });
}
this.getID = function openFileMenu_getID()
{
return "open file menu by alt+F press";
}
}
function openEditMenu()
{
this.eventSeq = [
new invokerChecker(EVENT_MENUPOPUP_END, getNode("menupopup-file")),
new invokerChecker(EVENT_MENUPOPUP_START, getNode("menupopup-edit"))
// new invokerChecker(EVENT_FOCUS, getNode("menuitem-undo")) intermitent failure
];
this.invoke = function openEditMenu_invoke()
{
synthesizeKey("VK_RIGHT", { });
}
this.getID = function openEditMenu_getID()
{
return "open edit menu by lef arrow press";
}
}
function closeEditMenu()
{
this.eventSeq = [
//new invokerChecker(EVENT_FOCUS, document), intermitent failure
new invokerChecker(EVENT_MENUPOPUP_END, getNode("menupopup-edit")),
new invokerChecker(EVENT_MENU_END, getNode("menubar"))
];
this.invoke = function closeEditMenu_invoke()
{
synthesizeKey("VK_ESCAPE", { });
}
this.getID = function closeEditMenu_getID()
{
return "close edit menu, leave menubar";
}
}
function focusFileMenu()
{
this.eventSeq = [
new invokerChecker(EVENT_MENU_START, getNode("menubar"))
// new invokerChecker(EVENT_FOCUS, getNode("menuitem-file")) //intermitent failure
];
this.invoke = function focusFileMenu_invoke()
{
synthesizeKey("VK_ALT", { });
}
this.getID = function focusFileMenu_getID()
{
return "activate menubar, focus file menu (atl press)";
}
}
function focusEditMenu()
{
this.eventSeq = [
new invokerChecker(EVENT_FOCUS, getNode("menuitem-edit"))
];
this.invoke = function focusEditMenu_invoke()
{
synthesizeKey("VK_RIGHT", { });
}
this.getID = function focusEditMenu_getID()
{
return "focus edit menu";
}
}
function leaveMenubar()
{
this.eventSeq = [
//new invokerChecker(EVENT_FOCUS, document), intermitent failure
new invokerChecker(EVENT_MENU_END, getNode("menubar"))
];
this.invoke = function leaveMenubar_invoke()
{
synthesizeKey("VK_ESCAPE", { });
}
this.getID = function leaveMenubar_getID()
{
return "leave menubar";
}
}
/**
* Do tests.
*/
//gA11yEventDumpID = "eventdump";
//gA11yEventDumpToConsole = true;
var gQueue = null;
function doTests()
{
if (!WIN) {
todo(false, "Enable this test on other platforms.");
SimpleTest.finish();
return;
}
todo(false,
"Fix intermitent failures. Focus may randomly occur before or after menupopup events!");
gQueue = new eventQueue();
gQueue.push(new openFileMenu());
gQueue.push(new openEditMenu());
gQueue.push(new closeEditMenu());
// Alt key is used to active menubar and focus menu item on Windows,
// other platforms requires setting a ui.key.menuAccessKeyFocuses
// preference.
if (WIN || LINUX) {
gQueue.push(new focusFileMenu());
gQueue.push(new focusEditMenu());
gQueue.push(new leaveMenubar());
}
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</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=615189"
title="Clean up FireAccessibleFocusEvent">
Mozilla Bug 615189
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
<vbox flex="1">
<menubar id="menubar">
<menu id="menuitem-file" label="File" accesskey="F">
<menupopup id="menupopup-file">
<menuitem id="menuitem-newtab" label="New Tab"/>
</menupopup>
</menu>
<menu id="menuitem-edit" label="Edit" accesskey="E">
<menupopup id="menupopup-edit">
<menuitem id="menuitem-undo" label="Undo"/>
</menupopup>
</menu>
</menubar>
<vbox id="eventdump" role="log"/>
</vbox>
</hbox>
</window>

View file

@ -0,0 +1,632 @@
<html>
<head>
<title>Accessible mutation events testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<style>
div.displayNone a { display:none; }
div.visibilityHidden a { visibility:hidden; }
</style>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
/**
* Invokers.
*/
var kNoEvents = 0;
var kShowEvent = 1;
var kHideEvent = 2;
var kReorderEvent = 4;
var kShowEvents = kShowEvent | kReorderEvent;
var kHideEvents = kHideEvent | kReorderEvent;
var kHideAndShowEvents = kHideEvents | kShowEvent;
/**
* Base class to test mutation a11y events.
*
* @param aNodeOrID [in] node invoker's action is executed for
* @param aEventTypes [in] events to register (see constants above)
* @param aDoNotExpectEvents [in] boolean indicates if events are expected
*/
function mutateA11yTree(aNodeOrID, aEventTypes, aDoNotExpectEvents)
{
// Interface
this.DOMNode = getNode(aNodeOrID);
this.doNotExpectEvents = aDoNotExpectEvents;
this.eventSeq = [];
this.unexpectedEventSeq = [];
/**
* Change default target (aNodeOrID) registered for the given event type.
*/
this.setTarget = function mutateA11yTree_setTarget(aEventType, aTarget)
{
var type = this.getA11yEventType(aEventType);
for (var idx = 0; idx < this.getEventSeq().length; idx++) {
if (this.getEventSeq()[idx].type == type) {
this.getEventSeq()[idx].target = aTarget;
return idx;
}
}
return -1;
}
/**
* Replace the default target currently registered for a given event type
* with the nodes in the targets array.
*/
this.setTargets = function mutateA11yTree_setTargets(aEventType, aTargets) {
var targetIdx = this.setTarget(aEventType, aTargets[0]);
var type = this.getA11yEventType(aEventType);
for (var i = 1; i < aTargets.length; i++) {
var checker = new invokerChecker(type, aTargets[i]);
this.getEventSeq().splice(++targetIdx, 0, checker);
}
}
// Implementation
this.getA11yEventType = function mutateA11yTree_getA11yEventType(aEventType)
{
if (aEventType == kReorderEvent)
return nsIAccessibleEvent.EVENT_REORDER;
if (aEventType == kHideEvent)
return nsIAccessibleEvent.EVENT_HIDE;
if (aEventType == kShowEvent)
return nsIAccessibleEvent.EVENT_SHOW;
}
this.getEventSeq = function mutateA11yTree_getEventSeq()
{
return this.doNotExpectEvents ? this.unexpectedEventSeq : this.eventSeq;
}
if (aEventTypes & kHideEvent) {
var checker = new invokerChecker(this.getA11yEventType(kHideEvent),
this.DOMNode);
this.getEventSeq().push(checker);
}
if (aEventTypes & kShowEvent) {
var checker = new invokerChecker(this.getA11yEventType(kShowEvent),
this.DOMNode);
this.getEventSeq().push(checker);
}
if (aEventTypes & kReorderEvent) {
var checker = new invokerChecker(this.getA11yEventType(kReorderEvent),
this.DOMNode.parentNode);
this.getEventSeq().push(checker);
}
}
/**
* Change CSS style for the given node.
*/
function changeStyle(aNodeOrID, aProp, aValue, aEventTypes)
{
this.__proto__ = new mutateA11yTree(aNodeOrID, aEventTypes, false);
this.invoke = function changeStyle_invoke()
{
this.DOMNode.style[aProp] = aValue;
}
this.getID = function changeStyle_getID()
{
return aNodeOrID + " change style " + aProp + " on value " + aValue;
}
}
/**
* Change class name for the given node.
*/
function changeClass(aParentNodeOrID, aNodeOrID, aClassName, aEventTypes)
{
this.__proto__ = new mutateA11yTree(aNodeOrID, aEventTypes, false);
this.invoke = function changeClass_invoke()
{
this.parentDOMNode.className = aClassName;
}
this.getID = function changeClass_getID()
{
return aNodeOrID + " change class " + aClassName;
}
this.parentDOMNode = getNode(aParentNodeOrID);
}
/**
* Clone the node and append it to its parent.
*/
function cloneAndAppendToDOM(aNodeOrID, aEventTypes,
aTargetsFunc, aReorderTargetFunc)
{
var eventTypes = aEventTypes || kShowEvents;
var doNotExpectEvents = (aEventTypes == kNoEvents);
this.__proto__ = new mutateA11yTree(aNodeOrID, eventTypes,
doNotExpectEvents);
this.invoke = function cloneAndAppendToDOM_invoke()
{
var newElm = this.DOMNode.cloneNode(true);
newElm.removeAttribute('id');
var targets = aTargetsFunc ?
aTargetsFunc.call(null, newElm) : [newElm];
this.setTargets(kShowEvent, targets);
if (aReorderTargetFunc) {
var reorderTarget = aReorderTargetFunc.call(null, this.DOMNode);
this.setTarget(kReorderEvent, reorderTarget);
}
this.DOMNode.parentNode.appendChild(newElm);
}
this.getID = function cloneAndAppendToDOM_getID()
{
return aNodeOrID + " clone and append to DOM.";
}
}
/**
* Removes the node from DOM.
*/
function removeFromDOM(aNodeOrID, aEventTypes,
aTargetsFunc, aReorderTargetFunc)
{
var eventTypes = aEventTypes || kHideEvents;
var doNotExpectEvents = (aEventTypes == kNoEvents);
this.__proto__ = new mutateA11yTree(aNodeOrID, eventTypes,
doNotExpectEvents);
this.invoke = function removeFromDOM_invoke()
{
this.DOMNode.parentNode.removeChild(this.DOMNode);
}
this.getID = function removeFromDOM_getID()
{
return prettyName(aNodeOrID) + " remove from DOM.";
}
if (aTargetsFunc && (eventTypes & kHideEvent))
this.setTargets(kHideEvent, aTargetsFunc.call(null, this.DOMNode));
if (aReorderTargetFunc && (eventTypes & kReorderEvent))
this.setTarget(kReorderEvent,
aReorderTargetFunc.call(null, this.DOMNode));
}
/**
* Clone the node and replace the original node by cloned one.
*/
function cloneAndReplaceInDOM(aNodeOrID)
{
this.__proto__ = new mutateA11yTree(aNodeOrID, kHideAndShowEvents,
false);
this.invoke = function cloneAndReplaceInDOM_invoke()
{
this.DOMNode.parentNode.replaceChild(this.newElm, this.DOMNode);
}
this.getID = function cloneAndReplaceInDOM_getID()
{
return aNodeOrID + " clone and replace in DOM.";
}
this.newElm = this.DOMNode.cloneNode(true);
this.newElm.removeAttribute('id');
this.setTarget(kShowEvent, this.newElm);
}
/**
* Trigger content insertion (flush layout), removal and insertion of
* the same element for the same parent.
*/
function test1(aContainerID)
{
this.divNode = document.createElement("div");
this.divNode.setAttribute("id", "div-test1");
this.containerNode = getNode(aContainerID);
this.eventSeq = [
new invokerChecker(EVENT_SHOW, this.divNode),
new invokerChecker(EVENT_REORDER, this.containerNode)
];
this.invoke = function test1_invoke()
{
this.containerNode.appendChild(this.divNode);
getComputedStyle(this.divNode, "").color;
this.containerNode.removeChild(this.divNode);
this.containerNode.appendChild(this.divNode);
}
this.getID = function test1_getID()
{
return "fuzzy test #1: content insertion (flush layout), removal and" +
"reinsertion";
}
}
/**
* Trigger content insertion (flush layout), removal and insertion of
* the same element for the different parents.
*/
function test2(aContainerID, aTmpContainerID)
{
this.divNode = document.createElement("div");
this.divNode.setAttribute("id", "div-test2");
this.containerNode = getNode(aContainerID);
this.tmpContainerNode = getNode(aTmpContainerID);
this.container = getAccessible(this.containerNode);
this.tmpContainer = getAccessible(this.tmpContainerNode);
this.eventSeq = [
new invokerChecker(EVENT_SHOW, this.divNode),
new invokerChecker(EVENT_REORDER, this.containerNode)
];
this.unexpectedEventSeq = [
new invokerChecker(EVENT_REORDER, this.tmpContainerNode)
];
this.invoke = function test2_invoke()
{
this.tmpContainerNode.appendChild(this.divNode);
getComputedStyle(this.divNode, "").color;
this.tmpContainerNode.removeChild(this.divNode);
this.containerNode.appendChild(this.divNode);
}
this.getID = function test2_getID()
{
return "fuzzy test #2: content insertion (flush layout), removal and" +
"reinsertion under another container";
}
}
/**
* Content insertion (flush layout) and then removal (nothing was changed).
*/
function test3(aContainerID)
{
this.divNode = document.createElement("div");
this.divNode.setAttribute("id", "div-test3");
this.containerNode = getNode(aContainerID);
this.unexpectedEventSeq = [
new invokerChecker(EVENT_SHOW, this.divNode),
new invokerChecker(EVENT_HIDE, this.divNode),
new invokerChecker(EVENT_REORDER, this.containerNode)
];
this.invoke = function test3_invoke()
{
this.containerNode.appendChild(this.divNode);
getComputedStyle(this.divNode, "").color;
this.containerNode.removeChild(this.divNode);
}
this.getID = function test3_getID()
{
return "fuzzy test #3: content insertion (flush layout) and removal";
}
}
function insertReferredElm(aContainerID)
{
this.containerNode = getNode(aContainerID);
this.eventSeq = [
new invokerChecker(EVENT_SHOW, function(aNode) { return aNode.firstChild; }, this.containerNode),
new invokerChecker(EVENT_SHOW, function(aNode) { return aNode.lastChild; }, this.containerNode),
new invokerChecker(EVENT_REORDER, this.containerNode)
];
this.invoke = function insertReferredElm_invoke()
{
this.containerNode.innerHTML =
"<span id='insertReferredElms_span'></span><input aria-labelledby='insertReferredElms_span'>";
}
this.getID = function insertReferredElm_getID()
{
return "insert inaccessible element and then insert referring element to make it accessible";
}
}
function showHiddenParentOfVisibleChild()
{
this.eventSeq = [
new invokerChecker(EVENT_HIDE, getNode("c4_child")),
new invokerChecker(EVENT_SHOW, getNode("c4_middle")),
new invokerChecker(EVENT_REORDER, getNode("c4"))
];
this.invoke = function showHiddenParentOfVisibleChild_invoke()
{
getNode("c4_middle").style.visibility = 'visible';
}
this.getID = function showHiddenParentOfVisibleChild_getID()
{
return "show hidden parent of visible child";
}
}
function hideNDestroyDoc()
{
this.txt = null;
this.eventSeq = [
new invokerChecker(EVENT_HIDE, function() { return this.txt; }.bind(this))
];
this.invoke = function hideNDestroyDoc_invoke()
{
this.txt = getAccessible('c5').firstChild.firstChild;
this.txt.DOMNode.parentNode.removeChild(this.txt.DOMNode);
}
this.check = function hideNDestroyDoc_check()
{
getNode('c5').parentNode.removeChild(getNode('c5'));
}
this.getID = function hideNDestroyDoc_getID()
{
return "remove text node and destroy a document on hide event";
}
}
function hideHideNDestroyDoc()
{
this.target = null;
this.eventSeq = [
new invokerChecker(EVENT_HIDE, function() { return this.target; }.bind(this))
];
this.invoke = function hideHideNDestroyDoc_invoke()
{
var doc = getAccessible('c6').firstChild;
var l1 = doc.firstChild;
this.target = l1.firstChild;
var l2 = doc.lastChild;
l1.DOMNode.removeChild(l1.DOMNode.firstChild);
l2.DOMNode.removeChild(l2.DOMNode.firstChild);
}
this.check = function hideHideNDestroyDoc_check()
{
getNode('c6').parentNode.removeChild(getNode('c6'));
}
this.getID = function hideHideNDestroyDoc_getID()
{
return "remove text nodes (2 events in the queue) and destroy a document on first hide event";
}
}
/**
* Target getters.
*/
function getFirstChild(aNode)
{
return [aNode.firstChild];
}
function getLastChild(aNode)
{
return [aNode.lastChild];
}
function getNEnsureFirstChild(aNode)
{
var node = aNode.firstChild;
getAccessible(node);
return [node];
}
function getNEnsureChildren(aNode)
{
var children = [];
var node = aNode.firstChild;
do {
children.push(node);
getAccessible(node);
node = node.nextSibling;
} while (node);
return children;
}
function getParent(aNode)
{
return aNode.parentNode;
}
//gA11yEventDumpToConsole = true; // debug stuff
//enableLogging("events,verbose");
/**
* Do tests.
*/
var gQueue = null;
function doTests()
{
gQueue = new eventQueue();
// Show/hide events by changing of display style of accessible DOM node
// from 'inline' to 'none', 'none' to 'inline'.
var id = "link1";
getAccessible(id); // ensure accessible is created
gQueue.push(new changeStyle(id, "display", "none", kHideEvents));
gQueue.push(new changeStyle(id, "display", "inline", kShowEvents));
// Show/hide events by changing of visibility style of accessible DOM node
// from 'visible' to 'hidden', 'hidden' to 'visible'.
var id = "link2";
getAccessible(id);
gQueue.push(new changeStyle(id, "visibility", "hidden", kHideEvents));
gQueue.push(new changeStyle(id, "visibility", "visible", kShowEvents));
// Show/hide events by changing of display style of accessible DOM node
// from 'inline' to 'block', 'block' to 'inline'.
var id = "link3";
getAccessible(id); // ensure accessible is created
gQueue.push(new changeStyle(id, "display", "block", kHideAndShowEvents));
gQueue.push(new changeStyle(id, "display", "inline", kHideAndShowEvents));
// Show/hide events by changing of visibility style of accessible DOM node
// from 'collapse' to 'visible', 'visible' to 'collapse'.
var id = "link4";
gQueue.push(new changeStyle(id, "visibility", "visible", kShowEvents));
gQueue.push(new changeStyle(id, "visibility", "collapse", kHideEvents));
// Show/hide events by adding new accessible DOM node and removing old one.
var id = "link5";
gQueue.push(new cloneAndAppendToDOM(id));
gQueue.push(new removeFromDOM(id));
// No show/hide events by adding new not accessible DOM node and removing
// old one, no reorder event for their parent.
var id = "child1";
gQueue.push(new cloneAndAppendToDOM(id, kNoEvents));
gQueue.push(new removeFromDOM(id, kNoEvents));
// Show/hide events by adding new accessible DOM node and removing
// old one, there is reorder event for their parent.
var id = "child2";
gQueue.push(new cloneAndAppendToDOM(id));
gQueue.push(new removeFromDOM(id));
// Show/hide events by adding new DOM node containing accessible DOM and
// removing old one, there is reorder event for their parent.
var id = "child3";
gQueue.push(new cloneAndAppendToDOM(id, kShowEvents, getFirstChild,
getParent));
// Hide event for accessible child of unaccessible removed DOM node and
// reorder event for its parent.
gQueue.push(new removeFromDOM(id, kHideEvents,
getNEnsureFirstChild, getParent));
// Hide events for accessible children of unaccessible removed DOM node
// and reorder event for its parent.
gQueue.push(new removeFromDOM("child4", kHideEvents,
getNEnsureChildren, getParent));
// Show/hide events by creating new accessible DOM node and replacing
// old one.
getAccessible("link6"); // ensure accessible is created
gQueue.push(new cloneAndReplaceInDOM("link6"));
// Show/hide events by changing class name on the parent node.
gQueue.push(new changeClass("container2", "link7", "", kShowEvents));
gQueue.push(new changeClass("container2", "link7", "displayNone",
kHideEvents));
gQueue.push(new changeClass("container3", "link8", "", kShowEvents));
gQueue.push(new changeClass("container3", "link8", "visibilityHidden",
kHideEvents));
gQueue.push(new test1("testContainer"));
gQueue.push(new test2("testContainer", "testContainer2"));
gQueue.push(new test2("testContainer", "testNestedContainer"));
gQueue.push(new test3("testContainer"));
gQueue.push(new insertReferredElm("testContainer3"));
gQueue.push(new showHiddenParentOfVisibleChild());
gQueue.push(new hideNDestroyDoc());
gQueue.push(new hideHideNDestroyDoc());
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=469985"
title=" turn the test from bug 354745 into mochitest">
Mozilla Bug 469985</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=472662"
title="no reorder event when html:link display property is changed from 'none' to 'inline'">
Mozilla Bug 472662</a>
<a target="_blank"
title="Rework accessible tree update code"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
Mozilla Bug 570275</a>
<a target="_blank"
title="Develop a way to handle visibility style"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=606125">
Mozilla Bug 606125</a>
<a target="_blank"
title="Update accessible tree on content insertion after layout"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=498015">
Mozilla Bug 498015</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="eventdump"></div>
<div id="testContainer">
<a id="link1" href="http://www.google.com">Link #1</a>
<a id="link2" href="http://www.google.com">Link #2</a>
<a id="link3" href="http://www.google.com">Link #3</a>
<a id="link4" href="http://www.google.com" style="visibility:collapse">Link #4</a>
<a id="link5" href="http://www.google.com">Link #5</a>
<div id="container" role="list">
<span id="child1"></span>
<span id="child2" role="listitem"></span>
<span id="child3"><span role="listitem"></span></span>
<span id="child4"><span id="child4_1" role="listitem"></span><span id="child4_2" role="listitem"></span></span>
</div>
<a id="link6" href="http://www.google.com">Link #6</a>
<div id="container2" class="displayNone"><a id="link7">Link #7</a></div>
<div id="container3" class="visibilityHidden"><a id="link8">Link #8</a></div>
<div id="testNestedContainer"></div>
</div>
<div id="testContainer2"></div>
<div id="testContainer3"></div>
<div id="c4">
<div style="visibility:hidden" id="c4_middle">
<div style="visibility:visible" id="c4_child"></div>
</div>
<iframe id="c5" src="data:text/html,hey"></iframe>
<iframe id="c6" src="data:text/html,<label>l</label><label>l</label>"></iframe>
</body>
</html>

View file

@ -0,0 +1,97 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Accessible mutation events testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<bindings xmlns="http://www.mozilla.org/xbl" >
<binding id="button">
<content>
<button xmlns="http://www.w3.org/1999/xhtml">a button</button>
</content>
</binding>
</bindings>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
/**
* Insert a not accessible bound element containing an accessible element
* in anonymous content.
*/
function insertBinding(aContainerID)
{
this.containerNode = getNode(aContainerID);
function getButtonFromBinding(aNode)
{
try { return document.getAnonymousNodes(aNode.firstChild)[0]; }
catch (e) { return null; }
}
this.eventSeq = [
new invokerChecker(EVENT_SHOW, getButtonFromBinding, this.containerNode),
new invokerChecker(EVENT_REORDER, this.containerNode)
];
this.invoke = function insertBinding_invoke()
{
var span = document.createElement("span");
span.setAttribute("style", "-moz-binding:url(#button)");
this.containerNode.appendChild(span);
}
this.getID = function insertBinding_getID()
{
return "insert button binding";
}
}
/**
* Do tests.
*/
var gQueue = null;
//gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true;
function doTests()
{
gQueue = new eventQueue();
gQueue.push(new insertBinding("testContainer"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=646369"
title="UpdateTree should rely on accessible tree walker rather than DOM tree traversal">
Mozilla Bug 646369</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="eventdump"></div>
<div id="testContainer"></div>
</body>
</html>

View file

@ -0,0 +1,123 @@
<html>
<head>
<title>Accessible name change event testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript">
////////////////////////////////////////////////////////////////////////////
// Invokers
function setAttr(aID, aAttr, aValue, aChecker)
{
this.eventSeq = [ aChecker ];
this.invoke = function setAttr_invoke()
{
getNode(aID).setAttribute(aAttr, aValue);
}
this.getID = function setAttr_getID()
{
return "set attr '" + aAttr + "', value '" + aValue + "'";
}
}
/**
* No name change on an accessible, because the accessible is recreated.
*/
function setAttr_recreate(aID, aAttr, aValue)
{
this.eventSeq = [
new invokerChecker(EVENT_HIDE, getAccessible(aID)),
new invokerChecker(EVENT_SHOW, aID)
];
this.invoke = function setAttr_recreate_invoke()
{
todo(false, "No accessible recreation should happen, just name change event");
getNode(aID).setAttribute(aAttr, aValue);
}
this.getID = function setAttr_recreate_getID()
{
return "set attr '" + aAttr + "', value '" + aValue + "'";
}
}
////////////////////////////////////////////////////////////////////////////
// Do tests
//gA11yEventDumpToConsole = true; // debuggin
var gQueue = null;
function doTests()
{
gQueue = new eventQueue();
gQueue.push(new setAttr("tst1", "aria-label", "hi",
new invokerChecker(EVENT_NAME_CHANGE, "tst1")));
gQueue.push(new setAttr("tst1", "aria-labelledby", "display",
new unexpectedInvokerChecker(EVENT_NAME_CHANGE, "tst1")));
gQueue.push(new setAttr("tst1", "alt", "alt",
new unexpectedInvokerChecker(EVENT_NAME_CHANGE, "tst1")));
gQueue.push(new setAttr("tst1", "title", "title",
new unexpectedInvokerChecker(EVENT_NAME_CHANGE, "tst1")));
gQueue.push(new setAttr("tst2", "aria-labelledby", "display",
new invokerChecker(EVENT_NAME_CHANGE, "tst2")));
gQueue.push(new setAttr("tst2", "alt", "alt",
new unexpectedInvokerChecker(EVENT_NAME_CHANGE, "tst2")));
gQueue.push(new setAttr("tst2", "title", "title",
new unexpectedInvokerChecker(EVENT_NAME_CHANGE, "tst2")));
gQueue.push(new setAttr_recreate("tst3", "alt", "alt"));
gQueue.push(new setAttr("tst3", "title", "title",
new unexpectedInvokerChecker(EVENT_NAME_CHANGE, "tst3")));
gQueue.push(new setAttr("tst4", "title", "title",
new invokerChecker(EVENT_NAME_CHANGE, "tst4")));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=991969"
title="Event not fired when description changes">
Bug 991969
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<img id="tst1">
<img id="tst2">
<img id="tst3">
<img id="tst4">
<div id="eventdump"></div>
</body>
</html>

View file

@ -0,0 +1,92 @@
<?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">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/chrome-harness.js"/>
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript">
<![CDATA[
/**
* Check name changed a11y event.
*/
function nameChangeChecker(aMsg, aID)
{
this.type = EVENT_NAME_CHANGE;
function targetGetter()
{
return getAccessible(aID);
}
Object.defineProperty(this, "target", { get: targetGetter });
this.getID = function getID()
{
return aMsg + " name changed";
}
}
function changeRichListItemChild()
{
this.invoke = function changeRichListItemChild_invoke()
{
getNode('childcontent').setAttribute('value', 'Changed.');
}
this.eventSeq =
[
new nameChangeChecker("changeRichListItemChild: ", "listitem")
];
this.getID = function changeRichListItemChild_getID()
{
return "changeRichListItemChild";
}
}
function doTest()
{
var queue = new eventQueue();
queue.push(new changeRichListItemChild());
queue.invoke();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
]]>
</script>
<vbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=986054"
title="Propagate name change events">
Mozilla Bug 986054
</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<richlistbox>
<richlistitem id="listitem">
<description id="childcontent" value="This will be changed."/>
</richlistitem>
</richlistbox>
</vbox>
</window>

View file

@ -0,0 +1,131 @@
<?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">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/chrome-harness.js"/>
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../role.js" />
<script type="application/javascript"
src="../states.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript"
src="../browser.js"></script>
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Tests
function getAnchorJumpInTabDocument(aTabIdx)
{
var tabDoc = aTabIdx ? tabDocumentAt(aTabIdx) : currentTabDocument();
return tabDoc.querySelector("a[name='link1']");
}
function loadTab(aURL)
{
this.eventSeq = [
new asyncInvokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, currentTabDocument),
new asyncInvokerChecker(EVENT_SCROLLING_START, getAnchorJumpInTabDocument)
];
this.invoke = function loadTab_invoke()
{
tabBrowser().loadURI(aURL);
}
this.getID = function loadTab_getID()
{
return "load tab: " + aURL;
}
}
function loadTabInBackground(aURL)
{
this.eventSeq = [
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, tabDocumentAt, 1)
];
this.unexpectedEventSeq = [
new invokerChecker(EVENT_SCROLLING_START, getAnchorJumpInTabDocument, 1)
];
this.invoke = function loadTabInBackground_invoke()
{
tabBrowser().loadOneTab(aURL, null, "", null, true);
}
this.getID = function loadTabInBackground_getID()
{
return "load tab in background: " + aURL;
}
}
function switchToBackgroundTab()
{
this.eventSeq = [
new invokerChecker(EVENT_SCROLLING_START, getAnchorJumpInTabDocument)
];
this.invoke = function switchToBackgroundTab_invoke()
{
tabBrowser().selectTabAtIndex(1);
}
this.getID = function switchToBackgroundTab_getID()
{
return "switch to background tab";
}
}
//gA11yEventDumpToConsole = true; // debug stuff
var gQueue = null;
function doTest()
{
gQueue = new eventQueue();
var url = "http://mochi.test:8888/a11y/accessible/tests/mochitest/events/scroll.html#link1";
gQueue.push(new loadTab(url));
gQueue.push(new loadTabInBackground(url));
gQueue.push(new switchToBackgroundTab());
gQueue.onFinish = function() { closeBrowserWindow(); }
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
openBrowserWindow(doTest);
]]>
</script>
<vbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=691734"
title="Make sure scrolling start event is fired when document receive focus">
Mozilla Bug 691734
</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox id="eventdump"></vbox>
</vbox>
</window>

View file

@ -0,0 +1,91 @@
<?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">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/chrome-harness.js"/>
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../role.js" />
<script type="application/javascript"
src="../states.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript"
src="../browser.js"></script>
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Tests
function getAnchorJumpInTabDocument(aTabIdx)
{
var tabDoc = aTabIdx ? tabDocumentAt(aTabIdx) : currentTabDocument();
return tabDoc.querySelector("h1[id='heading_1']");
}
function loadTab(aURL)
{
this.eventSeq = [
new asyncInvokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, currentTabDocument),
new asyncCaretMoveChecker(0, getAnchorJumpInTabDocument)
];
this.invoke = function loadTab_invoke()
{
tabBrowser().loadURI(aURL);
}
this.getID = function loadTab_getID()
{
return "load tab: " + aURL;
}
}
//gA11yEventDumpToConsole = true; // debug stuff
var gQueue = null;
function doTest()
{
gQueue = new eventQueue();
var url = "http://mochi.test:8888/a11y/accessible/tests/mochitest/events/scroll.html#heading_1";
gQueue.push(new loadTab(url));
gQueue.onFinish = function() { closeBrowserWindow(); }
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
openBrowserWindow(doTest);
]]>
</script>
<vbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1056459"
title="Make sure caret move event is fired when document receive focus">
Mozilla Bug 1056459
</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox id="eventdump"></vbox>
</vbox>
</window>

View file

@ -0,0 +1,118 @@
<html>
<head>
<title>Accessible selection event testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript">
////////////////////////////////////////////////////////////////////////////
// Invokers
////////////////////////////////////////////////////////////////////////////
// Do tests
//gA11yEventDumpToConsole = true; // debuggin
var gQueue = null;
function doTests()
{
gQueue = new eventQueue();
// open combobox
gQueue.push(new synthClick("combobox",
new invokerChecker(EVENT_FOCUS, "cb1_item1")));
gQueue.push(new synthDownKey("cb1_item1",
selChangeSeq("cb1_item1", "cb1_item2")));
// closed combobox
gQueue.push(new synthEscapeKey("combobox",
new invokerChecker(EVENT_FOCUS, "combobox")));
gQueue.push(new synthDownKey("cb1_item2",
selChangeSeq("cb1_item2", "cb1_item3")));
// listbox
gQueue.push(new synthClick("lb1_item1",
new invokerChecker(EVENT_SELECTION, "lb1_item1")));
gQueue.push(new synthDownKey("lb1_item1",
selChangeSeq("lb1_item1", "lb1_item2")));
// multiselectable listbox
gQueue.push(new synthClick("lb2_item1",
selChangeSeq(null, "lb2_item1")));
gQueue.push(new synthDownKey("lb2_item1",
selAddSeq("lb2_item2"),
{ shiftKey: true }));
gQueue.push(new synthUpKey("lb2_item2",
selRemoveSeq("lb2_item2"),
{ shiftKey: true }));
gQueue.push(new synthKey("lb2_item1", " ", { ctrlKey: true },
selRemoveSeq("lb2_item1")));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=414302"
title="Incorrect selection events in HTML, XUL and ARIA">
Bug 414302
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=810268"
title="There's no way to know unselected item when selection in single selection was changed">
Bug 810268
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<select id="combobox">
<option id="cb1_item1" value="mushrooms">mushrooms
<option id="cb1_item2" value="greenpeppers">green peppers
<option id="cb1_item3" value="onions" id="onions">onions
<option id="cb1_item4" value="tomatoes">tomatoes
<option id="cb1_item5" value="olives">olives
</select>
<select id="listbox" size=5>
<option id="lb1_item1" value="mushrooms">mushrooms
<option id="lb1_item2" value="greenpeppers">green peppers
<option id="lb1_item3" value="onions" id="onions">onions
<option id="lb1_item4" value="tomatoes">tomatoes
<option id="lb1_item5" value="olives">olives
</select>
<p>Pizza</p>
<select id="listbox2" multiple size=5>
<option id="lb2_item1" value="mushrooms">mushrooms
<option id="lb2_item2" value="greenpeppers">green peppers
<option id="lb2_item3" value="onions" id="onions">onions
<option id="lb2_item4" value="tomatoes">tomatoes
<option id="lb2_item5" value="olives">olives
</select>
</body>
</html>

View file

@ -0,0 +1,255 @@
<?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="Selection event tests">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../role.js" />
<script type="application/javascript"
src="../states.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript">
function advanceTab(aTabsID, aDirection, aNextTabID)
{
var eventSeq1 = [
new invokerChecker(EVENT_SELECTION, aNextTabID)
]
defineScenario(this, eventSeq1);
var eventSeq2 = [
new invokerChecker(EVENT_HIDE, getAccessible(aNextTabID)),
new invokerChecker(EVENT_SHOW, aNextTabID)
];
defineScenario(this, eventSeq2);
this.invoke = function advanceTab_invoke()
{
todo(false, "No accessible recreation should happen, just selection event");
getNode(aTabsID).advanceSelectedTab(aDirection, true);
}
this.getID = function synthFocus_getID()
{
return "advanceTab on " + prettyName(aTabsID) + " to " + prettyName(aNextTabID);
}
}
function select4FirstItems(aID)
{
this.listboxNode = getNode(aID);
this.eventSeq = [
new invokerChecker(EVENT_SELECTION_ADD, this.listboxNode.getItemAtIndex(0)),
new invokerChecker(EVENT_SELECTION_ADD, this.listboxNode.getItemAtIndex(1)),
new invokerChecker(EVENT_SELECTION_ADD, this.listboxNode.getItemAtIndex(2)),
new invokerChecker(EVENT_SELECTION_ADD, this.listboxNode.getItemAtIndex(3))
];
this.invoke = function select4FirstItems_invoke()
{
synthesizeKey("VK_DOWN", { shiftKey: true }); // selects two items
synthesizeKey("VK_DOWN", { shiftKey: true });
synthesizeKey("VK_DOWN", { shiftKey: true });
}
this.getID = function select4FirstItems_getID()
{
return "select 4 first items for " + prettyName(aID);
}
}
function unselect4FirstItems(aID)
{
this.listboxNode = getNode(aID);
this.eventSeq = [
new invokerChecker(EVENT_SELECTION_REMOVE, this.listboxNode.getItemAtIndex(3)),
new invokerChecker(EVENT_SELECTION_REMOVE, this.listboxNode.getItemAtIndex(2)),
new invokerChecker(EVENT_SELECTION_REMOVE, this.listboxNode.getItemAtIndex(1)),
new invokerChecker(EVENT_SELECTION_REMOVE, this.listboxNode.getItemAtIndex(0))
];
this.invoke = function unselect4FirstItems_invoke()
{
synthesizeKey("VK_UP", { shiftKey: true });
synthesizeKey("VK_UP", { shiftKey: true });
synthesizeKey("VK_UP", { shiftKey: true });
synthesizeKey(" ", { ctrlKey: true }); // unselect first item
}
this.getID = function unselect4FirstItems_getID()
{
return "unselect 4 first items for " + prettyName(aID);
}
}
function selectAllItems(aID)
{
this.listboxNode = getNode(aID);
this.eventSeq = [
new invokerChecker(EVENT_SELECTION_WITHIN, getAccessible(this.listboxNode))
];
this.invoke = function selectAllItems_invoke()
{
synthesizeKey("VK_END", { shiftKey: true });
}
this.getID = function selectAllItems_getID()
{
return "select all items for " + prettyName(aID);
}
}
function unselectAllItemsButFirst(aID)
{
this.listboxNode = getNode(aID);
this.eventSeq = [
new invokerChecker(EVENT_SELECTION_WITHIN, getAccessible(this.listboxNode))
];
this.invoke = function unselectAllItemsButFirst_invoke()
{
synthesizeKey("VK_HOME", { shiftKey: true });
}
this.getID = function unselectAllItemsButFirst_getID()
{
return "unselect all items for " + prettyName(aID);
}
}
function unselectSelectItem(aID)
{
this.listboxNode = getNode(aID);
this.eventSeq = [
new invokerChecker(EVENT_SELECTION_REMOVE, this.listboxNode.getItemAtIndex(0)),
new invokerChecker(EVENT_SELECTION_ADD, this.listboxNode.getItemAtIndex(0))
];
this.invoke = function unselectSelectItem_invoke()
{
synthesizeKey(" ", { ctrlKey: true }); // select item
synthesizeKey(" ", { ctrlKey: true }); // unselect item
}
this.getID = function unselectSelectItem_getID()
{
return "unselect and then select first item for " + prettyName(aID);
}
}
/**
* Do tests.
*/
var gQueue = null;
//enableLogging("events");
//gA11yEventDumpToConsole = true; // debuggin
function doTests()
{
gQueue = new eventQueue();
//////////////////////////////////////////////////////////////////////////
// tabbox
gQueue.push(new advanceTab("tabs", 1, "tab3"));
//////////////////////////////////////////////////////////////////////////
// listbox
gQueue.push(new synthClick("lb1_item1",
new invokerChecker(EVENT_SELECTION, "lb1_item1")));
gQueue.push(new synthDownKey("lb1_item1",
new invokerChecker(EVENT_SELECTION, "lb1_item2")));
//////////////////////////////////////////////////////////////////////////
// multiselectable listbox
gQueue.push(new synthClick("lb2_item1",
new invokerChecker(EVENT_SELECTION, "lb2_item1")));
gQueue.push(new synthDownKey("lb2_item1",
new invokerChecker(EVENT_SELECTION_ADD, "lb2_item2"),
{ shiftKey: true }));
gQueue.push(new synthUpKey("lb2_item2",
new invokerChecker(EVENT_SELECTION_REMOVE, "lb2_item2"),
{ shiftKey: true }));
gQueue.push(new synthKey("lb2_item1", " ", { ctrlKey: true },
new invokerChecker(EVENT_SELECTION_REMOVE, "lb2_item1")));
//////////////////////////////////////////////////////////////////////////
// selection event coalescence
// fire 4 selection_add events
gQueue.push(new select4FirstItems("listbox2"));
// fire 4 selection_remove events
gQueue.push(new unselect4FirstItems("listbox2"));
// fire selection_within event
gQueue.push(new selectAllItems("listbox2"));
// fire selection_within event
gQueue.push(new unselectAllItemsButFirst("listbox2"));
// fire selection_remove/add events
gQueue.push(new unselectSelectItem("listbox2"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</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=414302"
title="Incorrect selection events in HTML, XUL and ARIA">
Mozilla Bug 414302
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
<tabbox id="tabbox" selectedIndex="1">
<tabs id="tabs">
<tab id="tab1" label="tab1"/>
<tab id="tab2" label="tab2"/>
<tab id="tab3" label="tab3"/>
<tab id="tab4" label="tab4"/>
</tabs>
<tabpanels>
<tabpanel><!-- tabpanel First elements go here --></tabpanel>
<tabpanel><button id="b1" label="b1"/></tabpanel>
<tabpanel><button id="b2" label="b2"/></tabpanel>
<tabpanel></tabpanel>
</tabpanels>
</tabbox>
<listbox id="listbox">
<listitem id="lb1_item1" label="item1"/>
<listitem id="lb1_item2" label="item2"/>
</listbox>
<listbox id="listbox2" seltype="multiple">
<listitem id="lb2_item1" label="item1"/>
<listitem id="lb2_item2" label="item2"/>
<listitem id="lb2_item3" label="item3"/>
<listitem id="lb2_item4" label="item4"/>
<listitem id="lb2_item5" label="item5"/>
<listitem id="lb2_item6" label="item6"/>
<listitem id="lb2_item7" label="item7"/>
</listbox>
</hbox>
</window>

View file

@ -0,0 +1,127 @@
<html>
<head>
<title>ARIA selection event testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript">
////////////////////////////////////////////////////////////////////////////
// Invokers
function selectItem(aSelectID, aItemID)
{
this.selectNode = getNode(aSelectID);
this.itemNode = getNode(aItemID);
this.eventSeq = [
new invokerChecker(EVENT_SELECTION, aItemID)
];
this.invoke = function selectItem_invoke() {
var itemNode = this.selectNode.querySelector("*[aria-selected='true']");
if (itemNode)
itemNode.removeAttribute("aria-selected");
this.itemNode.setAttribute("aria-selected", "true");
}
this.getID = function selectItem_getID()
{
return "select item " + prettyName(aItemID);
}
}
////////////////////////////////////////////////////////////////////////////
// Do tests
var gQueue = null;
//gA11yEventDumpToConsole = true; // debug stuff
function doTests()
{
gQueue = new eventQueue();
gQueue.push(new selectItem("tablist", "tab1"));
gQueue.push(new selectItem("tablist", "tab2"));
gQueue.push(new selectItem("tree", "treeitem1"));
gQueue.push(new selectItem("tree", "treeitem1a"));
gQueue.push(new selectItem("tree", "treeitem1a1"));
gQueue.push(new selectItem("tree2", "tree2item1"));
gQueue.push(new selectItem("tree2", "tree2item1a"));
gQueue.push(new selectItem("tree2", "tree2item1a1"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=569653"
title="Make selection events async">
Mozilla Bug 569653
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=804040"
title="Selection event not fired when selection of ARIA tab changes">
Mozilla Bug 804040
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div role="tablist" id="tablist">
<div role="tab" id="tab1">tab1</div>
<div role="tab" id="tab2">tab2</div>
</div>
<div id="tree" role="tree">
<div id="treeitem1" role="treeitem">Canada
<div id="treeitem1a" role="treeitem">- Ontario
<div id="treeitem1a1" role="treeitem">-- Toronto</div>
</div>
<div id="treeitem1b" role="treeitem">- Manitoba</div>
</div>
<div id="treeitem2" role="treeitem">Germany</div>
<div id="treeitem3" role="treeitem">Russia</div>
</div>
<div id="tree2" role="tree" aria-multiselectable="true">
<div id="tree2item1" role="treeitem">Canada
<div id="tree2item1a" role="treeitem">- Ontario
<div id="tree2item1a1" role="treeitem">-- Toronto</div>
</div>
<div id="tree2item1b" role="treeitem">- Manitoba</div>
</div>
<div id="tree2item2" role="treeitem">Germany</div>
<div id="tree2item3" role="treeitem">Russia</div>
</div>
<div id="eventdump"></div>
</body>
</html>

View file

@ -0,0 +1,287 @@
<html>
<head>
<title>Accessible state change event testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript">
////////////////////////////////////////////////////////////////////////////
// Invokers
function makeEditableDoc(aDocNode, aIsEnabled)
{
this.DOMNode = aDocNode;
this.invoke = function editabledoc_invoke() {
// Note: this should fire an EVENT_STATE_CHANGE
this.DOMNode.designMode = 'on';
};
this.check = function editabledoc_check(aEvent) {
testStates(aDocNode, 0, EXT_STATE_EDITABLE);
var event = null;
try {
var event = aEvent.QueryInterface(nsIAccessibleStateChangeEvent);
} catch (e) {
ok(false, "State change event was expected");
}
if (!event) { return; }
ok(event.isExtraState, "Extra state change was expected");
is(event.state, EXT_STATE_EDITABLE, "Wrong state of statechange event");
ok(event.isEnabled, "Expected editable state to be enabled");
}
this.getID = function editabledoc_getID() {
return prettyName(aDocNode) + " editable state changed";
};
}
function invalidInput(aNodeOrID)
{
this.DOMNode = getNode(aNodeOrID);
this.invoke = function invalidInput_invoke() {
// Note: this should fire an EVENT_STATE_CHANGE
this.DOMNode.value = "I am not an email";
};
this.check = function invalidInput_check() {
testStates(aNodeOrID, STATE_INVALID);
};
this.getID = function invalidInput_getID() {
return prettyName(aNodeOrID) + " became invalid";
};
}
function changeCheckInput(aID, aIsChecked)
{
this.DOMNode = getNode(aID);
this.eventSeq = [
new stateChangeChecker(STATE_CHECKED, false, aIsChecked, this.DOMNode)
];
this.invoke = function changeCheckInput_invoke()
{
this.DOMNode.checked = aIsChecked;
}
this.getID = function changeCheckInput_getID()
{
return "change checked state to '" + aIsChecked + "' for " +
prettyName(aID);
}
}
function stateChangeOnFileInput(aID, aAttr, aValue,
aState, aIsExtraState, aIsEnabled)
{
this.fileControlNode = getNode(aID);
this.fileControl = getAccessible(this.fileControlNode);
this.browseButton = this.fileControl.firstChild;
// No state change events on the label.
this.invoke = function stateChangeOnFileInput_invoke()
{
this.fileControlNode.setAttribute(aAttr, aValue);
}
this.eventSeq = [
new stateChangeChecker(aState, aIsExtraState, aIsEnabled, this.fileControl),
new stateChangeChecker(aState, aIsExtraState, aIsEnabled, this.browseButton)
];
this.getID = function stateChangeOnFileInput_getID()
{
return "inherited state change on file input on attribute '" + aAttr + "' change";
}
}
function dupeStateChange(aID, aAttr, aValue,
aState, aIsExtraState, aIsEnabled)
{
this.eventSeq = [
new stateChangeChecker(aState, aIsExtraState, aIsEnabled, getNode(aID))
];
this.invoke = function dupeStateChange_invoke()
{
getNode(aID).setAttribute(aAttr, aValue);
getNode(aID).setAttribute(aAttr, aValue);
}
this.getID = function dupeStateChange_getID()
{
return "duped state change events";
}
}
function oppositeStateChange(aID, aAttr, aState, aIsExtraState)
{
this.eventSeq = [ ];
this.unexpectedEventSeq = [
new stateChangeChecker(aState, aIsExtraState, false, getNode(aID)),
new stateChangeChecker(aState, aIsExtraState, true, getNode(aID))
];
this.invoke = function oppositeStateChange_invoke()
{
getNode(aID).setAttribute(aAttr, "false");
getNode(aID).setAttribute(aAttr, "true");
}
this.getID = function oppositeStateChange_getID()
{
return "opposite state change events";
}
}
/**
* Change concomitant ARIA and native attribute at once.
*/
function echoingStateChange(aID, aARIAAttr, aAttr, aValue,
aState, aIsExtraState, aIsEnabled)
{
this.eventSeq = [
new stateChangeChecker(aState, aIsExtraState, aIsEnabled, getNode(aID))
];
this.invoke = function echoingStateChange_invoke()
{
if (aValue == null) {
getNode(aID).removeAttribute(aARIAAttr);
getNode(aID).removeAttribute(aAttr);
} else {
getNode(aID).setAttribute(aARIAAttr, aValue);
getNode(aID).setAttribute(aAttr, aValue);
}
}
this.getID = function echoingStateChange_getID()
{
return "enchoing ARIA and native attributes change";
}
}
////////////////////////////////////////////////////////////////////////////
// Do tests
var gQueue = null;
// var gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true; // debug stuff
function doTests()
{
gQueue = new eventQueue(nsIAccessibleEvent.EVENT_STATE_CHANGE);
// Test delayed editable state change
var doc = document.getElementById("iframe").contentDocument;
gQueue.push(new makeEditableDoc(doc));
// invalid state change
gQueue.push(new invalidInput("email"));
// checked state change
gQueue.push(new changeCheckInput("checkbox", true));
gQueue.push(new changeCheckInput("checkbox", false));
gQueue.push(new changeCheckInput("radio", true));
gQueue.push(new changeCheckInput("radio", false));
// file input inherited state changes
gQueue.push(new stateChangeOnFileInput("file", "aria-busy", "true",
STATE_BUSY, false, true));
gQueue.push(new stateChangeOnFileInput("file", "aria-required", "true",
STATE_REQUIRED, false, true));
gQueue.push(new stateChangeOnFileInput("file", "aria-invalid", "true",
STATE_INVALID, false, true));
gQueue.push(new dupeStateChange("div", "aria-busy", "true",
STATE_BUSY, false, true));
gQueue.push(new oppositeStateChange("div", "aria-busy",
STATE_BUSY, false));
gQueue.push(new echoingStateChange("text1", "aria-disabled", "disabled", "true",
EXT_STATE_ENABLED, true, false));
gQueue.push(new echoingStateChange("text1", "aria-disabled", "disabled", null,
EXT_STATE_ENABLED, true, true));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=564471"
title="Make state change events async">
Bug 564471
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=555728"
title="Fire a11y event based on HTML5 constraint validation">
Bug 555728
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=699017"
title="File input control should be propogate states to descendants">
Bug 699017
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=788389"
title="Fire statechange event whenever checked state is changed not depending on focused state">
Bug 788389
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=926812"
title="State change event not fired when both disabled and aria-disabled are toggled">
Bug 926812
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="testContainer">
<iframe id="iframe"></iframe>
</div>
<input id="email" type='email'>
<input id="checkbox" type="checkbox">
<input id="radio" type="radio">
<input id="file" type="file">
<div id="div"></div>
<input id="text1">
<div id="eventdump"></div>
</body>
</html>

View file

@ -0,0 +1,339 @@
<html>
<head>
<title>Accessible mutation events testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
////////////////////////////////////////////////////////////////////////////
// Invokers
/**
* Base text remove invoker and checker.
*/
function textRemoveInvoker(aID, aStart, aEnd, aText)
{
this.DOMNode = getNode(aID);
this.eventSeq = [
new textChangeChecker(aID, aStart, aEnd, aText, false)
];
}
function textInsertInvoker(aID, aStart, aEnd, aText)
{
this.DOMNode = getNode(aID);
this.eventSeq = [
new textChangeChecker(aID, aStart, aEnd, aText, true)
];
}
/**
* Remove inaccessible child node containing accessibles.
*/
function removeChildSpan(aID)
{
this.__proto__ = new textRemoveInvoker(aID, 0, 5, "33322");
this.invoke = function removeChildSpan_invoke()
{
// remove HTML span, a first child of the node
this.DOMNode.removeChild(this.DOMNode.firstChild);
}
this.getID = function removeChildSpan_getID()
{
return "Remove inaccessible span containing accessible nodes" + prettyName(aID);
}
}
/**
* Insert inaccessible child node containing accessibles.
*/
function insertChildSpan(aID, aInsertAllTogether)
{
this.__proto__ = new textInsertInvoker(aID, 0, 5, "33322");
this.invoke = function insertChildSpan_invoke()
{
// <span><span>333</span><span>22</span></span>
if (aInsertAllTogether) {
var topSpan = document.createElement("span");
var fSpan = document.createElement("span");
fSpan.textContent = "333";
topSpan.appendChild(fSpan);
var sSpan = document.createElement("span");
sSpan.textContent = "22";
topSpan.appendChild(sSpan);
this.DOMNode.insertBefore(topSpan, this.DOMNode.childNodes[0]);
} else {
var topSpan = document.createElement("span");
this.DOMNode.insertBefore(topSpan, this.DOMNode.childNodes[0]);
var fSpan = document.createElement("span");
fSpan.textContent = "333";
topSpan.appendChild(fSpan);
var sSpan = document.createElement("span");
sSpan.textContent = "22";
topSpan.appendChild(sSpan);
}
}
this.getID = function insertChildSpan_getID()
{
return "Insert inaccessible span containing accessibles" +
prettyName(aID);
}
}
/**
* Remove child embedded accessible.
*/
function removeChildDiv(aID)
{
this.__proto__ = new textRemoveInvoker(aID, 5, 6, kEmbedChar);
this.invoke = function removeChildDiv_invoke()
{
var childDiv = this.DOMNode.childNodes[1];
// Ensure accessible is created to get text remove event when it's
// removed.
getAccessible(childDiv);
this.DOMNode.removeChild(childDiv);
}
this.getID = function removeChildDiv_getID()
{
return "Remove accessible div from the middle of text accessible " +
prettyName(aID);
}
}
/**
* Insert child embedded accessible.
*/
function insertChildDiv(aID)
{
this.__proto__ = new textInsertInvoker(aID, 5, 6, kEmbedChar);
this.invoke = function insertChildDiv_invoke()
{
var childDiv = document.createElement("div");
this.DOMNode.insertBefore(childDiv, this.DOMNode.childNodes[1]);
}
this.getID = function insertChildDiv_getID()
{
return "Insert accessible div into the middle of text accessible " +
prettyName(aID);
}
}
/**
* Remove children from text container from first to last child or vice
* versa.
*/
function removeChildren(aID, aLastToFirst, aStart, aEnd, aText)
{
this.__proto__ = new textRemoveInvoker(aID, aStart, aEnd, aText);
this.invoke = function removeChildren_invoke()
{
if (aLastToFirst) {
while (this.DOMNode.firstChild)
this.DOMNode.removeChild(this.DOMNode.lastChild);
} else {
while (this.DOMNode.firstChild)
this.DOMNode.removeChild(this.DOMNode.firstChild);
}
}
this.getID = function removeChildren_getID()
{
return "remove children of " + prettyName(aID) +
(aLastToFirst ? " from last to first" : " from first to last");
}
}
/**
* Remove text from HTML input.
*/
function removeTextFromInput(aID, aStart, aEnd, aText)
{
this.__proto__ = new textRemoveInvoker(aID, aStart, aEnd, aText);
this.eventSeq.push(new invokerChecker(EVENT_TEXT_VALUE_CHANGE,
this.DOMNode));
this.invoke = function removeTextFromInput_invoke()
{
const nsIDOMNSEditableElement =
Components.interfaces.nsIDOMNSEditableElement;
this.DOMNode.focus();
this.DOMNode.setSelectionRange(aStart, aEnd);
synthesizeKey("VK_DELETE", {});
}
this.getID = function removeTextFromInput_getID()
{
return "Remove text from " + aStart + " to " + aEnd + " for " +
prettyName(aID);
}
}
/**
* Add text into HTML input.
*/
function insertTextIntoInput(aID, aStart, aEnd, aText)
{
this.__proto__ = new textInsertInvoker(aID, aStart, aEnd, aText);
this.eventSeq.push(new invokerChecker(EVENT_TEXT_VALUE_CHANGE,
this.DOMNode));
this.invoke = function insertTextIntoInput_invoke()
{
this.DOMNode.focus();
synthesizeKey("a", {});
}
this.getID = function insertTextIntoInput_getID()
{
return "Insert text to " + aStart + " for " + prettyName(aID);
}
}
/**
* Remove text data from text node of editable area.
*/
function removeTextFromEditable(aID, aStart, aEnd, aText, aTextNode)
{
this.__proto__ = new textRemoveInvoker(aID, aStart, aEnd, aText);
this.invoke = function removeTextFromEditable_invoke()
{
this.DOMNode.focus();
var selection = window.getSelection();
var range = document.createRange();
range.setStart(this.textNode, aStart);
range.setEnd(this.textNode, aEnd);
selection.addRange(range);
synthesizeKey("VK_DELETE", {});
}
this.getID = function removeTextFromEditable_getID()
{
return "Remove text from " + aStart + " to " + aEnd + " for " +
prettyName(aID);
}
this.textNode = getNode(aTextNode);
}
////////////////////////////////////////////////////////////////////////////
// Do tests
gA11yEventDumpToConsole = true; // debugging
var gQueue = null;
function doTests()
{
gQueue = new eventQueue();
// Text remove event on inaccessible child HTML span removal containing
// accessible text nodes.
gQueue.push(new removeChildSpan("p"));
gQueue.push(new insertChildSpan("p"), true);
gQueue.push(new insertChildSpan("p"), false);
// Remove embedded character.
gQueue.push(new removeChildDiv("div"));
gQueue.push(new insertChildDiv("div"));
// Remove all children.
var text = kEmbedChar + "txt" + kEmbedChar;
gQueue.push(new removeChildren("div2", true, 0, 5, text));
gQueue.push(new removeChildren("div3", false, 0, 5, text));
// Text remove from text node within hypertext accessible.
gQueue.push(new removeTextFromInput("input", 1, 3, "al"));
gQueue.push(new insertTextIntoInput("input", 1, 2, "a"));
// bug 570691
todo(false, "Fix text change events from editable area, see bug 570691");
//var textNode = getNode("editable").firstChild;
//gQueue.push(new removeTextFromEditable("editable", 1, 3, "al", textNode));
//textNode = getNode("editable2").firstChild.firstChild;
//gQueue.push(new removeTextFromEditable("editable2", 1, 3, "al", textNode));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=566293"
title=" wrong length of text remove event when inaccessible node containing accessible nodes is removed">
Mozilla Bug 566293
</a><br>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=570710"
title="Avoid extra array traversal during text event creation">
Mozilla Bug 570710
</a><br>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=574003"
title="Coalesce text events on nodes removal">
Mozilla Bug 574003
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=575052"
title="Cache text offsets within hypertext accessible">
Mozilla Bug 575052
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275"
title="Rework accessible tree update code">
Mozilla Bug 570275
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<p id="p"><span><span>333</span><span>22</span></span>1111</p>
<div id="div">hello<div>hello</div>hello</div>
<div id="div2"><div>txt</div>txt<div>txt</div></div>
<div id="div3"><div>txt</div>txt<div>txt</div></div>
<input id="input" value="value">
<div contentEditable="true" id="editable">value</div>
<div contentEditable="true" id="editable2"><span>value</span></div>
</body>
</html>

View file

@ -0,0 +1,249 @@
<html>
<head>
<title>Accessible text update algorithm testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
////////////////////////////////////////////////////////////////////////////
// Invokers
const kRemoval = false;
const kInsertion = true;
const kUnexpected = true;
function changeText(aContainerID, aValue, aEventList)
{
this.containerNode = getNode(aContainerID);
this.textNode = this.containerNode.firstChild;
this.textData = this.textNode.data;
this.eventSeq = [ ];
this.unexpectedEventSeq = [ ];
for (var i = 0; i < aEventList.length; i++) {
var event = aEventList[i];
var isInserted = event[0];
var str = event[1];
var offset = event[2];
var checker = new textChangeChecker(this.containerNode, offset,
offset + str.length, str,
isInserted);
if (event[3] == kUnexpected)
this.unexpectedEventSeq.push(checker);
else
this.eventSeq.push(checker);
}
this.invoke = function changeText_invoke()
{
this.textNode.data = aValue;
}
this.getID = function changeText_getID()
{
return "change text '" + shortenString(this.textData) + "' -> '" +
shortenString(this.textNode.data) + "' for " +
prettyName(this.containerNode);
}
}
function expStr(x, doublings)
{
for (var i = 0; i < doublings; ++i)
x = x + x;
return x;
}
////////////////////////////////////////////////////////////////////////////
// Do tests
//gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true;
var gQueue = null;
function doTests()
{
gQueue = new eventQueue();
//////////////////////////////////////////////////////////////////////////
// wqrema -> tqb: substitution coalesced with removal
var events = [
[ kRemoval, "w", 0 ], // wqrema -> qrema
[ kInsertion, "t", 0], // qrema -> tqrema
[ kRemoval, "rema", 2 ], // tqrema -> tq
[ kInsertion, "b", 2] // tq -> tqb
];
gQueue.push(new changeText("p1", "tqb", events));
//////////////////////////////////////////////////////////////////////////
// b -> insa: substitution coalesced with insertion (complex substitution)
events = [
[ kRemoval, "b", 0 ], // b ->
[ kInsertion, "insa", 0] // -> insa
];
gQueue.push(new changeText("p2", "insa", events));
//////////////////////////////////////////////////////////////////////////
// abc -> def: coalesced substitutions
events = [
[ kRemoval, "abc", 0 ], // abc ->
[ kInsertion, "def", 0] // -> def
];
gQueue.push(new changeText("p3", "def", events));
//////////////////////////////////////////////////////////////////////////
// abcabc -> abcDEFabc: coalesced insertions
events = [
[ kInsertion, "DEF", 3] // abcabc -> abcDEFabc
];
gQueue.push(new changeText("p4", "abcDEFabc", events));
//////////////////////////////////////////////////////////////////////////
// abc -> defabc: insertion into begin
events = [
[ kInsertion, "def", 0] // abc -> defabc
];
gQueue.push(new changeText("p5", "defabc", events));
//////////////////////////////////////////////////////////////////////////
// abc -> abcdef: insertion into end
events = [
[ kInsertion, "def", 3] // abc -> abcdef
];
gQueue.push(new changeText("p6", "abcdef", events));
//////////////////////////////////////////////////////////////////////////
// defabc -> abc: removal from begin
events = [
[ kRemoval, "def", 0] // defabc -> abc
];
gQueue.push(new changeText("p7", "abc", events));
//////////////////////////////////////////////////////////////////////////
// abcdef -> abc: removal from the end
events = [
[ kRemoval, "def", 3] // abcdef -> abc
];
gQueue.push(new changeText("p8", "abc", events));
//////////////////////////////////////////////////////////////////////////
// abcDEFabc -> abcabc: coalesced removals
events = [
[ kRemoval, "DEF", 3] // abcDEFabc -> abcabc
];
gQueue.push(new changeText("p9", "abcabc", events));
//////////////////////////////////////////////////////////////////////////
// !abcdef@ -> @axbcef!: insertion, deletion and substitutions
events = [
[ kRemoval, "!", 0 ], // !abcdef@ -> abcdef@
[ kInsertion, "@", 0], // abcdef@ -> @abcdef@
[ kInsertion, "x", 2 ], // @abcdef@ -> @axbcdef@
[ kRemoval, "d", 5], // @axbcdef@ -> @axbcef@
[ kRemoval, "@", 7 ], // @axbcef@ -> @axbcef
[ kInsertion, "!", 7 ], // @axbcef -> @axbcef!
];
gQueue.push(new changeText("p10", "@axbcef!", events));
//////////////////////////////////////////////////////////////////////////
// meilenstein -> levenshtein: insertion, complex and simple substitutions
events = [
[ kRemoval, "m", 0 ], // meilenstein -> eilenstein
[ kInsertion, "l", 0], // eilenstein -> leilenstein
[ kRemoval, "il", 2 ], // leilenstein -> leenstein
[ kInsertion, "v", 2], // leenstein -> levenstein
[ kInsertion, "h", 6 ], // levenstein -> levenshtein
];
gQueue.push(new changeText("p11", "levenshtein", events));
//////////////////////////////////////////////////////////////////////////
// long strings, remove/insert pair as the old string was replaced on
// new one
var longStr1 = expStr("x", 16);
var longStr2 = expStr("X", 16);
var newStr = "a" + longStr1 + "b", insStr = longStr1, rmStr = "";
events = [
[ kRemoval, rmStr, 1, kUnexpected ],
[ kInsertion, insStr, 1 ]
];
gQueue.push(new changeText("p12", newStr, events));
newStr = "a" + longStr2 + "b", insStr = longStr2, rmStr = longStr1;
events = [
[ kRemoval, rmStr, 1 ],
[ kInsertion, insStr, 1]
];
gQueue.push(new changeText("p12", newStr, events));
newStr = "ab", insStr = "", rmStr = longStr2;
events = [
[ kRemoval, rmStr, 1 ],
[ kInsertion, insStr, 1, kUnexpected ]
];
gQueue.push(new changeText("p12", newStr, events));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=626660"
title="Cache rendered text on a11y side">
Mozilla Bug 626660
</a>
<br>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="eventdump"></div>
<p id="p1">wqrema</p>
<p id="p2">b</p>
<p id="p3">abc</p>
<p id="p4">abcabc</p>
<p id="p5">abc</p>
<p id="p6">abc</p>
<p id="p7">defabc</p>
<p id="p8">abcdef</p>
<p id="p9">abcDEFabc</p>
<p id="p10">!abcdef@</p>
<p id="p11">meilenstein</p>
<p id="p12">ab</p>
</body>
</html>

View file

@ -0,0 +1,115 @@
<html>
<head>
<title>Text attribute changed event for misspelled text</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../attributes.js"></script>
<script type="application/javascript">
const nsIDOMNSEditableElement =
Components.interfaces.nsIDOMNSEditableElement;
Components.utils.import("resource://gre/modules/InlineSpellChecker.jsm");
function spelledTextInvoker(aID)
{
this.DOMNode = getNode(aID);
this.eventSeq = [
new invokerChecker(EVENT_TEXT_ATTRIBUTE_CHANGED, this.DOMNode)
];
this.invoke = function spelledTextInvoker_invoke()
{
var editor = this.DOMNode.QueryInterface(nsIDOMNSEditableElement).editor;
var spellChecker = new InlineSpellChecker(editor);
spellChecker.enabled = true;
//var spellchecker = editor.getInlineSpellChecker(true);
//spellchecker.enableRealTimeSpell = true;
this.DOMNode.value = "valid text inalid tixt";
}
this.finalCheck = function spelledTextInvoker_finalCheck()
{
var defAttrs = buildDefaultTextAttrs(this.DOMNode, kInputFontSize,
kNormalFontWeight,
kInputFontFamily);
testDefaultTextAttrs(aID, defAttrs);
var attrs = { };
var misspelledAttrs = {
"invalid": "spelling"
};
testTextAttrs(aID, 0, attrs, defAttrs, 0, 11);
testTextAttrs(aID, 11, misspelledAttrs, defAttrs, 11, 17);
testTextAttrs(aID, 17, attrs, defAttrs, 17, 18);
testTextAttrs(aID, 18, misspelledAttrs, defAttrs, 18, 22);
}
this.getID = function spelledTextInvoker_getID()
{
return "text attribute change for misspelled text";
}
}
/**
* Do tests.
*/
//gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true;
var gQueue = null;
function doTests()
{
// Synth focus before spellchecking turning on to make sure editor
// gets a time for initialization.
gQueue = new eventQueue();
gQueue.push(new synthFocus("input"));
gQueue.push(new spelledTextInvoker("input"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=345759"
title="Implement text attributes">
Mozilla Bug 345759
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<input id="input"/>
<div id="eventdump"></div>
</body>
</html>

View file

@ -0,0 +1,86 @@
<html>
<head>
<title>Accessible text selection change events testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../text.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
var gQueue = null;
// gA11yEventDumpID = "eventdump"; // debug stuff
//gA11yEventDumpToConsole = true;
function getOnclickSeq(aID)
{
return [
new caretMoveChecker(0, aID),
new unexpectedInvokerChecker(EVENT_TEXT_SELECTION_CHANGED, aID)
];
}
function doTests()
{
// test caret move events and caret offsets
gQueue = new eventQueue();
gQueue.push(new synthClick("c1_p1", getOnclickSeq("c1_p1")));
gQueue.push(new synthDownKey("c1", new textSelectionChecker("c1", 0, 1), { shiftKey: true }));
gQueue.push(new synthDownKey("c1", new textSelectionChecker("c1", 0, 2), { shiftKey: true }));
gQueue.push(new synthClick("ta1", getOnclickSeq("ta1")));
gQueue.push(new synthRightKey("ta1",
new textSelectionChecker("ta1", 0, 1),
{ shiftKey: true }));
gQueue.push(new synthLeftKey("ta1",
[new textSelectionChecker("ta1", 0, 0),
new caretMoveChecker(0, "ta1")]));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=762934"
title="Text selection change event has a wrong target when selection is spanned through several objects">
Bug 762934
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=956032"
title="Text selection change event missed when selected text becomes unselected">
Bug 956032
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="c1" contentEditable="true">
<p id="c1_p1">paragraph</p>
<p id="c1_p2">paragraph</p>
</div>
<textarea id="ta1">Hello world</textarea>
<div id="eventdump"></div>
</body>
</html>

View file

@ -0,0 +1,348 @@
<?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="DOM TreeRowCountChanged and a11y name change events.">
<script type="application/javascript"
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="../events.js" />
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Invoker's checkers
/**
* Check TreeRowCountChanged event.
*/
function rowCountChangedChecker(aMsg, aIdx, aCount)
{
this.type = "TreeRowCountChanged";
this.target = gTree;
this.check = function check(aEvent)
{
var propBag = aEvent.detail.QueryInterface(Components.interfaces.nsIPropertyBag2);
var index = propBag.getPropertyAsInt32("index");
is(index, aIdx, "Wrong 'index' data of 'treeRowCountChanged' event.");
var count = propBag.getPropertyAsInt32("count");
is(count, aCount, "Wrong 'count' data of 'treeRowCountChanged' event.");
}
this.getID = function getID()
{
return aMsg + "TreeRowCountChanged";
}
}
/**
* Check TreeInvalidated event.
*/
function treeInvalidatedChecker(aMsg, aStartRow, aEndRow, aStartCol, aEndCol)
{
this.type = "TreeInvalidated";
this.target = gTree;
this.check = function check(aEvent)
{
var propBag = aEvent.detail.QueryInterface(Components.interfaces.nsIPropertyBag2);
try {
var startRow = propBag.getPropertyAsInt32("startrow");
} catch (e if e.name == 'NS_ERROR_NOT_AVAILABLE') {
startRow = null;
}
is(startRow, aStartRow,
"Wrong 'startrow' of 'treeInvalidated' event on " + aMsg);
try {
var endRow = propBag.getPropertyAsInt32("endrow");
} catch (e if e.name == 'NS_ERROR_NOT_AVAILABLE') {
endRow = null;
}
is(endRow, aEndRow,
"Wrong 'endrow' of 'treeInvalidated' event on " + aMsg);
try {
var startCol = propBag.getPropertyAsInt32("startcolumn");
} catch (e if e.name == 'NS_ERROR_NOT_AVAILABLE') {
startCol = null;
}
is(startCol, aStartCol,
"Wrong 'startcolumn' of 'treeInvalidated' event on " + aMsg);
try {
var endCol = propBag.getPropertyAsInt32("endcolumn");
} catch (e if e.name == 'NS_ERROR_NOT_AVAILABLE') {
endCol = null;
}
is(endCol, aEndCol,
"Wrong 'endcolumn' of 'treeInvalidated' event on " + aMsg);
}
this.getID = function getID()
{
return "TreeInvalidated on " + aMsg;
}
}
/**
* Check name changed a11y event.
*/
function nameChangeChecker(aMsg, aRow, aCol)
{
this.type = EVENT_NAME_CHANGE;
function targetGetter()
{
var acc = getAccessible(gTree);
var tableAcc = getAccessible(acc, [nsIAccessibleTable]);
return tableAcc.getCellAt(aRow, aCol);
}
Object.defineProperty(this, "target", { get: targetGetter });
this.getID = function getID()
{
return aMsg + "name changed";
}
}
/**
* Check name changed a11y event for a row.
*/
function rowNameChangeChecker(aMsg, aRow)
{
this.type = EVENT_NAME_CHANGE;
function targetGetter()
{
var acc = getAccessible(gTree);
return acc.getChildAt(aRow + 1);
}
Object.defineProperty(this, "target", { get: targetGetter });
this.getID = function getID()
{
return aMsg + "name changed";
}
}
////////////////////////////////////////////////////////////////////////////
// Invokers
/**
* Set tree view.
*/
function setTreeView()
{
this.invoke = function setTreeView_invoke()
{
gTreeBox.view = gView;
}
this.getID = function setTreeView_getID() { return "set tree view"; }
this.eventSeq = [
new invokerChecker(EVENT_REORDER, gTree)
];
};
/**
* Insert row at 0 index and checks TreeRowCountChanged and TreeInvalidated
* event.
*/
function insertRow()
{
this.invoke = function insertRow_invoke()
{
gView.appendItem("last");
gTreeBox.rowCountChanged(0, 1);
}
this.eventSeq =
[
new rowCountChangedChecker("insertRow: ", 0, 1),
new treeInvalidatedChecker("insertRow", 0, 5, null, null)
];
this.getID = function insertRow_getID()
{
return "insert row";
}
}
/**
* Invalidates first column and checks six name changed events for each
* treeitem plus TreeInvalidated event.
*/
function invalidateColumn()
{
this.invoke = function invalidateColumn_invoke()
{
// Make sure accessible subtree of XUL tree is created otherwise no
// name change events for cell accessibles are emitted.
var tree = getAccessible(gTree);
var child = tree.firstChild;
var walkDown = true;
while (child != tree) {
if (walkDown) {
var grandChild = child.firstChild;
if (grandChild) {
child = grandChild;
continue;
}
}
var sibling = child.nextSibling;
if (sibling) {
child = sibling;
walkDown = true;
continue;
}
child = child.parent;
walkDown = false;
}
// Fire 'TreeInvalidated' event by InvalidateColumn()
var firstCol = gTree.columns.getFirstColumn();
for (var i = 0; i < gView.rowCount; i++)
gView.setCellText(i, firstCol, "hey " + String(i) + "x0");
gTreeBox.invalidateColumn(firstCol);
}
this.eventSeq =
[
new nameChangeChecker("invalidateColumn: ", 0, 0),
new nameChangeChecker("invalidateColumn: ", 1, 0),
new nameChangeChecker("invalidateColumn: ", 2, 0),
new nameChangeChecker("invalidateColumn: ", 3, 0),
new nameChangeChecker("invalidateColumn: ", 4, 0),
new nameChangeChecker("invalidateColumn: ", 5, 0),
new treeInvalidatedChecker("invalidateColumn", null, null, 0, 0)
];
this.getID = function invalidateColumn_getID()
{
return "invalidate column";
}
}
/**
* Invalidates second row and checks name changed event for first treeitem
* (note, there are two name changed events on linux due to different
* accessible tree for xul:tree element) plus TreeInvalidated event.
*/
function invalidateRow()
{
this.invoke = function invalidateRow_invoke()
{
// Fire 'TreeInvalidated' event by InvalidateRow()
var colCount = gTree.columns.count;
var column = gTree.columns.getFirstColumn();
while (column) {
gView.setCellText(1, column, "aloha 1x" + String(column.index));
column = column.getNext();
}
gTreeBox.invalidateRow(1);
}
this.eventSeq =
[
new nameChangeChecker("invalidateRow: ", 1, 0),
new nameChangeChecker("invalidateRow: ", 1, 1),
new rowNameChangeChecker("invalidateRow: ", 1),
new treeInvalidatedChecker("invalidateRow", 1, 1, null, null)
];
this.getID = function invalidateRow_getID()
{
return "invalidate row";
}
}
////////////////////////////////////////////////////////////////////////////
// Test
var gTree = null;
var gTreeBox = null;
var gTreeView = null;
var gQueue = null;
// gA11yEventDumpID = "debug";
gA11yEventDumpToConsole = true; // debuggin
function doTest()
{
// Initialize the tree
gTree = document.getElementById("tree");
gTreeBox = gTree.treeBoxObject;
gView = new nsTableTreeView(5);
// Perform actions
gQueue = new eventQueue();
gQueue.push(new setTreeView());
gQueue.push(new insertRow());
gQueue.push(new invalidateColumn());
gQueue.push(new invalidateRow());
gQueue.invoke();
}
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=368835"
title="Fire TreeViewChanged/TreeRowCountChanged events.">
Mozilla Bug 368835
</a><br/>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=308564"
title="No accessibility events when data in a tree row changes.">
Mozilla Bug 308564
</a><br/>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=739524"
title="replace TreeViewChanged DOM event on direct call from XUL tree.">
Mozilla Bug 739524
</a><br/>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=743568"
title="Thunderbird message list tree emitting incorrect focus signals after message deleted.">
Mozilla Bug 743568
</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox id="debug"/>
<tree id="tree" flex="1">
<treecols>
<treecol id="col1" flex="1" primary="true" label="column"/>
<treecol id="col2" flex="1" label="column 2"/>
</treecols>
<treechildren id="treechildren"/>
</tree>
</hbox>
</window>

View file

@ -0,0 +1,255 @@
<html>
<head>
<title>Accessible value change events testing</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../value.js"></script>
<script type="application/javascript">
/**
* Do tests.
*/
var gQueue = null;
// Value change invoker
function changeARIAValue(aNodeOrID, aValuenow, aValuetext)
{
this.DOMNode = getNode(aNodeOrID);
this.eventSeq = [ new invokerChecker(aValuetext ?
EVENT_TEXT_VALUE_CHANGE :
EVENT_VALUE_CHANGE, this.DOMNode)
];
this.invoke = function changeARIAValue_invoke() {
// Note: this should not fire an EVENT_VALUE_CHANGE when aria-valuetext
// is not empty
if (aValuenow != undefined)
this.DOMNode.setAttribute("aria-valuenow", aValuenow);
// Note: this should always fire an EVENT_VALUE_CHANGE
if (aValuetext != undefined)
this.DOMNode.setAttribute("aria-valuetext", aValuetext);
}
this.check = function changeARIAValue_check() {
var acc = getAccessible(aNodeOrID, [nsIAccessibleValue]);
if (!acc)
return;
// Note: always test against valuetext first because the existence of
// aria-valuetext takes precedence over aria-valuenow in gecko.
is(acc.value, (aValuetext != undefined)? aValuetext : aValuenow,
"Wrong value of " + prettyName(aNodeOrID));
}
this.getID = function changeARIAValue_getID() {
return prettyName(aNodeOrID) + " value changed";
}
}
function changeValue(aID, aValue)
{
this.DOMNode = getNode(aID);
this.eventSeq = [new invokerChecker(EVENT_TEXT_VALUE_CHANGE,
this.DOMNode)
];
this.invoke = function changeValue_invoke()
{
this.DOMNode.value = aValue;
}
this.check = function changeValue_check()
{
var acc = getAccessible(this.DOMNode);
is(acc.value, aValue, "Wrong value for " + prettyName(aID));
}
this.getID = function changeValue_getID()
{
return prettyName(aID) + " value changed";
}
}
function changeProgressValue(aID, aValue)
{
this.DOMNode = getNode(aID);
this.eventSeq = [new invokerChecker(EVENT_VALUE_CHANGE, this.DOMNode)];
this.invoke = function changeProgressValue_invoke()
{
this.DOMNode.value = aValue;
}
this.check = function changeProgressValue_check()
{
var acc = getAccessible(this.DOMNode);
is(acc.value, aValue+"%", "Wrong value for " + prettyName(aID));
}
this.getID = function changeProgressValue_getID()
{
return prettyName(aID) + " value changed";
}
}
function changeRangeValue(aID)
{
this.DOMNode = getNode(aID);
this.eventSeq = [new invokerChecker(EVENT_VALUE_CHANGE, this.DOMNode)];
this.invoke = function changeRangeValue_invoke()
{
synthesizeMouse(getNode(aID), 5, 5, { });
}
this.finalCheck = function changeRangeValue_finalCheck()
{
var acc = getAccessible(this.DOMNode);
is(acc.value, "0", "Wrong value for " + prettyName(aID));
}
this.getID = function changeRangeValue_getID()
{
return prettyName(aID) + " range value changed";
}
}
function changeSelectValue(aID, aKey, aValue)
{
this.eventSeq =
[ new invokerChecker(EVENT_TEXT_VALUE_CHANGE, getAccessible(aID)) ];
this.invoke = function changeSelectValue_invoke()
{
getNode(aID).focus();
synthesizeKey(aKey, {}, window);
}
this.finalCheck = function changeSelectValue_finalCheck()
{
is(getAccessible(aID).value, aValue, "Wrong value for " + prettyName(aID));
}
this.getID = function changeSelectValue_getID()
{
return `${prettyName(aID)} closed select value change on '${aKey}'' key press`;
}
}
//enableLogging("DOMEvents");
//gA11yEventDumpToConsole = true;
function doTests()
{
// Test initial values
testValue("slider_vn", "5", 5, 0, 1000, 0);
testValue("slider_vnvt", "plain", 0, 0, 5, 0);
testValue("slider_vt", "hi", 0, 0, 3, 0);
testValue("scrollbar", "5", 5, 0, 1000, 0);
testValue("progress", "22%", 22, 0, 100, 0);
testValue("range", "6", 6, 0, 10, 1);
// Test value change events
gQueue = new eventQueue();
gQueue.push(new changeARIAValue("slider_vn", "6", undefined));
gQueue.push(new changeARIAValue("slider_vt", undefined, "hey!"));
gQueue.push(new changeARIAValue("slider_vnvt", "3", "sweet"));
gQueue.push(new changeARIAValue("scrollbar", "6", undefined));
gQueue.push(new changeValue("combobox", "hello"));
gQueue.push(new changeProgressValue("progress", "50"));
gQueue.push(new changeRangeValue("range"));
gQueue.push(new changeSelectValue("select", "VK_DOWN", "2nd"));
gQueue.push(new changeSelectValue("select", "3", "3rd"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTests);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=478032"
title=" Fire delayed value changed event for aria-valuetext changes">
Mozilla Bug 478032
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=529289"
title="We dont expose new aria role 'scrollbar' and property aria-orientation">
Mozilla Bug 529289
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=559764"
title="Make HTML5 input@type=range element accessible">
Mozilla Bug 559764
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=703202"
title="ARIA comboboxes don't fire value change events">
Mozilla Bug 703202
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=761901"
title=" HTML5 progress accessible should fire value change event">
Mozilla Bug 761901
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="eventdump"></div>
<!-- ARIA sliders -->
<div id="slider_vn" role="slider" aria-valuenow="5"
aria-valuemin="0" aria-valuemax="1000">slider</div>
<div id="slider_vt" role="slider" aria-valuetext="hi"
aria-valuemin="0" aria-valuemax="3">greeting slider</div>
<div id="slider_vnvt" role="slider" aria-valuenow="0" aria-valuetext="plain"
aria-valuemin="0" aria-valuemax="5">sweetness slider</div>
<!-- ARIA scrollbar -->
<div id="scrollbar" role="scrollbar" aria-valuenow="5"
aria-valuemin="0" aria-valuemax="1000">slider</div>
<!-- ARIA combobox -->
<input id="combobox" role="combobox" aria-autocomplete="inline">
<!-- progress bar -->
<progress id="progress" value="22" max="100"></progress>
<!-- input@type="range" -->
<input type="range" id="range" min="0" max="10" value="6">
<select id="select">
<option>1st</option>
<option>2nd</option>
<option>3rd</option>
</select>
</body>
</html>