You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
621 lines
18 KiB
621 lines
18 KiB
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
|
"http://www.w3.org/TR/html4/strict.dtd"> |
|
<html> |
|
<head> |
|
<title>robot Dialog A11Y Test</title> |
|
|
|
<style> |
|
<style> |
|
@import "../../../util/doh/robot/robot.css"; |
|
</style> |
|
|
|
<!-- required: dojo.js --> |
|
<script type="text/javascript" src="../../../dojo/dojo.js" |
|
data-dojo-config="isDebug: true"></script> |
|
|
|
<script type="text/javascript"> |
|
require([ |
|
"doh/runner", "dojo/robotx", |
|
"dojo/aspect", "dojo/dom", "dojo/dom-class", "dojo/dom-style", "dojo/keys", |
|
"dijit/tests/helpers", "dojo/domReady!" |
|
], function(doh, robot, aspect, dom, domClass, domStyle, keys, helpers){ |
|
|
|
robot.initRobot('../test_Dialog.html'); |
|
|
|
doh.register(function setup(){ |
|
// get pointer to registry in the iframe |
|
registry = robot.window.require("dijit/registry"); |
|
dfocus = robot.window.require("dijit/focus"); |
|
DialogUnderlay = robot.window.require("dijit/DialogUnderlay"); |
|
}); |
|
|
|
doh.register("keyboard tests (cancel)", [ |
|
{ |
|
name: "open dialog", |
|
timeout: 10000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
// Click the button. We do this manually rather than calling Dialog.show() |
|
// so we can later test that focus is restored (to the previous position) |
|
// when the dialog is closed |
|
dom.byId("dialog1button").focus(); |
|
robot.keyPress(keys.SPACE, 1000, {}); |
|
robot.typeKeys("Bill", 1000, 800); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.t(helpers.isVisible("dialog1"), "dialog 1 has been made visible"); |
|
doh.is("name", dfocus.curNode.id, "focus is on the first field"); |
|
}), 500); |
|
|
|
return d; |
|
} |
|
}, |
|
|
|
{ |
|
name: "tab to the date field", |
|
timeout: 10000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
robot.keyPress(keys.TAB, 500, {}); |
|
robot.typeKeys("Japan", 1000, 1000); |
|
robot.keyPress(keys.TAB, 500, {}); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.is("date", dfocus.curNode.id, "focus is on the date field"); |
|
}), 1000); |
|
|
|
return d; |
|
} |
|
}, |
|
|
|
{ |
|
name: "open and close date drop down", |
|
timeout: 4000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
robot.keyPress(keys.DOWN_ARROW, 500, {}); |
|
robot.keyPress(keys.ESCAPE, 500, {}); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.is("date", dfocus.curNode.id, "focus is still on the date field"); |
|
doh.t(helpers.isVisible("dialog1"), "dialog 1 wasn't closed"); |
|
}), 1000); |
|
|
|
return d; |
|
} |
|
}, |
|
|
|
{ |
|
name: "tabbing loops around", |
|
timeout: 4000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
robot.keyPress(keys.TAB, 500, {}); |
|
robot.keyPress(keys.TAB, 500, {}); |
|
robot.keyPress(keys.TAB, 500, {}); |
|
robot.keyPress(keys.TAB, 500, {}); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.is("name", dfocus.curNode.id, "focus looped back to name field"); |
|
}), 1000); |
|
|
|
return d; |
|
} |
|
}, |
|
|
|
{ |
|
name: "reverse-tabbing loops around", |
|
timeout: 4000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
robot.keyPress(keys.TAB, 500, {shift: true}); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.is("ok", dfocus.curNode.id, "focus looped back to submit button"); |
|
}), 1000); |
|
|
|
return d; |
|
} |
|
}, |
|
|
|
{ |
|
name: "close via ESC", |
|
timeout: 4000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
robot.keyPress(keys.ESCAPE, 500, {}); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.t(helpers.isHidden("dialog1"), "dialog 1 was closed"); |
|
doh.is("dialog1button", dfocus.curNode.id, "focus returned to button"); |
|
}), 1000); |
|
|
|
return d; |
|
} |
|
} |
|
]); |
|
|
|
doh.register("keyboard tests (submit)", [ |
|
{ |
|
name: "submit some data", |
|
timeout: 15000, |
|
setUp: function(){ |
|
registry.byId("dialog1").reset(); |
|
}, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
// Setup handler to catch submitted data |
|
var data; |
|
aspect.after(registry.byId("dialog1"), "execute", function(vals){ |
|
data = vals; |
|
}, true); |
|
|
|
// Open the dialog |
|
dom.byId("dialog1button").focus(); |
|
robot.keyPress(keys.SPACE, 1000, {}); |
|
|
|
// Enter some info |
|
robot.typeKeys("Ted", 2000, 600); |
|
robot.keyPress(keys.TAB, 500, {}); |
|
robot.typeKeys("America", 1000, 1400); |
|
robot.keyPress(keys.TAB, 500, {}); |
|
robot.keyPress(keys.TAB, 1000, {}); |
|
robot.keyPress(keys.TAB, 1000, {}); |
|
robot.keyPress(keys.TAB, 1000, {}); |
|
|
|
// Submit |
|
robot.keyPress(keys.SPACE, 1000, {}); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.t(helpers.isHidden("dialog1"), "dialog 1 was closed on submit"); |
|
doh.t(data, "got submit data"); |
|
doh.is("Ted", data.name, "Name"); |
|
doh.is("America", data.loc, "Location"); |
|
}), 1000); |
|
|
|
return d; |
|
} |
|
} |
|
]); |
|
|
|
doh.register("keyboard tests (cancel via Cancel button)", [ |
|
{ |
|
name: "close Dialog via Cancel button", |
|
timeout: 15000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
// Test which callbacks are called on cancel |
|
var executed = false, canceled = false; |
|
aspect.after(registry.byId("ABDlg1"), "execute", function(vals){ |
|
executed = true; |
|
}, true); |
|
registry.byId("ABDlg1").on("cancel", function(){ |
|
canceled = true; |
|
}); |
|
|
|
// Open the dialog |
|
dom.byId("ABDlg1Btn").focus(); |
|
robot.keyPress(keys.SPACE, 1000, {}); |
|
|
|
robot.sequence(d.getTestErrback(function(){ |
|
doh.t(helpers.isVisible("ABDlg1"), "dialog opened"); |
|
}), 1000); |
|
|
|
// Cancel |
|
robot.keyPress(keys.TAB, 500, {}); |
|
robot.keyPress(keys.SPACE, 500, {}); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.t(helpers.isHidden("ABDlg1"), "dialog closed on cancel"); |
|
doh.t(canceled, "cancel callback was called"); |
|
doh.f(executed, "execute callback wasn't called"); |
|
}), 1000); |
|
|
|
return d; |
|
} |
|
} |
|
]); |
|
|
|
// Test aria roles, etc. |
|
doh.register("aria", function(){ |
|
var dlog = registry.byId("dialog1"); |
|
doh.is("dialog", dlog.domNode.getAttribute("role"), "role"); |
|
doh.is("dialog1_title", dlog.domNode.getAttribute("aria-labelledby"), "aria-labelledby"); |
|
doh.isNot(undefined, dom.byId("dialog1_title"), "label node exists"); |
|
doh.isNot("", helpers.innerText(dom.byId("dialog1_title")), "label node has text"); |
|
// dijit.Dialog does not implement aria-expanded as of this writing -- should it? |
|
}); |
|
|
|
// Focus tests for special cases. Focus for normal cases was already tested above. |
|
doh.register("special focus", [ |
|
{ |
|
name: "no focusable elements", |
|
timeout: 10000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
// Click the button. We do this manually rather than calling Dialog.show() |
|
// so we can later test that focus is restored (to the previous position) |
|
// when the dialog is closed |
|
dom.byId("unmovablebutton").focus(); |
|
robot.keyPress(keys.SPACE, 500, {}); |
|
|
|
robot.sequence(d.getTestErrback(function(){ |
|
doh.t(dfocus.curNode, "focus is somewhere #1"); |
|
doh.t(domClass.contains(dfocus.curNode, "dijitDialogCloseIcon"), "focus is on the close button #1"); |
|
}), 1000); |
|
|
|
// Tab key shouldn't change the focus |
|
robot.keyPress(keys.TAB, 500); |
|
|
|
robot.sequence(d.getTestErrback(function(){ |
|
doh.t(dfocus.curNode, "focus is somewhere #2"); |
|
doh.t(domClass.contains(dfocus.curNode, "dijitDialogCloseIcon"), "focus is on the close button #2"); |
|
}), 500); |
|
|
|
// Space key should close the dialog |
|
robot.keyPress(keys.SPACE, 500); |
|
|
|
robot.sequence(d.getTestErrback(function(){ |
|
doh.t(dfocus.curNode, "focus is somewhere #3"); |
|
doh.is("unmovablebutton", dfocus.curNode.id, "focus is back on the button that opened the dialog #1"); |
|
}), 500); |
|
|
|
// Open the dialog again |
|
robot.keyPress(keys.SPACE, 500, {}); |
|
|
|
robot.sequence(d.getTestErrback(function(){ |
|
doh.t(dfocus.curNode, "focus is somewhere #4"); |
|
doh.t(domClass.contains(dfocus.curNode, "dijitDialogCloseIcon"), "focus is on the close button #4"); |
|
}), 500); |
|
|
|
// Esc key should also close the dialog |
|
robot.keyPress(keys.ESCAPE, 500); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.t(dfocus.curNode, "focus is somewhere #5"); |
|
doh.is("unmovablebutton", dfocus.curNode.id, "focus is back on the button that opened the dialog #2"); |
|
}), 500); |
|
|
|
return d; |
|
} |
|
}, |
|
|
|
{ |
|
name: "input type=file", |
|
timeout: 10000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
// Click the button. We do this manually rather than calling Dialog.show() |
|
// so we can later test that focus is restored (to the previous position) |
|
// when the dialog is closed |
|
dom.byId("filebutton").focus(); |
|
robot.keyPress(keys.SPACE, 500, {}); |
|
|
|
robot.sequence(d.getTestErrback(function(){ |
|
doh.t(dfocus.curNode, "focus is somewhere #1"); |
|
doh.is("afile", dfocus.curNode.id, "focus is on the input type=file"); |
|
}), 1000); |
|
|
|
// Esc key should close the dialog |
|
robot.keyPress(keys.ESCAPE, 500); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.t(dfocus.curNode, "focus is somewhere #2"); |
|
doh.is("filebutton", dfocus.curNode.id, "focus is back on the button that opened the dialog"); |
|
}), 500); |
|
|
|
return d; |
|
} |
|
}, |
|
|
|
{ |
|
name: "radio button as last element", |
|
timeout: 10000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
// Click the button. We do this manually rather than calling Dialog.show() |
|
// so we can later test that focus is restored (to the previous position) |
|
// when the dialog is closed |
|
dom.byId("RadioButtonDlgBtn").focus(); |
|
robot.keyPress(keys.SPACE, 500, {}); |
|
|
|
robot.sequence(d.getTestErrback(function(){ |
|
doh.t(dfocus.curNode, "focus is somewhere #1"); |
|
doh.is("textarea-radio-test", dfocus.curNode.id, "focus is on the textarea"); |
|
}), 1000); |
|
|
|
robot.keyPress(keys.TAB, 500, {}); |
|
robot.keyPress(keys.TAB, 500, {}); |
|
|
|
robot.sequence(d.getTestErrback(function(){ |
|
doh.t(dfocus.curNode, "focus is somewhere #2"); |
|
doh.is("textarea-radio-test", dfocus.curNode.id, "focus wraps around back to the textarea"); |
|
}), 500); |
|
|
|
// Esc key should close the dialog |
|
robot.keyPress(keys.ESCAPE, 500); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.t(dfocus.curNode, "focus is somewhere #3"); |
|
doh.is("RadioButtonDlgBtn", dfocus.curNode.id, "focus is back on the button that opened the dialog"); |
|
}), 500); |
|
|
|
return d; |
|
} |
|
} |
|
]); |
|
|
|
doh.register("keyboard tests (multiple dialogs)", [ |
|
{ |
|
name: "open first dialog", |
|
timeout: 10000, |
|
setUp: function(){ |
|
registry.byId("dialog1").reset(); |
|
}, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
// Click the button. We do this manually rather than calling Dialog.show() |
|
// so we can later test that focus is restored (to the previous position) |
|
// when the dialog is closed |
|
dom.byId("dialog1button").focus(); |
|
robot.keyPress(keys.SPACE, 1000, {}); |
|
robot.typeKeys("lower", 1000, 1000); |
|
|
|
// Move focus to second field |
|
robot.keyPress(keys.TAB, 1000); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.t(helpers.isVisible("dialog1"), "dialog 1 is visible"); |
|
|
|
var dialog1Z = domStyle.get(registry.byId("dialog1").domNode, "zIndex"), |
|
underlayZ = domStyle.get(DialogUnderlay._singleton.domNode, "zIndex"); |
|
|
|
doh.t(dialog1Z > underlayZ, "dialog1 (zIndex=" + dialog1Z + |
|
") above underlay (zIndex=" + underlayZ + ")"); |
|
|
|
doh.is("loc", dfocus.curNode.id, "focus is on the second field"); |
|
}), 1000); |
|
|
|
return d; |
|
} |
|
}, |
|
|
|
{ |
|
name: "open second dialog", |
|
timeout: 10000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
registry.byId("tabDialog").show(); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.t(helpers.isVisible("tabDialog"), "tab dialog has been made visible"); |
|
doh.t(helpers.isVisible("dialog1"), "dialog 1 is still visible"); |
|
|
|
var tabDialogZ = domStyle.get(registry.byId("tabDialog").domNode, "zIndex"), |
|
dialog1Z = domStyle.get(registry.byId("dialog1").domNode, "zIndex"), |
|
underlayZ = domStyle.get(DialogUnderlay._singleton.domNode, "zIndex"); |
|
|
|
doh.t(tabDialogZ > underlayZ, "tabDialog (zIndex=" + tabDialogZ + |
|
") above underlay (zIndex=" + underlayZ + ")"); |
|
doh.t(dialog1Z < underlayZ, "dialog1 (zIndex=" + dialog1Z + |
|
") below underlay (zIndex=" + underlayZ + ")"); |
|
}), 2000); |
|
|
|
return d; |
|
} |
|
}, |
|
|
|
{ |
|
name: "cancel second dialog", |
|
timeout: 10000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
robot.keyPress(keys.ESCAPE, 500, {}); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.t(helpers.isHidden("tabDialog"), "tab dialog has been hidden"); |
|
doh.t(helpers.isVisible("dialog1"), "dialog 1 is still visible"); |
|
|
|
var dialog1Z = domStyle.get(registry.byId("dialog1").domNode, "zIndex"), |
|
underlayZ = domStyle.get(DialogUnderlay._singleton.domNode, "zIndex"); |
|
|
|
doh.t(dialog1Z > underlayZ, "dialog1 (zIndex=" + dialog1Z + |
|
") above underlay (zIndex=" + underlayZ + ")"); |
|
|
|
doh.is("loc", dfocus.curNode.id, "focus is on the second field"); |
|
}), 2000); |
|
|
|
return d; |
|
} |
|
}, |
|
|
|
{ |
|
name: "cancel first dialog", |
|
timeout: 10000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
robot.keyPress(keys.ESCAPE, 500, {}); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.t(helpers.isHidden("dialog1"), "dialog 1 was closed"); |
|
doh.is("dialog1button", dfocus.curNode.id, "focus returned to button"); |
|
}), 2000); |
|
|
|
return d; |
|
} |
|
} |
|
]); |
|
|
|
// Testing if focus somehow gets shifted to an element behind the underlay, by (for example) |
|
// access keys, or tabbing in from the URL bar, or clicking the underlay, thus focusing <body>. |
|
doh.register("focus return", [ |
|
{ |
|
name: "open first", |
|
timeout: 10000, |
|
runTest: function(){ |
|
return registry.byId('dialog1').show(); |
|
} |
|
}, |
|
{ |
|
name: "open second", |
|
timeout: 10000, |
|
runTest: function(){ |
|
var fifthDlg = registry.byId('fifthDlg'); |
|
return fifthDlg.show().then(function(){ |
|
return fifthDlg.onLoadDeferred; |
|
}); |
|
} |
|
}, |
|
{ |
|
name: "focus main page", |
|
timeout: 10000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
dom.byId("plainInput").focus(); |
|
|
|
setTimeout(d.getTestCallback(function(){ |
|
doh.t(helpers.isVisible("fifthDlg"), "dialog 5 still visible"); |
|
doh.is("timeref", dfocus.curNode && dfocus.curNode.id, |
|
"focus remains on / returned to dialog"); |
|
}), 1000); |
|
|
|
return d; |
|
} |
|
}, |
|
{ |
|
name: "close second", |
|
timeout: 10000, |
|
runTest: function(){ |
|
return registry.byId('fifthDlg').hide(); |
|
} |
|
}, |
|
{ |
|
name: "focus main page again", |
|
timeout: 10000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
dom.byId("plainInput").focus(); |
|
|
|
setTimeout(d.getTestCallback(function(){ |
|
doh.t(helpers.isVisible("dialog1"), "dialog 1 still visible"); |
|
doh.is("name", dfocus.curNode && dfocus.curNode.id, |
|
"focus remains on / returned to dialog"); |
|
}), 1000); |
|
|
|
return d; |
|
} |
|
}, |
|
{ |
|
name: "close first", |
|
timeout: 10000, |
|
runTest: function(){ |
|
return registry.byId('dialog1').hide(); |
|
} |
|
} |
|
]); |
|
|
|
// Negative test for "focus return". If the execute() handler shifts focus somewhere, |
|
// make sure it isn't automatically shifted back to the Dialog (which is fading out but |
|
// not yet hidden). |
|
doh.register("focus in execute", [ |
|
{ |
|
name: "use dialog", |
|
timeout: 15000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
// Open the dialog |
|
dom.byId("insertTextButton", robot.doc).focus(); |
|
robot.keyPress(keys.SPACE, 500, {}); |
|
|
|
// Enter some info |
|
robot.typeKeys("Hello world", 2000, 600); |
|
|
|
// Submit |
|
robot.keyPress(keys.TAB, 1000, {}); |
|
robot.keyPress(keys.SPACE, 1000, {}); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.is("editor", dfocus.curNode.id, "focus returned to editor"); |
|
doh.is("Hello world", dom.byId("editor", robot.doc).value, "text inserted"); |
|
}), 1000); |
|
|
|
return d; |
|
} |
|
} |
|
]); |
|
|
|
doh.register("closable", [ |
|
{ |
|
name: "open dialog", |
|
timeout: 10000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
dom.byId("unclosableButton").focus(); |
|
robot.keyPress(keys.SPACE, 1000, {}); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.t(helpers.isVisible("unclosable"), "visible"); |
|
doh.t(helpers.isHidden(registry.byId("unclosable").closeButtonNode), "close icon hidden"); |
|
}), 500); |
|
|
|
return d; |
|
} |
|
}, |
|
|
|
{ |
|
name: "close via ESC", |
|
timeout: 4000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
robot.keyPress(keys.ESCAPE, 500, {}); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.t(helpers.isVisible("unclosable"), "still visible"); |
|
}), 1000); |
|
|
|
return d; |
|
} |
|
}, |
|
|
|
{ |
|
name: "close via ENTER on OK button", |
|
timeout: 4000, |
|
runTest: function(){ |
|
var d = new doh.Deferred(); |
|
|
|
robot.keyPress(keys.ENTER, 500, {}); |
|
|
|
robot.sequence(d.getTestCallback(function(){ |
|
doh.t(helpers.isHidden("unclosable"), "hidden"); |
|
}), 1000); |
|
|
|
return d; |
|
} |
|
} |
|
]); |
|
|
|
doh.run(); |
|
}); |
|
</script> |
|
</head> |
|
</html>
|
|
|