Bug 1459677 - Promisify, simplify, and unabstract jsat content tests. r=yzen

This commit is contained in:
Eitan Isaacson 2018-05-08 14:59:00 -04:00
Родитель 4ea509a01c
Коммит abb7638965
11 изменённых файлов: 1150 добавлений и 1075 удалений

Просмотреть файл

@ -166,7 +166,7 @@ var AccessFu = {
},
_output: function _output(aPresentationData, aBrowser) {
if (!aPresentationData || typeof aPresentationData == "string") {
if (!aPresentationData) {
// Either no android events to send or a string used for testing only.
return;
}
@ -176,6 +176,10 @@ var AccessFu = {
}
for (let evt of aPresentationData) {
if (typeof evt == "string") {
continue;
}
Utils.win.WindowEventDispatcher.sendRequest({
...evt,
type: "GeckoView:AccessibilityEvent"

Просмотреть файл

@ -172,7 +172,7 @@ class AndroidPresentor {
* @param {nsIAccessible} aObject the object that has been selected.
*/
selectionChanged(aObject) {
return "todo.selection-changed";
return ["todo.selection-changed"];
}
/**
@ -181,7 +181,7 @@ class AndroidPresentor {
* @param {nsIAccessible} aAccessible the object whose value has changed.
*/
nameChanged(aAccessible) {
return "todo.name-changed";
return ["todo.name-changed"];
}
/**
@ -190,7 +190,7 @@ class AndroidPresentor {
* @param {nsIAccessible} aAccessible the object whose value has changed.
*/
valueChanged(aAccessible) {
return "todo.value-changed";
return ["todo.value-changed"];
}
/**

Просмотреть файл

@ -11,9 +11,6 @@ skip-if = (os == 'win' && (os_version == '5.1' || os_version == '5.2'))
[test_alive.html]
[test_content_integration.html]
skip-if = buildapp == 'mulet'
[test_content_text.html]
skip-if = buildapp == 'mulet'
[test_explicit_names.html]
[test_hints.html]
[test_landmarks.html]
@ -21,5 +18,9 @@ skip-if = buildapp == 'mulet'
[test_output_mathml.html]
[test_output.html]
[test_tables.html]
[test_text_editable_navigation.html]
[test_text_editing.html]
[test_text_navigation_focus.html]
[test_text_navigation.html]
[test_traversal.html]
[test_traversal_helper.html]

Просмотреть файл

@ -16,45 +16,10 @@
"</body>" +
"</html>";
function showAlert() {
document.getElementById("alert").hidden = false;
}
function hideAlert() {
document.getElementById("alert").hidden = true;
}
function ariaShowBack() {
document.getElementById("back").setAttribute("aria-hidden", false);
}
function ariaHideBack() {
document.getElementById("back").setAttribute("aria-hidden", true);
}
function ariaShowIframe() {
document.getElementById("iframe").setAttribute("aria-hidden", false);
}
function ariaHideIframe() {
document.getElementById("iframe").setAttribute("aria-hidden", true);
}
function renameFruit() {
document.getElementById("fruit").setAttribute("aria-label", "banana");
}
function renameSlider() {
document.getElementById("slider").setAttribute(
"aria-label", "mover");
}
function changeSliderValue() {
document.getElementById("slider").setAttribute("aria-valuenow", "5");
document.getElementById("slider").setAttribute(
"aria-valuetext", "medium");
}
function toggleLight() {
var lightSwitch = document.getElementById("light");
lightSwitch.setAttribute("aria-checked",

Просмотреть файл

@ -19,6 +19,13 @@ ChromeUtils.import("resource://gre/modules/accessibility/Utils.jsm");
ChromeUtils.import("resource://gre/modules/accessibility/EventManager.jsm");
ChromeUtils.import("resource://gre/modules/accessibility/Constants.jsm");
const MovementGranularity = {
CHARACTER: 1,
WORD: 2,
LINE: 4,
PARAGRAPH: 8
};
var AccessFuTest = {
addFunc: function AccessFuTest_addFunc(aFunc) {
@ -164,506 +171,263 @@ var AccessFuTest = {
}
};
function AccessFuContentTest(aFuncResultPairs) {
this.queue = aFuncResultPairs;
}
AccessFuContentTest.prototype = {
expected: [],
currentAction: null,
actionNum: -1,
class AccessFuContentTestRunner {
constructor() {
this.listenersMap = new Map();
let frames = Array.from(currentTabDocument().querySelectorAll("iframe"));
this.mms = [Utils.getMessageManager(currentBrowser()),
...frames.map(f => Utils.getMessageManager(f)).filter(mm => !!mm)];
}
start(aFinishedCallback) {
Logger.logLevel = Logger.DEBUG;
this.finishedCallback = aFinishedCallback;
var self = this;
// Get top content message manager, and set it up.
this.mms = [Utils.getMessageManager(currentBrowser())];
this.setupMessageManager(this.mms[0], function() {
// Get child message managers and set them up
var frames = currentTabDocument().querySelectorAll("iframe");
if (frames.length === 0) {
self.pump();
return;
}
var toSetup = 0;
for (var i = 0; i < frames.length; i++ ) {
var mm = Utils.getMessageManager(frames[i]);
if (mm) {
toSetup++;
self.mms.push(mm);
self.setupMessageManager(mm, function() {
if (--toSetup === 0) {
// All message managers are loaded and ready to go.
self.pump();
}
});
}
}
});
},
return Promise.all(this.mms.map(mm => this.setupMessageManager(mm)));
}
finish() {
Logger.logLevel = Logger.INFO;
this.listenersMap.clear();
for (var mm of this.mms) {
mm.sendAsyncMessage("AccessFu:Stop");
mm.removeMessageListener("AccessFu:Present", this);
mm.removeMessageListener("AccessFu:Input", this);
mm.removeMessageListener("AccessFu:CursorCleared", this);
mm.removeMessageListener("AccessFu:Focused", this);
mm.removeMessageListener("AccessFu:AriaHidden", this);
mm.removeMessageListener("AccessFu:Ready", this);
mm.removeMessageListener("AccessFu:ContentStarted", this);
}
if (this.finishedCallback) {
this.finishedCallback();
mm.sendAsyncMessage("AccessFu:Stop");
mm.removeMessageListener("AccessFu:Present", this);
}
},
}
setupMessageManager(aMessageManager, aCallback) {
sendMessage(message) {
// First message manager is the top-level one.
this.mms[0].sendAsyncMessage(message.name, message.data);
}
androidEvent(eventType) {
return new Promise(resolve => {
if (!this.listenersMap.has(eventType)) {
this.listenersMap.set(eventType, [resolve]);
} else {
this.listenersMap.get(eventType).push(resolve);
}
}).then(evt => {
if (this.debug) {
info("Resolving event: " + evt.eventType);
}
return evt;
});
}
isFocused(aExpected) {
var doc = currentTabDocument();
SimpleTest.is(doc.activeElement, doc.querySelector(aExpected),
"Correct element is focused: " + aExpected);
}
async setupMessageManager(aMessageManager) {
function contentScript() {
addMessageListener("AccessFuTest:Focus", function(aMessage) {
var elem = content.document.querySelector(aMessage.json.selector);
addMessageListener("AccessFuTest:Focus", aMessage => {
var elem = content.document.querySelector(aMessage.data.selector);
if (elem) {
if (aMessage.json.blur) {
elem.blur();
} else {
elem.focus();
}
elem.focus();
}
});
addMessageListener("AccessFuTest:Blur", () => {
content.document.activeElement.blur();
});
}
aMessageManager.addMessageListener("AccessFu:Present", this);
aMessageManager.addMessageListener("AccessFu:Input", this);
aMessageManager.addMessageListener("AccessFu:CursorCleared", this);
aMessageManager.addMessageListener("AccessFu:Focused", this);
aMessageManager.addMessageListener("AccessFu:AriaHidden", this);
aMessageManager.addMessageListener("AccessFu:Ready", function() {
aMessageManager.addMessageListener("AccessFu:ContentStarted", aCallback);
aMessageManager.sendAsyncMessage("AccessFu:Start",
{ buildApp: "browser",
androidSdkVersion: Utils.AndroidSdkVersion,
logLevel: "DEBUG",
inTest: true });
});
aMessageManager.loadFrameScript(
"data:,(" + contentScript.toString() + ")();", false);
let readyPromise = new Promise(resolve =>
aMessageManager.addMessageListener("AccessFu:Ready", resolve));
aMessageManager.loadFrameScript(
"chrome://global/content/accessibility/content-script.js", false);
aMessageManager.loadFrameScript(
"data:,(" + contentScript.toString() + ")();", false);
},
pump() {
this.expected.shift();
if (this.expected.length) {
return;
}
await readyPromise;
var currentPair = this.queue.shift();
let startedPromise = new Promise(resolve =>
aMessageManager.addMessageListener("AccessFu:ContentStarted", resolve));
if (currentPair) {
this.actionNum++;
this.currentAction = currentPair[0];
if (typeof this.currentAction === "function") {
this.currentAction(this.mms[0]);
} else if (this.currentAction) {
this.mms[0].sendAsyncMessage(this.currentAction.name,
this.currentAction.json);
}
aMessageManager.sendAsyncMessage("AccessFu:Start",
{ buildApp: "browser",
androidSdkVersion: Utils.AndroidSdkVersion,
logLevel: "DEBUG",
inTest: true });
this.expected = currentPair.slice(1, currentPair.length);
await startedPromise;
if (!this.expected[0]) {
this.pump();
}
} else {
this.finish();
}
},
aMessageManager.addMessageListener("AccessFu:Present", this);
}
receiveMessage(aMessage) {
var expected = this.expected[0];
if (!expected) {
if (aMessage.name != "AccessFu:Present" || !aMessage.data) {
return;
}
var actionsString = typeof this.currentAction === "function" ?
this.currentAction.toString() : JSON.stringify(this.currentAction);
if (typeof expected === "string") {
ok(true, "Got " + expected + " after " + actionsString);
this.pump();
} else if (expected.ignore && !expected.ignore(aMessage)) {
expected.is(aMessage.json, "after " + actionsString +
" (" + this.actionNum + ")");
expected.is_correct_focus();
this.pump();
for (let evt of aMessage.data) {
if (this.debug) {
info("Android event: " + JSON.stringify(evt));
}
let listener = (this.listenersMap.get(evt.eventType || evt) || []).shift();
if (listener) {
listener(evt);
}
}
}
};
// Common content messages
async expectAndroidEvents(aFunc, ...aExpectedEvents) {
let events = Promise.all(aExpectedEvents.map(e => this.androidEvent(e)));
aFunc();
let gotEvents = await events;
return gotEvents.length == 1 ? gotEvents[0] : gotEvents;
}
var ContentMessages = {
simpleMoveFirst: {
name: "AccessFu:MoveCursor",
json: {
action: "moveFirst",
rule: "Simple",
inputType: "gesture",
origin: "top"
}
},
moveCursor(aArgs, ...aExpectedEvents) {
return this.expectAndroidEvents(() => {
this.sendMessage({
name: "AccessFu:MoveCursor",
data: {
inputType: "gesture",
origin: "top",
...aArgs
}
});
}, ...aExpectedEvents);
}
simpleMoveLast: {
name: "AccessFu:MoveCursor",
json: {
action: "moveLast",
rule: "Simple",
inputType: "gesture",
origin: "top"
}
},
moveNext(aRule, ...aExpectedEvents) {
return this.moveCursor({ action: "moveNext", rule: aRule },
...aExpectedEvents);
}
simpleMoveNext: {
name: "AccessFu:MoveCursor",
json: {
action: "moveNext",
rule: "Simple",
inputType: "gesture",
origin: "top"
}
},
movePrevious(aRule, ...aExpectedEvents) {
return this.moveCursor({ action: "movePrevious", rule: aRule },
...aExpectedEvents);
}
simpleMovePrevious: {
name: "AccessFu:MoveCursor",
json: {
action: "movePrevious",
rule: "Simple",
inputType: "gesture",
origin: "top"
}
},
moveFirst(aRule, ...aExpectedEvents) {
return this.moveCursor({ action: "moveFirst", rule: aRule },
...aExpectedEvents);
}
clearCursor: {
name: "AccessFu:ClearCursor",
json: {
origin: "top"
}
},
moveLast(aRule, ...aExpectedEvents) {
return this.moveCursor({ action: "moveLast", rule: aRule },
...aExpectedEvents);
}
moveOrAdjustUp: function moveOrAdjustUp(aRule) {
return {
name: "AccessFu:MoveCursor",
json: {
origin: "top",
action: "movePrevious",
inputType: "gesture",
rule: (aRule || "Simple"),
adjustRange: true
}
};
},
async clearCursor() {
return new Promise(resolve => {
let _listener = (msg) => {
this.mms.forEach(
mm => mm.removeMessageListener("AccessFu:CursorCleared", _listener));
resolve();
};
this.mms.forEach(
mm => mm.addMessageListener("AccessFu:CursorCleared", _listener));
this.sendMessage({
name: "AccessFu:ClearCursor",
data: {
origin: "top"
}
});
});
}
moveOrAdjustDown: function moveOrAdjustUp(aRule) {
return {
name: "AccessFu:MoveCursor",
json: {
origin: "top",
action: "moveNext",
inputType: "gesture",
rule: (aRule || "Simple"),
adjustRange: true
}
};
},
focusSelector(aSelector, ...aExpectedEvents) {
return this.expectAndroidEvents(() => {
this.sendMessage({
name: "AccessFuTest:Focus",
data: {
selector: aSelector
}
});
}, ...aExpectedEvents);
}
androidScrollForward: function adjustUp() {
return {
blur(...aExpectedEvents) {
return this.expectAndroidEvents(() => {
this.sendMessage({ name: "AccessFuTest:Blur" });
}, ...aExpectedEvents);
}
activateCurrent(aOffset, ...aExpectedEvents) {
return this.expectAndroidEvents(() => {
this.sendMessage({
name: "AccessFu:Activate",
data: {
origin: "top",
offset: aOffset
}
});
}, ...aExpectedEvents);
}
typeKey(aKey, ...aExpectedEvents) {
return this.expectAndroidEvents(() => {
synthesizeKey(aKey, {}, currentTabWindow());
}, ...aExpectedEvents);
}
eventTextMatches(aEvent, aExpected) {
isDeeply(aEvent.text, aExpected,
"Event text matches. " +
`Got ${JSON.stringify(aEvent.text)}, expected ${JSON.stringify(aExpected)}.`);
}
androidScrollForward() {
this.sendMessage({
name: "AccessFu:AndroidScroll",
json: { origin: "top", direction: "forward" }
};
},
data: { origin: "top", direction: "forward" }
});
}
androidScrollBackward: function adjustDown() {
return {
androidScrollBackward() {
this.sendMessage({
name: "AccessFu:AndroidScroll",
json: { origin: "top", direction: "backward" }
};
},
focusSelector: function focusSelector(aSelector, aBlur) {
return {
name: "AccessFuTest:Focus",
json: {
selector: aSelector,
blur: aBlur
}
};
},
activateCurrent: function activateCurrent(aOffset) {
return {
name: "AccessFu:Activate",
json: {
origin: "top",
offset: aOffset
}
};
},
moveNextBy: function moveNextBy(aGranularity) {
return {
name: "AccessFu:MoveByGranularity",
json: {
direction: "Next",
granularity: this._granularityMap[aGranularity]
}
};
},
movePreviousBy: function movePreviousBy(aGranularity) {
return {
name: "AccessFu:MoveByGranularity",
json: {
direction: "Previous",
granularity: this._granularityMap[aGranularity]
}
};
},
moveCaretNextBy: function moveCaretNextBy(aGranularity) {
return {
name: "AccessFu:MoveCaret",
json: {
direction: "Next",
granularity: this._granularityMap[aGranularity]
}
};
},
moveCaretPreviousBy: function moveCaretPreviousBy(aGranularity) {
return {
name: "AccessFu:MoveCaret",
json: {
direction: "Previous",
granularity: this._granularityMap[aGranularity]
}
};
},
_granularityMap: {
"character": 1, // MOVEMENT_GRANULARITY_CHARACTER
"word": 2, // MOVEMENT_GRANULARITY_WORD
"paragraph": 8 // MOVEMENT_GRANULARITY_PARAGRAPH
}
};
function ExpectedMessage(aName, aOptions) {
this.name = aName;
this.options = aOptions || {};
this.json = {};
}
ExpectedMessage.prototype.lazyCompare = function(aReceived, aExpected, aInfo) {
if (aExpected && !aReceived) {
return [false, "Expected something but got nothing -- " + aInfo];
data: { origin: "top", direction: "backward" }
});
}
if (typeof aReceived === "string" || typeof aExpected === "string") {
return [aReceived == aExpected, `String comparison: Got '${aReceived}.', expected: ${aExpected} -- ${aInfo}`];
moveByGranularity(aDirection, aGranularity, ...aExpectedEvents) {
return this.expectAndroidEvents(() => {
this.sendMessage({
name: "AccessFu:MoveByGranularity",
data: {
direction: aDirection,
granularity: aGranularity
}
});
}, ...aExpectedEvents);
}
var matches = true;
var delta = [];
for (var attr in aExpected) {
var expected = aExpected[attr];
var received = aReceived[attr];
if (typeof expected === "object") {
var [childMatches, childDelta] = this.lazyCompare(received, expected);
if (!childMatches) {
delta.push(attr + " [ " + childDelta + " ]");
matches = false;
}
} else if (received !== expected) {
delta.push(
attr + " [ expected " + JSON.stringify(expected) +
" got " + JSON.stringify(received) + " ]");
matches = false;
}
moveNextByGranularity(aGranularity, ...aExpectedEvents) {
return this.moveByGranularity("Next", aGranularity, ...aExpectedEvents);
}
var msg = delta.length ? delta.join(" ") : "Structures lazily match";
return [matches, msg + " -- " + aInfo];
};
ExpectedMessage.prototype.is = function(aReceived, aInfo) {
var checkFunc = this.options.todo ? "todo" : "ok";
SimpleTest[checkFunc].apply(
SimpleTest, this.lazyCompare(aReceived, this.json, aInfo));
};
ExpectedMessage.prototype.is_correct_focus = function(aInfo) {
if (!this.options.focused) {
return;
movePreviousByGranularity(aGranularity, ...aExpectedEvents) {
return this.moveByGranularity("Previous", aGranularity, ...aExpectedEvents);
}
var checkFunc = this.options.focused_todo ? "todo_is" : "is";
var doc = currentTabDocument();
SimpleTest[checkFunc].apply(SimpleTest,
[ doc.activeElement, doc.querySelector(this.options.focused),
"Correct element is focused: " + this.options.focused + " -- " + aInfo ]);
};
ExpectedMessage.prototype.ignore = function(aMessage) {
return aMessage.name !== this.name;
};
function ExpectedPresent(aAndroidEvents, aOptions) {
ExpectedMessage.call(this, "AccessFu:Present", aOptions);
this.expectedEvents = aAndroidEvents;
}
ExpectedPresent.prototype = Object.create(ExpectedMessage.prototype);
ExpectedPresent.prototype.is = function(aReceived, aInfo) {
if (typeof this.expectedEvents == "string") {
// This is an event we have yet to implement, do a simple string comparison.
if (this.expectedEvents == aReceived) {
SimpleTest.todo(false, `${aInfo} (${aReceived})`);
return;
}
// XXX: moveCaret* methods will go away soon as we fold it into the
// granularity messages above.
moveCaret(aDirection, aGranularity, ...aExpectedEvents) {
return this.expectAndroidEvents(() => {
this.sendMessage({
name: "AccessFu:MoveCaret",
data: {
direction: aDirection,
granularity: aGranularity
}
});
}, ...aExpectedEvents);
}
SimpleTest[this.options.todo ? "todo" : "ok"].apply(SimpleTest,
this.lazyCompare(aReceived, this.expectedEvents, aInfo + " aReceived: " +
JSON.stringify(aReceived) + " evt: " + JSON.stringify(this.expectedEvents)));
};
ExpectedPresent.prototype.ignore = function(aMessage) {
if (!aMessage.json || ExpectedMessage.prototype.ignore.call(this, aMessage)) {
return true;
moveCaretNext(aGranularity, ...aExpectedEvents) {
return this.moveCaret("Next", aGranularity, ...aExpectedEvents);
}
let firstEvent = (aMessage.json || [])[0];
return firstEvent && firstEvent.eventType === AndroidEvents.VIEW_SCROLLED;
};
function ExpectedCursorChange(aSpeech, aOptions) {
ExpectedPresent.call(this, [{
eventType: 0x8000, // VIEW_ACCESSIBILITY_FOCUSED
}], aOptions);
moveCaretPrevious(aGranularity, ...aExpectedEvents) {
return this.moveCaret("Previous", aGranularity, ...aExpectedEvents);
}
}
ExpectedCursorChange.prototype = Object.create(ExpectedPresent.prototype);
function ExpectedCursorTextChange(aSpeech, aStartOffset, aEndOffset, aOptions) {
ExpectedPresent.call(this, [{
eventType: AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: aStartOffset,
toIndex: aEndOffset
}], aOptions);
// bug 980509
this.options.b2g_todo = true;
}
ExpectedCursorTextChange.prototype =
Object.create(ExpectedCursorChange.prototype);
function ExpectedClickAction(aOptions) {
ExpectedPresent.call(this, [{
eventType: AndroidEvents.VIEW_CLICKED
}], aOptions);
}
ExpectedClickAction.prototype = Object.create(ExpectedPresent.prototype);
function ExpectedCheckAction(aChecked, aOptions) {
ExpectedPresent.call(this, [{
eventType: AndroidEvents.VIEW_CLICKED,
checked: aChecked
}], aOptions);
}
ExpectedCheckAction.prototype = Object.create(ExpectedPresent.prototype);
function ExpectedSwitchAction(aSwitched, aOptions) {
ExpectedPresent.call(this, [{
eventType: AndroidEvents.VIEW_CLICKED,
checked: aSwitched
}], aOptions);
}
ExpectedSwitchAction.prototype = Object.create(ExpectedPresent.prototype);
// XXX: Implement Android event?
function ExpectedNameChange(aName, aOptions) {
ExpectedPresent.call(this, "todo.name-changed", aOptions);
}
ExpectedNameChange.prototype = Object.create(ExpectedPresent.prototype);
// XXX: Implement Android event?
function ExpectedValueChange(aValue, aOptions) {
ExpectedPresent.call(this, "todo.value-changed", aOptions);
}
ExpectedValueChange.prototype = Object.create(ExpectedPresent.prototype);
// XXX: Implement Android event?
function ExpectedTextChanged(aValue, aOptions) {
ExpectedPresent.call(this, [{
eventType: AndroidEvents.VIEW_TEXT_CHANGED
}], aOptions);
}
ExpectedTextChanged.prototype = Object.create(ExpectedPresent.prototype);
function ExpectedEditState(aEditState, aOptions) {
ExpectedMessage.call(this, "AccessFu:Input", aOptions);
this.json = aEditState;
}
ExpectedEditState.prototype = Object.create(ExpectedMessage.prototype);
function ExpectedTextSelectionChanged(aStart, aEnd, aOptions) {
ExpectedPresent.call(this, [{
eventType: AndroidEvents.VIEW_TEXT_SELECTION_CHANGED,
}], aOptions);
}
ExpectedTextSelectionChanged.prototype =
Object.create(ExpectedPresent.prototype);
function ExpectedTextCaretChanged(aFrom, aTo, aOptions) {
ExpectedPresent.call(this, [{
eventType: AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: aFrom,
toIndex: aTo
}], aOptions);
}
ExpectedTextCaretChanged.prototype = Object.create(ExpectedPresent.prototype);
function ExpectedAnnouncement(aAnnouncement, aOptions) {
ExpectedPresent.call(this, [{
eventType: AndroidEvents.ANNOUNCEMENT,
text: [ aAnnouncement],
addedCount: aAnnouncement.length
}], aOptions);
}
ExpectedAnnouncement.prototype = Object.create(ExpectedPresent.prototype);
// XXX: Implement Android event?
function ExpectedNoMove(aOptions) {
ExpectedPresent.call(this, null, aOptions);
}
ExpectedNoMove.prototype = Object.create(ExpectedPresent.prototype);

Просмотреть файл

@ -21,289 +21,412 @@
<script type="application/javascript" src="jsatcommon.js"></script>
<script type="application/javascript">
async function testSimpleNavigation(doc, runner) {
let evt;
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Traversal Rule test document", "Phone status bar"]);
runner.isFocused("body");
evt = await runner.movePrevious("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
is(evt.exitView, "movePrevious");
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Back", "button"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["such app", "wow", "heading level 1"]);
runner.isFocused("iframe");
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["many option", "not checked", "check button", "First item", "list", "1 item"]);
evt = await runner.activateCurrent(0,
AndroidEvents.VIEW_CLICKED,
AndroidEvents.VIEW_CLICKED);
is(evt[1].checked, true, "checkbox is checked");
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["much range", "label"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["much range", "5", "slider"]);
expectedMsg = runner.androidEvent("todo.value-changed");
runner.androidScrollBackward();
evt = await expectedMsg;
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Home", "button"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["apple", "button"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Light", "off", "switch"]);
evt = await runner.activateCurrent(0,
AndroidEvents.VIEW_CLICKED,
AndroidEvents.VIEW_CLICKED);
is(evt[1].checked, true, "checkbox is checked");
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["slider", "0", "slider", "live"]);
evt = await runner.movePrevious("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Light", "on", "switch"]);
evt = await runner.activateCurrent(0,
AndroidEvents.VIEW_CLICKED,
AndroidEvents.VIEW_CLICKED);
is(evt[1].checked, false, "checkbox is checked");
evt = await runner.movePrevious("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["apple", "button"]);
evt = await runner.movePrevious("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Home", "button"]);
evt = await runner.movePrevious("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["such app", "much range", "4", "slider"]);
expectedMsg = runner.androidEvent("todo.value-changed");
runner.androidScrollForward();
evt = await expectedMsg;
expectedMsg = runner.androidEvent("todo.value-changed");
runner.androidScrollBackward();
evt = await expectedMsg;
evt = await runner.movePrevious("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["much range", "label"]);
evt = await runner.movePrevious("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["many option", "checked", "check button", "First item", "list", "1 item"]);
evt = await runner.activateCurrent(0,
AndroidEvents.VIEW_CLICKED,
AndroidEvents.VIEW_CLICKED);
is(evt[1].checked, false, "checkbox is checked");
evt = await runner.movePrevious("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["wow", "heading level 1"]);
evt = await runner.movePrevious("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Back", "button"]);
evt = await runner.movePrevious("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Phone status bar"]);
// Reached top
evt = await runner.movePrevious("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
is(evt.exitView, "movePrevious");
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Back", "button"]);
// Moving to the absolute last item from an embedded document
// fails. Bug 972035.
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["such app", "wow", "heading level 1"]);
// Move from an inner frame to the last element in the parent doc
evt = await runner.moveLast("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["much range", "4", "slider"]);
await runner.clearCursor();
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Traversal Rule test document", "Phone status bar"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Back", "button"]);
evt = await runner.moveNext("FormElement",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["such app", "many option", "not checked", "check button", "First item", "list", "1 item"]);
evt = await runner.moveNext("FormElement",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["much range", "4", "slider"]);
evt = await runner.movePrevious("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["much range", "label"]);
evt = await runner.movePrevious("FormElement",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["many option", "not checked", "check button", "First item", "list", "1 item"]);
evt = await runner.movePrevious("FormElement",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Back", "button"]);
await runner.clearCursor();
// Moving to the absolute first item from an embedded document
// fails. Bug 972035.
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Traversal Rule test document", "Phone status bar"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Back", "button"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["such app", "wow", "heading level 1"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["many option", "not checked", "check button", "First item", "list", "1 item"]);
evt = await runner.moveFirst("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
todo_is(evt.text[0], "Phone status bar");
await runner.clearCursor();
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Traversal Rule test document", "Phone status bar"]);
evt = await runner.focusSelector("button#fruit",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["apple", "button"]);
// Current virtual cursor's position's name changes
expectedMsg = runner.androidEvent("todo.name-changed");
doc.getElementById("fruit").setAttribute("aria-label", "banana");
evt = await expectedMsg;
// Name and value changes inside a live-region (no cursor present)
expectedMsg = runner.androidEvent("todo.name-changed");
doc.getElementById("slider").setAttribute("aria-label", "mover");
evt = await expectedMsg;
expectedMsg = runner.androidEvent("todo.value-changed");
doc.getElementById("slider").setAttribute("aria-valuenow", "5");
doc.getElementById("slider").setAttribute("aria-valuetext", "medium");
evt = await expectedMsg;
// Blur button and reset cursor
runner.blur();
await runner.clearCursor();
// Move cursor with focus in outside document
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Traversal Rule test document", "Phone status bar"]);
evt = await runner.focusSelector("button#home",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Home", "button"]);
// Blur button and reset cursor
runner.blur();
await runner.clearCursor();
// Set focus on element outside of embedded frame while cursor is in frame
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Traversal Rule test document", "Phone status bar"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Back", "button"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["such app", "wow", "heading level 1"]);
evt = await runner.focusSelector("button#home",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Home", "button"]);
// Blur button and reset cursor
runner.blur();
await runner.clearCursor();
// XXX: Set focus on iframe itself.
// XXX: Set focus on element in iframe when cursor is outside of it.
// XXX: Set focus on element in iframe when cursor is in iframe.
// aria-hidden element that the virtual cursor is positioned on
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Traversal Rule test document", "Phone status bar"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Back", "button"]);
evt = await runner.expectAndroidEvents(() => {
doc.getElementById("back").setAttribute("aria-hidden", true);
}, AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["such app", "wow", "heading level 1"]);
// Changing aria-hidden attribute twice and making sure that the event
// is fired only once when the actual change happens.
doc.getElementById("back").setAttribute("aria-hidden", true);
doc.getElementById("back").setAttribute("aria-hidden", false);
evt = await runner.movePrevious("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Back", "button"]);
await runner.clearCursor();
// aria-hidden on the iframe that has the vc.
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Traversal Rule test document", "Phone status bar"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Back", "button"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["such app", "wow", "heading level 1"]);
evt = await runner.expectAndroidEvents(() => {
doc.getElementById("iframe").setAttribute("aria-hidden", true);
}, AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Home", "button"]);
doc.getElementById("iframe").setAttribute("aria-hidden", false);
await runner.clearCursor();
// aria-hidden element and auto Move
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Traversal Rule test document", "Phone status bar"]);
doc.getElementById("back").setAttribute("aria-hidden", true);
evt = await runner.focusSelector("button#back",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["such app", "wow", "heading level 1"]);
doc.getElementById("back").setAttribute("aria-hidden", false);
runner.blur();
await runner.clearCursor();
// Open dialog in outer doc, while cursor is also in outer doc
evt = await runner.moveLast("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Traversal Rule test document", "mover", "medium", "slider", "live"]);
evt = await runner.expectAndroidEvents(() => {
doc.getElementById("alert").hidden = false;
}, AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["This is an alert!", "heading level 1", "dialog"]);
evt = await runner.expectAndroidEvents(() => {
doc.getElementById("alert").hidden = true;
}, AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Traversal Rule test document", "mover", "medium", "slider", "live"]);
await runner.clearCursor();
// Open dialog in outer doc, while cursor is in inner frame
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Traversal Rule test document", "Phone status bar"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Back", "button"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["such app", "wow", "heading level 1"]);
evt = await runner.expectAndroidEvents(() => {
doc.getElementById("alert").hidden = false;
}, AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["This is an alert!", "heading level 1", "dialog"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Do you agree?"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Yes", "button"]);
evt = await runner.activateCurrent(0,
AndroidEvents.VIEW_CLICKED,
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt[1], ["such app", "wow", "heading level 1"]);
await runner.clearCursor();
// Open dialog, then focus on something when closing
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Traversal Rule test document", "Phone status bar"]);
evt = await runner.expectAndroidEvents(() => {
doc.getElementById("alert").hidden = false;
}, AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["This is an alert!", "heading level 1", "dialog"]);
evt = await runner.expectAndroidEvents(() => {
doc.getElementById("alert").hidden = true;
doc.querySelector("button#home").focus();
}, AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Traversal Rule test document", "Home", "button"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["banana", "button"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Light", "off", "switch"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["mover", "medium", "slider", "live"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
is(evt.exitView, "moveNext", "Reached end of content");
}
function doTest() {
var doc = currentTabDocument();
var iframe = doc.createElement("iframe");
iframe.id = "iframe";
iframe.mozbrowser = true;
iframe.addEventListener("mozbrowserloadend", function() {
var contentTest = new AccessFuContentTest(
[
// Simple traversal forward
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(
["Traversal Rule test document", "Phone status bar"],
{ focused: "body" })],
[ContentMessages.simpleMovePrevious, new ExpectedNoMove()],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
[ContentMessages.simpleMoveNext, new ExpectedCursorChange(
["such app", "wow", {"string": "headingLevel", "args": [1]}],
{ focused: "iframe" })],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["many option", {"string": "stateNotChecked"},
{"string": "checkbutton"}, {"string": "listStart"},
{"string": "list"}, {"string": "listItemsCount", "count": 1}])],
addA11yLoadEvent(async function() {
let runner = new AccessFuContentTestRunner();
await runner.start();
// check checkbox
[ContentMessages.activateCurrent(),
new ExpectedClickAction(),
new ExpectedCheckAction(true)],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["much range", {"string": "label"}])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["much range", "5", {"string": "slider"}])],
[ContentMessages.moveOrAdjustUp(), new ExpectedValueChange("6")],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Home", {"string": "pushbutton"}])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["apple", {"string": "pushbutton"}])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Light", {"string": "stateOff"}, {"string": "switch"}])],
// switch on
[ContentMessages.activateCurrent(),
new ExpectedClickAction(),
new ExpectedSwitchAction(true)],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["slider", "0", {"string": "slider"}])],
await testSimpleNavigation(doc, runner);
// Simple traversal backward
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(["Light", {"string": "stateOn"}, {"string": "switch"}])],
// switch off
[ContentMessages.activateCurrent(),
new ExpectedClickAction(),
new ExpectedSwitchAction(false)],
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(["apple", {"string": "pushbutton"}])],
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(["Home", {"string": "pushbutton"}])],
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(["such app", "much range", "6", {"string": "slider"}])],
[ContentMessages.moveOrAdjustDown(), new ExpectedValueChange("5")],
[ContentMessages.androidScrollForward(), new ExpectedValueChange("6")],
[ContentMessages.androidScrollBackward(), new ExpectedValueChange("5")],
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(["much range", {"string": "label"}])],
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(["many option", {"string": "stateChecked"},
{"string": "checkbutton"}, {"string": "listStart"},
{"string": "list"}, {"string": "listItemsCount", "count": 1}])],
// uncheck checkbox
[ContentMessages.activateCurrent(),
new ExpectedClickAction(),
new ExpectedCheckAction(false)],
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(["wow", {"string": "headingLevel", "args": [1]}])],
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(["Phone status bar"])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
// Moving to the absolute last item from an embedded document
// fails. Bug 972035.
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(
["such app", "wow", {"string": "headingLevel", "args": [1]}])],
// Move from an inner frame to the last element in the parent doc
[ContentMessages.simpleMoveLast,
new ExpectedCursorChange(
["slider", "0", {"string": "slider"}])],
[ContentMessages.clearCursor, "AccessFu:CursorCleared"],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Traversal Rule test document", "Phone status bar"])],
[ContentMessages.moveOrAdjustDown("FormElement"),
new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
[ContentMessages.moveOrAdjustDown("FormElement"),
new ExpectedCursorChange(["such app", "many option", {"string": "stateNotChecked"},
{"string": "checkbutton"}, {"string": "listStart"},
{"string": "list"}, {"string": "listItemsCount", "count": 1}])],
[ContentMessages.moveOrAdjustDown("FormElement"),
new ExpectedCursorChange(["much range", "5", {"string": "slider"}])],
// Calling AdjustOrMove should adjust the range.
[ContentMessages.moveOrAdjustDown("FormElement"),
new ExpectedValueChange("4")],
[ContentMessages.moveOrAdjustUp("FormElement"),
new ExpectedValueChange("5")],
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(["much range", {"string": "label"}])],
[ContentMessages.moveOrAdjustUp("FormElement"),
new ExpectedCursorChange(["many option", {"string": "stateNotChecked"},
{"string": "checkbutton"}, {"string": "listStart"},
{"string": "list"}, {"string": "listItemsCount", "count": 1}])],
[ContentMessages.moveOrAdjustUp("FormElement"),
new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
[ContentMessages.clearCursor, "AccessFu:CursorCleared"],
// Moving to the absolute first item from an embedded document
// fails. Bug 972035.
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Traversal Rule test document", "Phone status bar"])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["such app", "wow", {"string": "headingLevel", "args": [1]}])],
[ContentMessages.simpleMoveNext, new ExpectedCursorChange(
["many option", {"string": "stateNotChecked"},
{"string": "checkbutton"}, {"string": "listStart"},
{"string": "list"}, {"string": "listItemsCount", "count": 1}])],
[ContentMessages.simpleMoveFirst,
new ExpectedCursorChange(["Phone status bar"])],
// Reset cursors
[ContentMessages.clearCursor, "AccessFu:CursorCleared"],
// Current virtual cursor's position's name changes
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Traversal Rule test document", "Phone status bar"])],
[ContentMessages.focusSelector("button#fruit", false),
new ExpectedCursorChange(["apple", {"string": "pushbutton"}])],
[doc.defaultView.renameFruit, new ExpectedNameChange("banana")],
// Name and value changes inside a live-region (no cursor present)
[doc.defaultView.renameSlider,
new ExpectedNameChange("mover")],
[doc.defaultView.changeSliderValue,
new ExpectedValueChange("medium")],
// Blur button and reset cursor
[ContentMessages.focusSelector("button#fruit", true), null],
[ContentMessages.clearCursor, "AccessFu:CursorCleared"],
// Move cursor with focus in outside document
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Traversal Rule test document", "Phone status bar"])],
[ContentMessages.focusSelector("button#home", false),
new ExpectedCursorChange(["Home", {"string": "pushbutton"}])],
// Blur button and reset cursor
[ContentMessages.focusSelector("button#home", true), null],
[ContentMessages.clearCursor, "AccessFu:CursorCleared"],
// Set focus on element outside of embedded frame while
// cursor is in frame
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Traversal Rule test document", "Phone status bar"])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["such app", "wow", {"string": "headingLevel", "args": [1]}])],
[ContentMessages.focusSelector("button#home", false),
new ExpectedCursorChange(["Home", {"string": "pushbutton"}])],
// Blur button and reset cursor
[ContentMessages.focusSelector("button#home", true), null],
[ContentMessages.clearCursor, "AccessFu:CursorCleared"],
// XXX: Set focus on iframe itself.
// XXX: Set focus on element in iframe when cursor is outside of it.
// XXX: Set focus on element in iframe when cursor is in iframe.
// aria-hidden element that the virtual cursor is positioned on
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Traversal Rule test document", "Phone status bar"])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
[doc.defaultView.ariaHideBack,
new ExpectedCursorChange(
["such app", "wow", {"string": "headingLevel", "args": [1]}])],
// Changing aria-hidden attribute twice and making sure that the event
// is fired only once when the actual change happens.
[doc.defaultView.ariaHideBack],
[doc.defaultView.ariaShowBack],
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
[ContentMessages.clearCursor, "AccessFu:CursorCleared"],
// aria-hidden on the iframe that has the vc.
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Traversal Rule test document", "Phone status bar"])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["such app", "wow", {"string": "headingLevel", "args": [1]}])],
[doc.defaultView.ariaHideIframe,
new ExpectedCursorChange(["Home", {"string": "pushbutton"}])],
[doc.defaultView.ariaShowIframe],
[ContentMessages.clearCursor, "AccessFu:CursorCleared"],
// aria-hidden element and auto Move
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Traversal Rule test document", "Phone status bar"])],
[doc.defaultView.ariaHideBack],
[ContentMessages.focusSelector("button#back", false),
// Must not speak Back button as it is aria-hidden
new ExpectedCursorChange(
["such app", "wow", {"string": "headingLevel", "args": [1]}])],
[doc.defaultView.ariaShowBack],
[ContentMessages.focusSelector("button#back", true), null],
[ContentMessages.clearCursor, "AccessFu:CursorCleared"],
// Open dialog in outer doc, while cursor is also in outer doc
[ContentMessages.simpleMoveLast,
new ExpectedCursorChange(["Traversal Rule test document", "mover",
"medium", {"string": "slider"}])],
[doc.defaultView.showAlert,
new ExpectedCursorChange(["This is an alert!",
{"string": "headingLevel", "args": [1]},
{"string": "dialog"}])],
[doc.defaultView.hideAlert,
new ExpectedCursorChange(["Traversal Rule test document", "mover",
"medium", {"string": "slider"}])],
[ContentMessages.clearCursor, "AccessFu:CursorCleared"],
// Open dialog in outer doc, while cursor is in inner frame
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Traversal Rule test document", "Phone status bar"])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(
["such app", "wow", {"string": "headingLevel", "args": [1]}])],
[doc.defaultView.showAlert, new ExpectedCursorChange(["This is an alert!",
{"string": "headingLevel", "args": [1]},
{"string": "dialog"}])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Do you agree?"])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Yes", {"string": "pushbutton"}])],
[ContentMessages.activateCurrent(),
new ExpectedClickAction(),
new ExpectedCursorChange(
["such app", "wow", {"string": "headingLevel", "args": [1]}])],
[ContentMessages.clearCursor, "AccessFu:CursorCleared"],
// Open dialog, then focus on something when closing
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["Traversal Rule test document", "Phone status bar"])],
[doc.defaultView.showAlert,
new ExpectedCursorChange(["This is an alert!",
{"string": "headingLevel", "args": [1]}, {"string": "dialog"}])],
[function hideAlertAndFocusHomeButton() {
doc.defaultView.hideAlert();
doc.querySelector("button#home").focus();
}, new ExpectedCursorChange(["Traversal Rule test document",
"Home", {"string": "pushbutton"}])],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["banana", {"string": "pushbutton"}])]
[ContentMessages.simpleMoveNext, new ExpectedNoMove()]
]);
addA11yLoadEvent(function() {
contentTest.start(function() {
closeBrowserWindow();
SimpleTest.finish();
});
runner.finish();
closeBrowserWindow();
SimpleTest.finish();
}, doc.defaultView);
});
iframe.src = "data:text/html;charset=utf-8," + doc.defaultView.frameContents;
@ -335,7 +458,7 @@
<a target="_blank"
title="Add tests for OOP message handling and general integration"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=972047">Mozilla Bug 933808</a>
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1459677">Mozilla Bug 1459677</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">

Просмотреть файл

@ -1,311 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests AccessFu content integration</title>
<meta charset="utf-8" />
<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="chrome://mochikit/content/chrome-harness.js">
</script>
<script type="application/javascript" src="../common.js"></script>
<script type="application/javascript" src="../browser.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" src="../layout.js"></script>
<script type="application/javascript" src="jsatcommon.js"></script>
<script type="application/javascript">
function doTest() {
var doc = currentTabDocument();
var textTest = new AccessFuContentTest(
[
// Read-only text tests
[ContentMessages.simpleMoveFirst,
new ExpectedCursorChange(
["Text content test document", "These are my awards, Mother. " +
"From Army. The seal is for marksmanship, and the gorilla is " +
"for sand racing."])],
[ContentMessages.moveNextBy("word"),
new ExpectedCursorTextChange("These", 0, 5)],
[ContentMessages.moveNextBy("word"),
new ExpectedCursorTextChange("are", 6, 9)],
[ContentMessages.moveNextBy("word"),
new ExpectedCursorTextChange("my", 10, 12)],
[ContentMessages.moveNextBy("word"),
new ExpectedCursorTextChange("awards,", 13, 20)],
[ContentMessages.moveNextBy("word"),
new ExpectedCursorTextChange("Mother.", 21, 28)],
[ContentMessages.movePreviousBy("word"),
new ExpectedCursorTextChange("awards,", 13, 20)],
[ContentMessages.movePreviousBy("word"),
new ExpectedCursorTextChange("my", 10, 12)],
[ContentMessages.movePreviousBy("word"),
new ExpectedCursorTextChange("are", 6, 9)],
[ContentMessages.movePreviousBy("word"),
new ExpectedCursorTextChange("These", 0, 5)],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(["You're a good guy, mon frere. " +
"That means brother in French. " +
"I don't know how I know that. " +
"I took four years of Spanish."])],
// XXX: Word boundary should be past the apostraphe.
[ContentMessages.moveNextBy("word"),
new ExpectedCursorTextChange("You're", 0, 6,
{ todo: true /* Bug 980512 */})],
// Editable text tests.
[ContentMessages.focusSelector("textarea"),
new ExpectedAnnouncement("editing"),
new ExpectedEditState({
editing: true,
multiline: true,
atStart: true,
atEnd: false
}),
new ExpectedCursorChange(
["Please refrain from Mayoneggs during this salmonella scare.",
{string: "textarea"}]),
new ExpectedTextSelectionChanged(0, 0)
],
[ContentMessages.activateCurrent(10),
new ExpectedTextCaretChanged(0, 10),
new ExpectedEditState({ editing: true,
multiline: true,
atStart: false,
atEnd: false }),
new ExpectedTextSelectionChanged(10, 10)],
[ContentMessages.activateCurrent(20),
new ExpectedTextCaretChanged(10, 20),
new ExpectedTextSelectionChanged(20, 20)
],
[ContentMessages.moveCaretNextBy("word"),
new ExpectedTextCaretChanged(20, 29),
new ExpectedTextSelectionChanged(29, 29)
],
[ContentMessages.moveCaretNextBy("word"),
new ExpectedTextCaretChanged(29, 36),
new ExpectedTextSelectionChanged(36, 36)
],
[ContentMessages.moveCaretNextBy("character"),
new ExpectedTextCaretChanged(36, 37),
new ExpectedTextSelectionChanged(37, 37)
],
[ContentMessages.moveCaretNextBy("character"),
new ExpectedTextCaretChanged(37, 38),
new ExpectedTextSelectionChanged(38, 38)
],
[ContentMessages.moveCaretNextBy("paragraph"),
new ExpectedTextCaretChanged(38, 59),
new ExpectedTextSelectionChanged(59, 59)
],
[ContentMessages.moveCaretPreviousBy("word"),
new ExpectedTextCaretChanged(53, 59),
new ExpectedTextSelectionChanged(53, 53)
],
// bug xxx
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(
["So we don't get dessert?", {string: "label"}],
{ focused: "html"}),
new ExpectedAnnouncement("navigating"),
new ExpectedEditState({
editing: false,
multiline: false,
atStart: true,
atEnd: false })],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(
[{ string: "entry" }],
{ focused: "html"})],
[ContentMessages.activateCurrent(0),
new ExpectedClickAction(),
new ExpectedAnnouncement("editing"),
new ExpectedEditState({
editing: true,
multiline: false,
atStart: true,
atEnd: true
}, { focused: "input[type=text]" }),
new ExpectedTextSelectionChanged(0, 0)
],
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(
["So we don't get dessert?", {string: "label"}]),
new ExpectedAnnouncement("navigating"),
new ExpectedEditState({
editing: false,
multiline: false,
atStart: true,
atEnd: false
}, { focused: "html" })
],
[ContentMessages.simpleMoveNext,
new ExpectedCursorChange(
[{ string: "entry" }],
{ focused: "html"})],
[ContentMessages.activateCurrent(0),
new ExpectedClickAction(),
new ExpectedAnnouncement("editing"),
new ExpectedEditState({
editing: true,
multiline: false,
atStart: true,
atEnd: true
},
{ focused: "input[type=text]" }),
new ExpectedTextSelectionChanged(0, 0,
// Bug 1455749: Fix granularity control in text entries.
{ todo: true }
)],
[ContentMessages.simpleMovePrevious,
new ExpectedCursorChange(
[ "So we don't get dessert?", {string: "label"} ]),
new ExpectedAnnouncement("navigating"),
new ExpectedEditState({
editing: false,
multiline: false,
atStart: true,
atEnd: false
}, { focused: "html" })],
[ContentMessages.focusSelector("input"),
new ExpectedAnnouncement("editing"),
new ExpectedEditState({
editing: true,
multiline: false,
atStart: true,
atEnd: true
}),
new ExpectedCursorChange([{string: "entry"}]),
new ExpectedTextSelectionChanged(0, 0)
],
[function() {
SpecialPowers.pushPrefEnv({"set": [[KEYBOARD_ECHO_SETTING, 3]]}, typeKey("a")());
},
new ExpectedTextChanged("a"),
new ExpectedTextSelectionChanged(1, 1),
new ExpectedValueChange(),
],
[typeKey("b"),
new ExpectedTextChanged("b"),
new ExpectedValueChange(),
new ExpectedTextSelectionChanged(2, 2),
],
[typeKey("c"),
new ExpectedTextChanged("c"),
new ExpectedValueChange(),
new ExpectedTextSelectionChanged(3, 3),
],
[typeKey("d"),
new ExpectedTextChanged("d"),
new ExpectedValueChange(),
new ExpectedTextSelectionChanged(4, 4),
],
[typeKey(" "),
new ExpectedTextChanged(" abcd"),
new ExpectedValueChange(),
new ExpectedTextSelectionChanged(5, 5),
],
[typeKey("e"),
new ExpectedTextChanged("e"),
new ExpectedValueChange(),
new ExpectedTextSelectionChanged(6, 6),
],
[function() {
SpecialPowers.pushPrefEnv({"set": [[KEYBOARD_ECHO_SETTING, 2]]}, typeKey("a")());
},
new ExpectedTextChanged(""),
new ExpectedValueChange(),
new ExpectedTextSelectionChanged(7, 7),
],
[typeKey("d"),
new ExpectedTextChanged(""),
new ExpectedValueChange(),
new ExpectedTextSelectionChanged(8, 8),
],
[typeKey(" "),
new ExpectedTextChanged(" ead"),
new ExpectedValueChange(),
new ExpectedTextSelectionChanged(9, 9),
],
[function() {
SpecialPowers.pushPrefEnv({"set": [[KEYBOARD_ECHO_SETTING, 1]]}, typeKey("f")());
},
new ExpectedTextChanged("f"),
new ExpectedValueChange(),
new ExpectedTextSelectionChanged(10, 10),
],
[typeKey("g"),
new ExpectedTextChanged("g"),
new ExpectedValueChange(),
new ExpectedTextSelectionChanged(11, 11),
],
[typeKey(" "),
new ExpectedTextChanged(" "),
new ExpectedValueChange(),
new ExpectedTextSelectionChanged(12, 12),
],
[function() {
SpecialPowers.pushPrefEnv({"set": [[KEYBOARD_ECHO_SETTING, 0]]}, typeKey("f")());
},
new ExpectedTextChanged(""),
new ExpectedValueChange(),
new ExpectedTextSelectionChanged(13, 13),
],
[typeKey("g"),
new ExpectedTextChanged(""),
new ExpectedValueChange(),
new ExpectedTextSelectionChanged(14, 14),
],
[typeKey(" "),
new ExpectedTextChanged(""),
new ExpectedValueChange(),
new ExpectedTextSelectionChanged(15, 15),
],
]);
const KEYBOARD_ECHO_SETTING = "accessibility.accessfu.keyboard_echo";
function typeKey(key) {
let func = function() { synthesizeKey(key, {}, currentTabWindow()); };
func.toString = () => `typeKey('${key}')`;
return func;
}
addA11yLoadEvent(function() {
textTest.start(function() {
closeBrowserWindow();
SimpleTest.finish();
});
}, doc.defaultView);
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(
function() {
openBrowserWindow(
doTest,
getRootDirectory(window.location.href) + "doc_content_text.html");
});
</script>
</head>
<body id="body">
<a target="_blank"
title="Add tests for text editing and navigating"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=972047">Mozilla Bug 933808</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,129 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests AccessFu navigation in focused editable</title>
<meta charset="utf-8" />
<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="chrome://mochikit/content/chrome-harness.js">
</script>
<script type="application/javascript" src="../common.js"></script>
<script type="application/javascript" src="../browser.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" src="../layout.js"></script>
<script type="application/javascript" src="jsatcommon.js"></script>
<script type="application/javascript">
function checkMoveCaret(aMoveEvent, aSelectionEvent, aFrom, aTo) {
is(aMoveEvent.fromIndex, Math.min(aFrom, aTo), "Move to offset (fromIndex)");
is(aMoveEvent.toIndex, Math.max(aFrom, aTo), "Move to offset (toIndex)");
is(aSelectionEvent.fromIndex, aTo, "Caret offset (fromIndex)");
is(aSelectionEvent.toIndex, aTo, "Caret offset (toIndex)");
}
async function testEditableTextNavigation(doc, runner) {
// Editable text tests.
let evt;
evt = await runner.focusSelector("textarea",
AndroidEvents.ANNOUNCEMENT,
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED);
// XXX: Get rid of announcements, and send focus events instead
runner.eventTextMatches(evt[0], ["editing"]);
runner.eventTextMatches(evt[1],
["Text content test document",
"Please refrain from Mayoneggs during this salmonella scare.",
"text area"]);
is(evt[2].fromIndex, 0, "Correct fromIndex");
is(evt[2].toIndex, 0, "Correct toIndex");
evt = await runner.activateCurrent(10,
AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED);
checkMoveCaret(...evt, 0, 10);
evt = await runner.activateCurrent(20,
AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED);
checkMoveCaret(...evt, 10, 20);
evt = await runner.moveCaretNext(MovementGranularity.WORD,
AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED);
checkMoveCaret(...evt, 20, 29);
evt = await runner.moveCaretNext(MovementGranularity.WORD,
AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED);
checkMoveCaret(...evt, 29, 36);
evt = await runner.moveCaretNext(MovementGranularity.CHARACTER,
AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED);
checkMoveCaret(...evt, 36, 37);
evt = await runner.moveCaretNext(MovementGranularity.CHARACTER,
AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED);
checkMoveCaret(...evt, 37, 38);
evt = await runner.moveCaretNext(MovementGranularity.PARAGRAPH,
AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED);
checkMoveCaret(...evt, 38, 59);
evt = await runner.moveCaretPrevious(MovementGranularity.WORD,
AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED);
checkMoveCaret(...evt, 59, 53);
evt = await runner.blur(AndroidEvents.ANNOUNCEMENT);
runner.eventTextMatches(evt, ["navigating"]);
}
function doTest() {
var doc = currentTabDocument();
addA11yLoadEvent(async function() {
let runner = new AccessFuContentTestRunner();
await runner.start();
await testEditableTextNavigation(doc, runner);
runner.finish();
closeBrowserWindow();
SimpleTest.finish();
}, doc.defaultView);
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(
function() {
openBrowserWindow(
doTest,
getRootDirectory(window.location.href) + "doc_content_text.html");
});
</script>
</head>
<body id="body">
<a target="_blank"
title="Add tests for text editing and navigating"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1459677">Mozilla Bug 1459677</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,148 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests AccessFu text editing</title>
<meta charset="utf-8" />
<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="chrome://mochikit/content/chrome-harness.js">
</script>
<script type="application/javascript" src="../common.js"></script>
<script type="application/javascript" src="../browser.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" src="../layout.js"></script>
<script type="application/javascript" src="jsatcommon.js"></script>
<script type="application/javascript">
async function testTextEditing(doc, runner) {
function checkInsert(textChangeEvent, testSelEvent, text, insertIndex, addedCount) {
runner.eventTextMatches(textChangeEvent, text);
is(textChangeEvent.addedCount, addedCount);
is(textChangeEvent.fromIndex, insertIndex);
runner.eventTextMatches(testSelEvent, text);
is(testSelEvent.toIndex, insertIndex + addedCount);
is(testSelEvent.fromIndex, insertIndex + addedCount);
}
let evt;
evt = await runner.focusSelector("input",
AndroidEvents.ANNOUNCEMENT,
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED);
// XXX: Get rid of announcements, and send focus events instead
runner.eventTextMatches(evt[0], ["editing"]);
runner.eventTextMatches(evt[1], ["Text content test document", "entry"]);
is(evt[2].fromIndex, 0, "Caret at start (fromIndex)");
is(evt[2].toIndex, 0, "Caret at start (toIndex)");
evt = await runner.typeKey("B",
AndroidEvents.VIEW_TEXT_CHANGED,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED,
"todo.value-changed");
checkInsert(evt[0], evt[1], ["B"], 0, 1);
evt = await runner.typeKey("o",
AndroidEvents.VIEW_TEXT_CHANGED,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED,
"todo.value-changed");
checkInsert(evt[0], evt[1], ["Bo"], 1, 1);
evt = await runner.typeKey("b",
AndroidEvents.VIEW_TEXT_CHANGED,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED,
"todo.value-changed");
checkInsert(evt[0], evt[1], ["Bob"], 2, 1);
evt = await runner.typeKey(" ",
AndroidEvents.VIEW_TEXT_CHANGED,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED,
"todo.value-changed");
checkInsert(evt[0], evt[1], ["Bob "], 3, 1);
evt = await runner.typeKey("L",
AndroidEvents.VIEW_TEXT_CHANGED,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED,
"todo.value-changed");
checkInsert(evt[0], evt[1], ["Bob L"], 4, 1);
evt = await runner.typeKey("o",
AndroidEvents.VIEW_TEXT_CHANGED,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED,
"todo.value-changed");
checkInsert(evt[0], evt[1], ["Bob Lo"], 5, 1);
evt = await runner.typeKey("b",
AndroidEvents.VIEW_TEXT_CHANGED,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED,
"todo.value-changed");
checkInsert(evt[0], evt[1], ["Bob Lob"], 6, 1);
evt = await runner.typeKey("l",
AndroidEvents.VIEW_TEXT_CHANGED,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED,
"todo.value-changed");
checkInsert(evt[0], evt[1], ["Bob Lobl"], 7, 1);
evt = await runner.typeKey("a",
AndroidEvents.VIEW_TEXT_CHANGED,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED,
"todo.value-changed");
checkInsert(evt[0], evt[1], ["Bob Lobla"], 8, 1);
evt = await runner.typeKey("w",
AndroidEvents.VIEW_TEXT_CHANGED,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED,
"todo.value-changed");
checkInsert(evt[0], evt[1], ["Bob Loblaw"], 9, 1);
evt = await runner.blur(AndroidEvents.ANNOUNCEMENT);
runner.eventTextMatches(evt, ["navigating"]);
}
function doTest() {
var doc = currentTabDocument();
addA11yLoadEvent(async function() {
let runner = new AccessFuContentTestRunner();
await runner.start();
await testTextEditing(doc, runner);
runner.finish();
closeBrowserWindow();
SimpleTest.finish();
}, doc.defaultView);
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(
function() {
openBrowserWindow(
doTest,
getRootDirectory(window.location.href) + "doc_content_text.html");
});
</script>
</head>
<body id="body">
<a target="_blank"
title="Add tests for text editing and navigating"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1459677">Mozilla Bug 1459677</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,134 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests AccessFu text navigation</title>
<meta charset="utf-8" />
<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="chrome://mochikit/content/chrome-harness.js">
</script>
<script type="application/javascript" src="../common.js"></script>
<script type="application/javascript" src="../browser.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" src="../layout.js"></script>
<script type="application/javascript" src="jsatcommon.js"></script>
<script type="application/javascript">
function checkFromToIndex(aEvent, aFrom, aTo) {
is(aEvent.fromIndex, aFrom, "Correct fromIndex");
is(aEvent.toIndex, aTo, "Correct toIndex");
}
async function testTextNavigation(doc, runner) {
let evt;
// Read-only text tests
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["Text content test document",
"These are my awards, Mother. From Army. " +
"The seal is for marksmanship, and the gorilla is for sand racing."]);
// "These"
evt = await runner.moveNextByGranularity(MovementGranularity.WORD,
AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
checkFromToIndex(evt, 0, 5);
// "are"
evt = await runner.moveNextByGranularity(MovementGranularity.WORD,
AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
checkFromToIndex(evt, 6, 9);
// "my"
evt = await runner.moveNextByGranularity(MovementGranularity.WORD,
AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
checkFromToIndex(evt, 10, 12);
// "awards,"
evt = await runner.moveNextByGranularity(MovementGranularity.WORD,
AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
checkFromToIndex(evt, 13, 20);
// "Mother."
evt = await runner.moveNextByGranularity(MovementGranularity.WORD,
AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
checkFromToIndex(evt, 21, 28);
// "awards,"
evt = await runner.movePreviousByGranularity(MovementGranularity.WORD,
AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
checkFromToIndex(evt, 13, 20);
// "my"
evt = await runner.movePreviousByGranularity(MovementGranularity.WORD,
AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
checkFromToIndex(evt, 10, 12);
// "are"
evt = await runner.movePreviousByGranularity(MovementGranularity.WORD,
AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
checkFromToIndex(evt, 6, 9);
// "These"
evt = await runner.movePreviousByGranularity(MovementGranularity.WORD,
AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
checkFromToIndex(evt, 0, 5);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["You're a good guy, mon frere. " +
"That means brother in French. I don't know how I know that. " +
"I took four years of Spanish."]);
// "You're"
evt = await runner.moveNextByGranularity(MovementGranularity.WORD,
AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
is(evt.fromIndex, 0, "Correct fromIndex");
todo_is(evt.toIndex, 6, "Word boundary should be past the apostraphe");
}
function doTest() {
var doc = currentTabDocument();
addA11yLoadEvent(async function() {
let runner = new AccessFuContentTestRunner();
await runner.start();
await testTextNavigation(doc, runner);
runner.finish();
closeBrowserWindow();
SimpleTest.finish();
}, doc.defaultView);
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(
function() {
openBrowserWindow(
doTest,
getRootDirectory(window.location.href) + "doc_content_text.html");
});
</script>
</head>
<body id="body">
<a target="_blank"
title="Add tests for text editing and navigating"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1459677">Mozilla Bug 1459677</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,118 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests AccessFu text entry focus and a11y focus</title>
<meta charset="utf-8" />
<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="chrome://mochikit/content/chrome-harness.js">
</script>
<script type="application/javascript" src="../common.js"></script>
<script type="application/javascript" src="../browser.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" src="../layout.js"></script>
<script type="application/javascript" src="jsatcommon.js"></script>
<script type="application/javascript">
async function testTextNavigationFocus(doc, runner) {
let evt;
evt = await runner.focusSelector("textarea",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED,
AndroidEvents.ANNOUNCEMENT);
// XXX: Get rid of announcements, and send focus events instead
runner.eventTextMatches(evt[0],
["Text content test document",
"Please refrain from Mayoneggs during this salmonella scare.",
"text area"]);
runner.eventTextMatches(evt[1], ["editing"]);
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED,
AndroidEvents.ANNOUNCEMENT);
runner.eventTextMatches(evt[0], ["So we don't get dessert?", "label"]);
runner.eventTextMatches(evt[1], ["navigating"]);
runner.isFocused("html");
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["entry"]);
runner.isFocused("html");
evt = await runner.activateCurrent(0,
AndroidEvents.VIEW_CLICKED,
AndroidEvents.ANNOUNCEMENT,
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED);
runner.eventTextMatches(evt[1], ["editing"]);
is(evt[2].fromIndex, 0, "Cursor at start");
runner.isFocused("input[type=text]");
evt = await runner.movePrevious("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED,
AndroidEvents.ANNOUNCEMENT);
runner.eventTextMatches(evt[0], ["So we don't get dessert?", "label"]);
runner.eventTextMatches(evt[1], ["navigating"]);
runner.isFocused("html");
evt = await runner.moveNext("Simple",
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
runner.eventTextMatches(evt, ["entry"]);
runner.isFocused("html");
// XXX: TEXT_SELECTION_CHANGED should be fired here
evt = await runner.activateCurrent(0,
AndroidEvents.VIEW_CLICKED,
AndroidEvents.ANNOUNCEMENT);
runner.eventTextMatches(evt[1], ["editing"]);
runner.isFocused("input[type=text]");
evt = await runner.blur(AndroidEvents.ANNOUNCEMENT);
runner.eventTextMatches(evt, ["navigating"]);
}
function doTest() {
var doc = currentTabDocument();
addA11yLoadEvent(async function() {
let runner = new AccessFuContentTestRunner();
await runner.start();
await testTextNavigationFocus(doc, runner);
runner.finish();
closeBrowserWindow();
SimpleTest.finish();
}, doc.defaultView);
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(
function() {
openBrowserWindow(
doTest,
getRootDirectory(window.location.href) + "doc_content_text.html");
});
</script>
</head>
<body id="body">
<a target="_blank"
title="Add tests for text editing and navigating"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1459677">Mozilla Bug 1459677</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
</body>
</html>