Bug 976082 - added tests for Touch Adapter. r=eeejay

---
 accessible/tests/mochitest/jsat/a11y.ini           |   3 +
 accessible/tests/mochitest/jsat/dom_helper.js      | 157 +++++++++++++++++
 accessible/tests/mochitest/jsat/gestures.json      | 194 +++++++++++++++++++++
 accessible/tests/mochitest/jsat/jsatcommon.js      |  15 +-
 .../tests/mochitest/jsat/test_touch_adapter.html   |  66 +++++++
 5 files changed, 430 insertions(+), 5 deletions(-)
 create mode 100644 accessible/tests/mochitest/jsat/dom_helper.js
 create mode 100644 accessible/tests/mochitest/jsat/gestures.json
 create mode 100644 accessible/tests/mochitest/jsat/test_touch_adapter.html
This commit is contained in:
Yura Zenevich 2014-03-10 23:33:58 -04:00
parent 7f43187552
commit 7bf8884628
5 changed files with 430 additions and 5 deletions

View File

@ -1,5 +1,7 @@
[DEFAULT]
support-files =
dom_helper.js
gestures.json
jsatcommon.js
output.js
doc_traversal.html
@ -12,4 +14,5 @@ support-files =
[test_live_regions.html]
[test_output.html]
[test_tables.html]
[test_touch_adapter.html]
[test_traversal.html]

View File

@ -0,0 +1,157 @@
'use strict';
/*global getMainChromeWindow, getBoundsForDOMElm, AccessFuTest, Point*/
/* exported loadJSON*/
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import('resource://gre/modules/accessibility/Utils.jsm');
Cu.import('resource://gre/modules/Geometry.jsm');
var win = getMainChromeWindow(window);
var winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(
Ci.nsIDOMWindowUtils);
/**
* For a given list of points calculate their coordinates in relation to the
* document body.
* @param {Array} aTouchPoints An array of objects of the following format: {
* base: {String}, // Id of an element to server as a base for the touch.
* x: {Number}, // An optional x offset from the base element's geometric
* // centre.
* y: {Number} // An optional y offset from the base element's geometric
* // centre.
* }
* @return {JSON} An array of {x, y} coordinations.
*/
function calculateTouchListCoordinates(aTouchPoints) {
var coords = [];
var dpi = winUtils.displayDPI;
for (var i = 0, target = aTouchPoints[i]; i < aTouchPoints.length; ++i) {
var bounds = getBoundsForDOMElm(target.base);
var parentBounds = getBoundsForDOMElm('root');
var point = new Point(target.x || 0, target.y || 0);
point.scale(dpi);
point.add(bounds[0], bounds[1]);
point.add(bounds[2] / 2, bounds[3] / 2);
point.subtract(parentBounds[0], parentBounds[0]);
coords.push({
x: point.x,
y: point.y
});
}
return coords;
}
/**
* Send a touch event with specified touchPoints.
* @param {Array} aTouchPoints An array of points to be associated with
* touches.
* @param {String} aName A name of the touch event.
*/
function sendTouchEvent(aTouchPoints, aName) {
var touchList = sendTouchEvent.touchList;
if (aName === 'touchend') {
sendTouchEvent.touchList = null;
} else {
var coords = calculateTouchListCoordinates(aTouchPoints);
var touches = [];
for (var i = 0; i < coords.length; ++i) {
var {x, y} = coords[i];
var node = document.elementFromPoint(x, y);
var touch = document.createTouch(window, node, aName === 'touchstart' ?
1 : touchList.item(i).identifier, x, y, x, y);
touches.push(touch);
}
touchList = document.createTouchList(touches);
sendTouchEvent.touchList = touchList;
}
var evt = document.createEvent('TouchEvent');
evt.initTouchEvent(aName, true, true, window, 0, false, false, false, false,
touchList, touchList, touchList);
document.dispatchEvent(evt);
}
sendTouchEvent.touchList = null;
/**
* A map of event names to the functions that actually send them.
* @type {Object}
*/
var eventMap = {
touchstart: sendTouchEvent,
touchend: sendTouchEvent,
touchmove: sendTouchEvent
};
/**
* Attach a listener for the mozAccessFuGesture event that tests its
* type.
* @param {Array} aExpectedGestures A stack of expected event types.
* Note: the listener is removed once the stack reaches 0.
*/
function testMozAccessFuGesture(aExpectedGestures) {
var types = typeof aExpectedGestures === "string" ?
[aExpectedGestures] : aExpectedGestures;
function handleGesture(aEvent) {
if (aEvent.detail.type !== types[0]) {
// The is not the event of interest.
return;
}
ok(true, 'Received correct mozAccessFuGesture: ' + types.shift() + '.');
if (types.length === 0) {
win.removeEventListener('mozAccessFuGesture', handleGesture);
if (AccessFuTest.sequenceCleanup) {
AccessFuTest.sequenceCleanup();
}
AccessFuTest.nextTest();
}
}
win.addEventListener('mozAccessFuGesture', handleGesture);
}
/**
* An extention to AccessFuTest that adds an ability to test a sequence of
* touch/mouse/etc events and their expected mozAccessFuGesture events.
* @param {Object} aSequence An object that has a list of touch/mouse/etc events
* to be generated and the expected mozAccessFuGesture events.
*/
AccessFuTest.addSequence = function AccessFuTest_addSequence(aSequence) {
AccessFuTest.addFunc(function testSequence() {
testMozAccessFuGesture(aSequence.expectedGestures);
var events = aSequence.events;
function fireEvent(aEvent) {
eventMap[aEvent.type](aEvent.target, aEvent.type);
processEvents();
}
function processEvents() {
if (events.length === 0) {
return;
}
var event = events.shift();
if (event.delay) {
window.setTimeout(fireEvent, event.delay, event);
} else {
fireEvent(event);
}
}
processEvents();
});
};
/**
* A helper function that loads JSON files.
* @param {String} aPath A path to a JSON file.
* @param {Function} aCallback A callback to be called on success.
*/
function loadJSON(aPath, aCallback) {
var request = new XMLHttpRequest();
request.open('GET', aPath, true);
request.responseType = 'json';
request.onload = function onload() {
aCallback(request.response);
};
request.send();
}

View File

@ -0,0 +1,194 @@
[
{
"events": [
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0}]},
{"type": "touchend", "delay": 50}
],
"expectedGestures": "tap"
},
{
"events": [
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0}]},
{"type": "touchmove",
"target": [{"base": "button", "x": 0.03, "y": 0.02}], "delay": 25},
{"type": "touchend", "delay": 25}
],
"expectedGestures": "tap"
},
{
"events": [
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0}]},
{"type": "touchend", "delay": 525}
],
"expectedGestures": ["dwell", "dwellend"]
},
{
"events": [
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0}]},
{"type": "touchmove",
"target": [{"base": "button", "x": 0.03, "y": 0.02}], "delay": 25},
{"type": "touchend", "delay": 25},
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0}],
"delay": 25},
{"type": "touchmove",
"target": [{"base": "button", "x": -0.03, "y": 0.01}], "delay": 25},
{"type": "touchend", "delay": 25}
],
"expectedGestures": ["tap", "doubletap"]
},
{
"events": [
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0}]},
{"type": "touchend", "delay": 25},
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0}],
"delay": 25},
{"type": "touchend", "delay": 25},
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0}],
"delay": 25},
{"type": "touchend", "delay": 25}
],
"expectedGestures": ["tap", "doubletap", "tripletap"]
},
{
"events": [
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0}]},
{"type": "touchend", "delay": 25},
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0}],
"delay": 25},
{"type": "touchend", "delay": 25},
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0}],
"delay": 25},
{"type": "touchend", "delay": 525}
],
"expectedGestures": ["tap", "doubletap", "doubletaphold", "dwellend"]
},
{
"events": [
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0}]},
{"type": "touchend", "delay": 25},
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0}],
"delay": 25},
{"type": "touchend", "delay": 525}
],
"expectedGestures": ["tap", "taphold", "dwellend"]
},
{
"events": [
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0}]},
{"type": "touchmove", "target": [{"base": "button", "x": 0.5, "y": 0}],
"delay": 25},
{"type": "touchend", "delay": 25}
],
"expectedGestures": "swiperight"
},
{
"events": [
{"type": "touchstart", "target": [{"base": "button", "x": 0.5, "y": 0}]},
{"type": "touchmove", "target": [{"base": "button", "x": 0, "y": 0}],
"delay": 25},
{"type": "touchend", "delay": 25}
],
"expectedGestures": "swipeleft"
},
{
"events": [
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0}]},
{"type": "touchmove", "target": [{"base": "button", "x": 0, "y": 0.5}],
"delay": 25},
{"type": "touchend", "delay": 25}
],
"expectedGestures": "swipedown"
},
{
"events": [
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0.5}]},
{"type": "touchmove", "target": [{"base": "button", "x": 0, "y": 0}],
"delay": 25},
{"type": "touchend", "delay": 25}
],
"expectedGestures": "swipeup"
},
{
"events": [
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0}]},
{"type": "touchmove", "target": [{"base": "button", "x": 0.5, "y": 0.1}],
"delay": 25},
{"type": "touchend", "delay": 25}
],
"expectedGestures": "swiperight"
},
{
"events": [
{"type": "touchstart",
"target": [{"base": "button", "x": 0.5, "y": 0.1}]},
{"type": "touchmove", "target": [{"base": "button", "x": 0, "y": -0.05}],
"delay": 25},
{"type": "touchend", "delay": 25}
],
"expectedGestures": "swipeleft"
},
{
"events": [
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0}]},
{"type": "touchmove",
"target": [{"base": "button", "x": -0.1, "y": 0.5}], "delay": 25},
{"type": "touchend", "delay": 25}
],
"expectedGestures": "swipedown"
},
{
"events": [
{"type": "touchstart",
"target": [{"base": "button", "x": 0.1, "y": 0.5}]},
{"type": "touchmove", "target": [{"base": "button", "x": 0, "y": 0}],
"delay": 25},
{"type": "touchend", "delay": 25}
],
"expectedGestures": "swipeup"
},
{
"events": [
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0},
{"base": "button", "x": 0, "y": 0.5}]},
{"type": "touchmove", "target": [{"base": "button", "x": 0.5, "y": 0},
{"base": "button", "x": 0.5, "y": 0.5}], "delay": 25},
{"type": "touchend", "delay": 25}
],
"expectedGestures": "swiperight"
},
{
"events": [
{"type": "touchstart", "target": [{"base": "button", "x": 0, "y": 0},
{"base": "button", "x": 0, "y": 0.5},
{"base": "button", "x": 0, "y": 1}]},
{"type": "touchmove", "target": [{"base": "button", "x": 0.5, "y": 0},
{"base": "button", "x": 0.5, "y": 0.5},
{"base": "button", "x": 0.5, "y": 1}],
"delay": 25},
{"type": "touchend", "delay": 25}
],
"expectedGestures": "swiperight"
},
{
"events": [
{"type": "touchstart",
"target": [{"base": "button", "x": 0.6, "y": 0.5}]},
{"type": "touchmove", "target": [{"base": "button", "x": 0, "y": 0}],
"delay": 525},
{"type": "touchend", "delay": 25}
],
"expectedGestures": ["dwell", "explore", "exploreend"]
},
{
"events": [
{"type": "touchstart",
"target": [{"base": "button", "x": 0, "y": 0.5}]},
{"type": "touchmove", "target": [{"base": "button", "x": 0, "y": 0}],
"delay": 525},
{"type": "touchmove", "target": [{"base": "button", "x": 0.5, "y": 0}],
"delay": 125},
{"type": "touchend", "delay": 25}
],
"expectedGestures": ["dwell", "explore", "explore", "exploreend"]
}
]

View File

@ -1,5 +1,10 @@
// A common module to run tests on the AccessFu module
'use strict';
/*global isDeeply, getMainChromeWindow, SimpleTest, SpecialPowers, Logger,
AccessFu, Utils, addMessageListener, currentTabDocument, currentBrowser*/
/**
* A global variable holding an array of test functions.
*/
@ -117,12 +122,12 @@ var AccessFuTest = {
runTests: function AccessFuTest_runTests() {
if (gTestFuncs.length === 0) {
ok(false, "No tests specified!");
simpleTest.finish();
SimpleTest.finish();
return;
}
// Create an Iterator for gTestFuncs array.
gIterator = Iterator(gTestFuncs);
gIterator = Iterator(gTestFuncs); // jshint ignore:line
// Start AccessFu and put it in stand-by.
Components.utils.import("resource://gre/modules/accessibility/AccessFu.jsm");
@ -144,7 +149,7 @@ var AccessFuTest = {
AccessFuTest.nextTest();
} else {
// Run all test functions synchronously.
[testFunc() for (testFunc of gTestFuncs)];
[testFunc() for (testFunc of gTestFuncs)]; // jshint ignore:line
AccessFuTest.finish();
}
});
@ -199,7 +204,7 @@ AccessFuContentTest.prototype = {
}
aMessageManager.addMessageListener('AccessFu:Present', this);
aMessageManager.addMessageListener('AccessFu:Ready', function (aMessage) {
aMessageManager.addMessageListener('AccessFu:Ready', function () {
aMessageManager.addMessageListener('AccessFu:ContentStarted', aCallback);
aMessageManager.sendAsyncMessage('AccessFu:Start', { buildApp: 'browser' });
});
@ -226,7 +231,7 @@ AccessFuContentTest.prototype = {
}
} else if (this.finishedCallback) {
for (var mm of this.mms) {
mm.sendAsyncMessage('AccessFu:Stop');
mm.sendAsyncMessage('AccessFu:Stop');
}
this.finishedCallback();
}

View File

@ -0,0 +1,66 @@
<html>
<head>
<title>AccessFu tests for touch adapters.</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="../layout.js"></script>
<script type="application/javascript" src="./jsatcommon.js"></script>
<script type="application/javascript" src="./dom_helper.js"></script>
<script type="application/javascript">
Components.utils.import(
"resource://gre/modules/accessibility/TouchAdapter.jsm");
function startComponents() {
TouchAdapter.start();
AccessFuTest.nextTest();
}
/**
* Clean up all state data related to previous events/gestures.
*/
function cleanupTouchAdapter() {
TouchAdapter.cleanupTouches();
TouchAdapter._touchPoints = {};
TouchAdapter._dwellTimeout = 0;
TouchAdapter._prevGestures = {};
TouchAdapter._lastExploreTime = 0;
}
function stopComponents() {
TouchAdapter.stop();
AccessFuTest.finish();
}
function doTest() {
loadJSON("./gestures.json", function onSuccess(gestures) {
AccessFuTest.addFunc(startComponents);
AccessFuTest.sequenceCleanup = cleanupTouchAdapter;
gestures.forEach(AccessFuTest.addSequence);
AccessFuTest.addFunc(stopComponents);
AccessFuTest.waitForExplicitFinish();
AccessFuTest.runTests();
});
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body id="root">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=976082"
title="[AccessFu] Provide tests for touch adapter.">
Mozilla Bug 976082
</a>
<div>
<button id="button">I am a button</button>
</div>
</body>
</html>