Files
openlayers/master/examples/Spinner_a11y.html
Éric Lemoine 5d14b9e2d4 Updated
2013-02-20 10:38:25 +01:00

714 lines
25 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>doh.robot Spinner Test</title>
<style>
@import "../../../../util/doh/robot/robot.css";
</style>
<!-- required: dojo.js -->
<script type="text/javascript" src="../../../../dojo/dojo.js"></script>
<script type="text/javascript">
dojo.require("dijit.robotx");
dojo.ready(function(){
var spin1;
var spin2;
var spin3;
var spinnerIds = ["integerspinner1", "integerspinner2", "integertextbox3", "realspinner1"];
doh.robot.initRobot('../test_Spinner.html');
// focus handlers for noticing tab/shift+tab navigation
var focusCountZ = 0;
var blurCountZ = 0;
var countFocus = function(){
focusCountZ++;
};
var countBlur = function(){
blurCountZ++;
};
var focusConnect;
var blurConnect;
var tabFocusSetup = function(inSpinnerId){
var spinner = dijit.byId(inSpinnerId);
dijit.byId('integerspinner1').focus();
focusCountZ = 0;
blurCountZ = 0;
focusConnect = spinner.connect(spinner.focusNode, "onfocus", countFocus);
blurConnect = spinner.connect(spinner.focusNode, "onblur", countBlur);
};
// Setup to test manipulation of spinner via keystrokes.
var results; // array holding both expected value and actual value after each keypress
var strokeIndex = 0;
var noteConnect;
function keyStrokeSetup(inSpinnerId){
// summary:
// Populates results[] with expected values after each keypress.
// Also sets up listener to every keyboard event (arrow key etc) on a spinner and
// records to record the actual spinner values into results[].
var spinner = dijit.byId(inSpinnerId);
results = populateExpected(spinner);
strokeIndex = 0;
noteConnect = spinner.connect(spinner.focusNode, "onkeypress", function(){
results[strokeIndex].actual = spinner.get('value');
strokeIndex++;
});
}
// Use spinner api to calculate values for a set of keystrokes.
// Returns array of expected values.
var populateExpected = function(/*Spinner Widget*/inSpinner){
var initVal = inSpinner.get('value');
var eVals = [];
var newVal;
var i;
// The values expected by pressing HOME, right arrow five times,
// PgUp twice, PgDn, up arrow twice, down arrow once,
// left arrow once, and END.
if(inSpinner.constraints.min){
inSpinner.set('value', inSpinner.constraints.min);
}
newVal = inSpinner.get('value');
eVals.push({stroke: "HOME", expected: newVal});
// UP 5 times
for(i = 0; i < 5; i++){
newVal = inSpinner.adjust(newVal, inSpinner.smallDelta);
inSpinner.set('value', newVal);
newVal = inSpinner.get('value');
eVals.push({stroke: "UP", expected: newVal});
}
// PgUp twice
for(i = 0; i < 2; i++){
newVal = inSpinner.adjust(newVal, inSpinner.largeDelta);
inSpinner.set('value', newVal);
newVal = inSpinner.get('value');
eVals.push({stroke: "PgUp", expected: newVal});
}
// PgDn once.
newVal = inSpinner.adjust(newVal, -inSpinner.largeDelta);
inSpinner.set('value', newVal);
newVal = inSpinner.get('value');
eVals.push({stroke: "PgDn", expected: newVal});
// DOWN
newVal = inSpinner.adjust(newVal, -inSpinner.smallDelta);
inSpinner.set('value', newVal);
newVal = inSpinner.get('value');
eVals.push({stroke: "DOWN", expected: newVal});
// END
if(inSpinner.constraints.max){
inSpinner.set('value', inSpinner.constraints.max);
}
newVal = inSpinner.get('value');
eVals.push({stroke: "END", expected: newVal});
// reset <inSpinner> back to its initial value, and return
inSpinner.set('value', initVal);
return eVals;
};
// execute some test as soon as the widget gets focus
var focusThenRun = function(widget, fcn){
if(!widget.focused){
var handler = widget.connect(widget, '_onFocus', function(){
widget.disconnect(handler);
setTimeout(fcn, 1);
});
widget.focus();
}else{
fcn();
}
};
// common robot TAB-focus test function.
var a11yTabFocus = function(inSpinnerId){
var d = new doh.Deferred();
var spinner = dijit.byId(inSpinnerId);
focusThenRun(spinner, function(){
var handler = spinner.connect(spinner, '_onBlur', function(){
spinner.disconnect(handler);
setTimeout(function(){
handler = spinner.connect(spinner, '_onFocus', function(){
spinner.disconnect(handler);
setTimeout(function(){
handler = spinner.connect(spinner, '_onBlur', function(){
spinner.disconnect(handler);
setTimeout(function(){
handler = spinner.connect(spinner, '_onFocus', function(){
spinner.disconnect(handler);
setTimeout(d.getTestCallback(function(){
spinner.disconnect(focusConnect);
spinner.disconnect(blurConnect);
doh.is(3, focusCountZ, "# of times focused (" + spinner.id + ")");
doh.is(2, blurCountZ, "# of times lost focus (" + spinner.id + ")");
}), 1);
});
doh.robot.keyPress(dojo.keys.TAB, 1, {shift:true}); // refocus
}, 1);
});
doh.robot.keyPress(dojo.keys.TAB, 1); // reblur
}, 1);
});
doh.robot.keyPress(dojo.keys.TAB, 1); // refocus
}, 1);
});
doh.robot.keyPress(dojo.keys.TAB, 1, {shift:true}); // blur
});
return d;
};
// common robot keystroke test function.
var a11yKeystrokeTest = function(inSpinnerId){
var d = new doh.Deferred();
var spinner = dijit.byId(inSpinnerId);
var initVal = spinner.get('value');
focusThenRun(spinner, function(){
doh.robot.keyPress(dojo.keys.HOME, 1);
doh.robot.keyPress(dojo.keys.UP_ARROW, 200);
doh.robot.keyPress(dojo.keys.UP_ARROW, 200);
doh.robot.keyPress(dojo.keys.UP_ARROW, 200);
doh.robot.keyPress(dojo.keys.UP_ARROW, 200);
doh.robot.keyPress(dojo.keys.UP_ARROW, 200);
doh.robot.keyPress(dojo.keys.PAGE_UP, 200);
doh.robot.keyPress(dojo.keys.PAGE_UP, 200);
doh.robot.keyPress(dojo.keys.PAGE_DOWN, 200);
doh.robot.keyPress(dojo.keys.DOWN_ARROW, 200);
doh.robot.keyPress(dojo.keys.END, 200);
var testPresses = function(){
spinner.disconnect(noteConnect);
spinner.set('value', initVal);
for(var i = 0; i < results.length; i++){
var aResult = results[i];
if(!(isNaN(aResult.expected) && isNaN(aResult.actual))){
doh.is(aResult.expected, aResult.actual, aResult.stroke);
}
}
};
doh.robot.sequence(d.getTestCallback(testPresses), 1000, 1000);
});
return d;
};
doh.register("setUp",{
name: "setUp",
timeout: 5000,
setUp:function(){
spin1 = dijit.byId('integerspinner1');
spin2 = dijit.byId('integerspinner2');
spin3 = dijit.byId('realspinner1');
spin4 = dijit.byId('spinnerMinOnly');
safeClick = dojo.byId('form1');
},
runTest: function(){
// assert onChange not fired
doh.is("not fired yet!", dojo.byId('oc1').value, "onChange should not have fired");
// make sure initial values are what we expect
doh.is(1, spin1.smallDelta);
doh.is(900, spin1.get('value'), "integerspinner1");
doh.is(1000, spin2.get('value'), "integerspinner2");
doh.is(1.0, spin3.get('value'), "realspinner1");
doh.is(1.0, spin4.get('value'), "spinnerMinOnly");
}
});
doh.register("dojo.query() input by name",
dojo.map(spinnerIds, function(id){
return {
name: id,
spinner: id,
spinnerName: id,
runTest:function(){
this.spinner = dijit.byId(this.spinner);
var queried=dojo.query("input[name="+this.spinnerName+"]");
doh.is(1, queried.length,"Expected 1 spinner with name "+this.spinnerName+", found "+queried.length);
doh.is(this.spinner.valueNode, queried[0],"Spinner's valueNode did not match the one found by dojo.query.");
}
};
})
);
doh.register("a11y", [
{
name: "spinner2_typematic",
timeout: 9000,
runTest: function(){
// test typematic
var d=new doh.Deferred();
spin2.set('value', 900);
focusThenRun(spin2, function(){
doh.robot.keyDown(dojo.keys.DOWN_ARROW, 1);
doh.robot.keyUp(dojo.keys.DOWN_ARROW, 5000);
doh.robot.sequence(d.getTestCallback(function(){
var v = spin2.get('value');
doh.t(v <= 800, 'Error in typematic test. Expected <=800, got '+v);
}), 1000);
});
return d;
}
},
{
name: "spinner2_max",
timeout: 5000,
runTest: function(){
// test max with arrow key
var d=new doh.Deferred();
spin2.set('value', 1549);
focusThenRun(spin2, function(){
// press once: should move up
doh.robot.keyPress(dojo.keys.UP_ARROW, 1);
doh.robot.sequence(d.getTestErrback(function(){
doh.is(1550, spin2.get('value'), "value 1: " + spin2.get('value'));
doh.is("1550", spin2.focusNode.value, "displayed value 1: " + spin2.focusNode.value);
doh.t(spin2.isValid(), "invalid 1");
// press again: shouldn't move
doh.robot.keyPress(dojo.keys.UP_ARROW, 500);
doh.robot.sequence(d.getTestCallback(function(){
doh.is(1550, spin2.get('value'), "value 2: " + spin2.get('value'));
doh.is("1550", spin2.focusNode.value, "displayed value 2: " + spin2.focusNode.value);
doh.t(spin2.isValid(), "invalid 2");
}), 500);
}), 500);
});
return d;
}
},
{
name: "spinner2_min",
timeout: 5000,
runTest: function(){
// test min with arrow key
var d=new doh.Deferred();
spin2.set('value', 10);
focusThenRun(spin2, function(){
// press once: should move up
doh.robot.keyPress(dojo.keys.DOWN_ARROW, 1);
doh.robot.sequence(d.getTestErrback(function(){
doh.is(9, spin2.get('value'), "value 1: " + spin2.get('value'));
doh.is("9", spin2.focusNode.value, "displayed value 1: " + spin2.focusNode.value);
doh.t(spin2.isValid(), "invalid 1");
// press again: shouldn't move
doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500);
doh.robot.sequence(d.getTestCallback(function(){
doh.is(9, spin2.get('value'), "value 2: " + spin2.get('value'));
doh.is("9", spin2.focusNode.value, "displayed value 2: " + spin2.focusNode.value);
doh.t(spin2.isValid(), "invalid 2");
}), 500);
}), 500);
});
return d;
}
},
{
name: "spinner2_invalid",
timeout: 3000,
runTest: function(){
// assert invalid works
var d=new doh.Deferred();
spin2.focusNode.value="";
focusThenRun(spin2, function(){
doh.robot.typeKeys("0.5", 1, 600);
doh.robot.sequence(d.getTestCallback(function(){
doh.f(spin2.isValid(), "valid");
}), 500);
});
return d;
}
}
]);
// Test ARIA role. Since role attribute is set in template,
// checking one should be sufficient.
doh.register("a11yAriaRole",
function spinnerRole(){
var spinner = dijit.byId("integerspinner1");
doh.isNot(spinner, null, "can't find 'integerspinner1'");
doh.is(dojo.attr(spinner.focusNode, "role"), "spinbutton", spinner.id + ": aria role (spinbutton)");
}
);
// Check ARIA min/max values.
// - both min and max.
// - min, no max.
// - max, no min.
// - neither.
doh.register("a11yMinMaxValues",
[
function minAndMax(){
var spinner = dijit.byId("integerspinner2");
doh.isNot(spinner, null, "can't find 'integerspinner2'");
doh.is(spinner.focusNode.getAttribute("aria-valuemin"), spinner.constraints.min, spinner.id + ": aria-valuemin");
doh.is(spinner.focusNode.getAttribute("aria-valuemax"), spinner.constraints.max, spinner.id + ": aria-valuemax");
},
function minOnly(){
var spinner = dijit.byId("spinnerMinOnly");
doh.isNot(spinner, null, "can't find 'spinnerMinOnly'");
doh.is(spinner.focusNode.getAttribute("aria-valuemin"), spinner.constraints.min, spinner.id + ": aria-valuemin");
if(spinner.constraints.max){
doh.is(spinner.focusNode.getAttribute("aria-valuemax"), spinner.constraints.max, spinner.id + ": aria-valuemax");
}else{
doh.f(spinner.focusNode.hasAttribute("aria-valuemax"), spinner.id + ": aria-valuemax");
}
},
function maxOnly(){
var spinner = dijit.byId("integertextbox3");
doh.isNot(spinner, null, "can't find 'integertextbox3'");
doh.is(spinner.focusNode.getAttribute("aria-valuemax"), spinner.constraints.max, spinner.id + ": aria-valuemax");
if(spinner.constraints.min){
doh.is(spinner.focusNode.getAttribute("aria-valuemin"), spinner.constraints.min, spinner.id + ": aria-valuemin");
}else{
doh.f(spinner.focusNode.hasAttribute("aria-valuemin"), spinner.id + ": aria-valuemin");
}
},
function neitherMinNorMax(){
var spinner = dijit.byId("integertextbox3");
doh.isNot(spinner, null, "can't find 'integertextbox3'");
if(spinner.constraints.min){
doh.is(spinner.focusNode.getAttribute("aria-valuemin"), spinner.constraints.min, spinner.id + ": aria-valuemin");
}else{
doh.f(spinner.focusNode.hasAttribute("aria-valuemin"), spinner.id + ": aria-valuemin");
}
if(spinner.constraints.max){
doh.is(spinner.focusNode.getAttribute("aria-valuemax"), spinner.constraints.max, spinner.id + ": aria-valuemax");
}else{
doh.f(spinner.focusNode.hasAttribute("aria-valuemax"), spinner.id + ": aria-valuemax");
}
}
]
);
// Loop to test each spinner for aria-valuenow
// TODO:
// Is testing one spinner sufficient?
//
// test aria valuemin, valuemax, valuenow.
doh.register("a11yValueNow",
dojo.map(spinnerIds, function(id){
return {
name: id+"_value",
spinnerId: id,
runTest:function(){
var spinner = dijit.byId(this.spinnerId);
spinner.set('value', 100);
var ariaVal = spinner.focusNode.getAttribute("aria-valuenow");
doh.is(100, ariaVal, spinner.id + ": aria-valuenow");
}
};
})
);
// test "null" aria-valuenow
/* Remove null aria-valuenow test until #7866 is resolved
doh.register("a11yNullValuenow", {
name:spinnerIds[i]+"_nullValueNow",
spinnerId:spinnerIds[i],
runTest:function(){
var spinner = dijit.byId(this.spinnerId);
var initVal = spinner.get('value');
spinner.set('value', null);
var spinnerVal = spinner.get('value');
var nowVal = spinner.focusNode.getAttribute("aria-valuenow");
var invalid = spinner.focusNode.getAttribute("aria-invalid");
spinner.set('value', initVal);
doh.t(invalid, spinner.id + ": aria-invalid");
if(!(isNaN(spinnerVal) && isNaN(nowVal))){
doh.is(spinnerVal, nowVal, spinner.id + ": null aria-valuenow");
}
}
});
*/
// a11y tab focus tests (robot)
doh.register("a11yTabFocus",
[
// don't test integerspinner1 since shift-tab from there goes to address bar and the robot doesn't like that at all
{
name:"integertextbox3TabFocus",
timeout:3000,
setUp:function(){
tabFocusSetup("integertextbox3");
},
runTest:function(){
return a11yTabFocus("integertextbox3");
}
},
{ // test integerspinner2 second since the previous test group already had it focused
name:"integerspinner2TabFocus",
timeout:3000,
setUp:function(){
tabFocusSetup("integerspinner2");
},
runTest:function(){
return a11yTabFocus("integerspinner2");
}
},
{
name:"realspinner1TabFocus",
timeout:3000,
setUp:function(){
tabFocusSetup("realspinner1");
},
runTest:function(){
return a11yTabFocus("realspinner1");
}
}
]);
// a11y keystroke tests
doh.register("a11yKeystrokes",
[
{
name:"integerspinner1Keystrokes",
timeout:9000,
setUp:function(){
keyStrokeSetup("integerspinner1");
},
runTest:function(){
return a11yKeystrokeTest("integerspinner1");
}
},
{
name:"integerspinner2Keystrokes",
timeout:9000,
setUp:function(){
keyStrokeSetup("integerspinner2");
},
runTest:function(){
return a11yKeystrokeTest("integerspinner2");
}
},
{
name:"integertextbox3Keystrokes",
timeout:9000,
setUp:function(){
keyStrokeSetup("integertextbox3");
},
runTest:function(){
return a11yKeystrokeTest("integertextbox3");
}
},
{
name:"realspinner1Keystrokes",
timeout:9000,
setUp:function(){
keyStrokeSetup("realspinner1");
},
runTest:function(){
return a11yKeystrokeTest("realspinner1");
}
}
]);
// exponential value keystroke tests
doh.register("exponential",
[
{
name: "spinnerMinOnly large exp",
timeout: 5000,
runTest: function(){
var d=new doh.Deferred();
spin4.focusNode.value="";
focusThenRun(spin4, function(){
var handler = spin4.connect(spin4, '_onBlur',
function(){
spin4.disconnect(handler);
setTimeout(d.getTestCallback(function(){
doh.f(spin4.isValid(false), "large exponential is invalid");
doh.f(spin4.isInRange(false), "large exponential is out of range");
doh.is(spin4.getErrorMessage(true), spin4.rangeMessage, "large exponential showing out of range message");
doh.is("5e+98", spin4.get('displayedValue'), "large exponential reformatted to standard form");
}), 150);
});
doh.robot.typeKeys("0.5e99", 1, 1200);
doh.robot.keyPress(dojo.keys.TAB, 500, {shift:true});
});
return d;
}
},
{
name: "spinnerMinOnly adjust small exp",
timeout: 5000,
runTest: function(){
var d=new doh.Deferred();
spin4.focusNode.value="";
focusThenRun(spin4, function(){
var handler = spin4.connect(spin4, '_onBlur',
function(){
spin4.disconnect(handler);
setTimeout(d.getTestCallback(function(){
doh.t(spin4.isValid(false), "small exponential is valid");
doh.t(spin4.isInRange(false), "small exponential is in range");
doh.is(500000000.1, spin4.get('value'), "small exponential converted to whole number");
doh.is("500,000,000.1", spin4.get('displayedValue'), "small exponential converted to whole number with formatting");
}), 150);
});
doh.robot.typeKeys("0.5e9", 1, 1000);
doh.robot.keyPress(dojo.keys.UP_ARROW, 500);
doh.robot.keyPress(dojo.keys.TAB, 500, {shift:true});
});
return d;
}
},
{
name: "spinnerMinOnly adjust max exp",
timeout: 9000,
runTest: function(){
var d=new doh.Deferred();
spin4.focusNode.value="";
focusThenRun(spin4, function(){
var handler = spin4.connect(spin4, '_onBlur',
function(){
spin4.disconnect(handler);
setTimeout(d.getTestCallback(function(){
doh.t(spin4.isValid(false), "large exponential converted to max is valid");
doh.t(spin4.isInRange(false), "max value is in range");
doh.is(89999999999999.9, spin4.get('value'), "max value (-.1)");
doh.is("89,999,999,999,999.9", spin4.get('displayedValue'), "max value (-.1) with formatting");
}), 150);
});
doh.robot.typeKeys("0.5e99", 1, 1200);
doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500); // convert to max
doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500);
doh.robot.keyPress(dojo.keys.TAB, 500, {shift:true});
});
return d;
}
}
]);
// invalid editing keystroke tests
doh.register("invalid editing",
[
{
name: "HOME key, out of range",
timeout: 5000,
runTest: function(){
var d=new doh.Deferred();
spin4.focusNode.value="";
focusThenRun(spin4, function(){
doh.robot.typeKeys("0.5e99", 1, 1200);
doh.robot.keyPress(dojo.keys.HOME, 500);
doh.robot.sequence(d.getTestCallback(function(){
doh.t(spin4.isValid(true), "HOME changed large exponential to valid min, value is instead: "+spin4.focusNode.value);
doh.t(spin4.isInRange(true), "HOME changed large exponential to in range");
doh.is(-10.9, spin4.get('value'), "HOME changed large exponential to min value");
doh.is("-10.9", spin4.get('displayedValue'), "HOME changed large exponential to min display");
}), 500);
});
return d;
}
},
{
name: "HOME key, invalid",
timeout: 9000,
runTest: function(){
var d=new doh.Deferred();
spin4.focusNode.value="";
focusThenRun(spin4, function(){
doh.robot.typeKeys(".5e9a", 1, 1000);
doh.robot.keyPress(dojo.keys.HOME, 500);
if(dojo.isMac){
doh.robot.keyPress(dojo.keys.LEFT_ARROW, 500, {meta:true});
}
doh.robot.typeKeys("1", 500, 200);
doh.robot.keyPress(dojo.keys.END, 500);
if(dojo.isMac){
doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {meta:true});
}
doh.robot.keyPress(dojo.keys.BACKSPACE, 500);
doh.robot.sequence(d.getTestCallback(function(){
doh.t(spin4.isValid(true), "edited exponential is now valid");
doh.is(1.5e+9, spin4.get('value'), "edited exponential");
}), 500);
});
return d;
}
},
{
name: "out-of-range formatting",
timeout: 5000,
runTest: function(){
var d=new doh.Deferred();
spin3.focusNode.value="";
focusThenRun(spin3, function(){
var handler = spin3.connect(spin3, '_onBlur',
function(){
spin3.disconnect(handler);
setTimeout(d.getTestCallback(function(){
doh.f(spin3.isValid(), "out-of-range is invalid");
doh.is('156.0', spin3.get('displayedValue'), "fraction not removed from out-of-range");
doh.is(156, spin3.get('value'), "out-of-range number returns number");
}), 150);
});
doh.robot.typeKeys("156.0", 1, 1000);
doh.robot.keyPress(dojo.keys.TAB, 500);
});
return d;
}
},
{
name: "improper fraction",
timeout: 5000,
runTest: function(){
var d=new doh.Deferred();
spin4.focusNode.value="";
focusThenRun(spin4, function(){
var handler = spin4.connect(spin4, '_onBlur',
function(){
spin4.disconnect(handler);
setTimeout(d.getTestCallback(function(){
doh.f(spin4.isValid(), "missing fraction is invalid");
doh.is('99', spin4.get('displayedValue'), "fraction not added to unparsable number");
doh.t(isNaN(spin4.get('value')), "unparsable number causes no value");
}), 150);
});
doh.robot.typeKeys("99", 1, 400);
doh.robot.keyPress(dojo.keys.TAB, 500, {shift:true});
});
return d;
}
}
]);
doh.register("rounding",
[
{
name: "simple",
timeout: 5000,
runTest: function(){
var d=new doh.Deferred();
var spinner = dijit.byId("integertextbox3");
spinner.set('value', '');
focusThenRun(spinner, function(){
var handler = spinner.connect(spinner, '_onBlur',
function(){
spinner.disconnect(handler);
setTimeout(d.getTestCallback(function(){
doh.t(spinner.isValid(false), "no error when rounding");
doh.is(1.234, spinner.get('value'), "value is rounded");
doh.is("1.234", spinner.get('displayedValue'), "rounded value correctly displayed");
}), 150);
});
doh.robot.typeKeys("1.2339", 1, 1200);
doh.robot.keyPress(dojo.keys.TAB, 500);
});
return d;
}
}
]);
doh.run();
});
</script>
</head>
</html>