Bug 980521 - Introduce content text tests. r=yzen

This commit is contained in:
Eitan Isaacson 2014-03-19 00:38:25 -07:00
parent 054e401662
commit b6f7eb8725
9 changed files with 632 additions and 166 deletions

View File

@ -699,12 +699,24 @@ var Output = {
}
},
get androidBridge() {
delete this.androidBridge;
if (Utils.MozBuildApp === 'mobile/android') {
this.androidBridge = Cc['@mozilla.org/android/bridge;1'].getService(
Ci.nsIAndroidBridge);
} else {
this.androidBridge = null;
}
return this.androidBridge;
},
Android: function Android(aDetails, aBrowser) {
const ANDROID_VIEW_TEXT_CHANGED = 0x10;
const ANDROID_VIEW_TEXT_SELECTION_CHANGED = 0x2000;
if (!this._bridge)
this._bridge = Cc['@mozilla.org/android/bridge;1'].getService(Ci.nsIAndroidBridge);
if (!this.androidBridge) {
return;
}
for each (let androidEvent in aDetails) {
androidEvent.type = 'Accessibility:Event';
@ -722,7 +734,7 @@ var Output = {
androidEvent.brailleOutput = this.brailleState.init(androidEvent.brailleOutput);
break;
}
this._bridge.handleGeckoMessage(JSON.stringify(androidEvent));
this.androidBridge.handleGeckoMessage(JSON.stringify(androidEvent));
}
},

View File

@ -625,7 +625,8 @@ this.UtteranceGenerator = {
// This is because we expose the checked information on the node itself.
// XXX: this means the checked state is always appended to the end, regardless
// of the utterance ordering preference.
if (Utils.AndroidSdkVersion < 16 && aState.contains(States.CHECKABLE)) {
if ((Utils.AndroidSdkVersion < 16 || Utils.MozBuildApp === 'browser') &&
aState.contains(States.CHECKABLE)) {
let statetr = aState.contains(States.CHECKED) ?
'stateChecked' : 'stateNotChecked';
stateUtterances.push(Utils.stringBundle.GetStringFromName(statetr));

View File

@ -569,15 +569,13 @@ BraillePresenter.prototype = {
this.Presentation = {
get presenters() {
delete this.presenters;
this.presenters = [new VisualPresenter()];
if (Utils.MozBuildApp == 'mobile/android') {
this.presenters.push(new AndroidPresenter());
} else {
this.presenters.push(new SpeechPresenter());
this.presenters.push(new HapticPresenter());
}
let presenterMap = {
'mobile/android': [VisualPresenter, AndroidPresenter],
'b2g': [VisualPresenter, SpeechPresenter, HapticPresenter],
'browser': [VisualPresenter, SpeechPresenter, HapticPresenter,
AndroidPresenter]
};
this.presenters = [new P() for (P of presenterMap[Utils.MozBuildApp])];
return this.presenters;
},

View File

@ -98,7 +98,7 @@ this.Utils = {
this._AndroidSdkVersion = Services.sysinfo.getPropertyAsInt32('version');
} else {
// Most useful in desktop debugging.
this._AndroidSdkVersion = 15;
this._AndroidSdkVersion = 16;
}
}
return this._AndroidSdkVersion;

View File

@ -6,9 +6,11 @@ support-files =
output.js
doc_traversal.html
doc_content_integration.html
doc_content_text.html
[test_alive.html]
[test_content_integration.html]
[test_content_text.html]
[test_explicit_names.html]
[test_landmarks.html]
[test_live_regions.html]

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<title>Text content test document</title>
<meta charset="utf-8" />
</head>
<body>
<p>These are my awards, Mother. From Army.
The seal is for marksmanship, and the gorilla is for sand racing.</p>
<p>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.</p>
<textarea>Please refrain from Mayoneggs during this salmonella scare.</textarea>
</body>
</html>

View File

@ -172,6 +172,11 @@ AccessFuContentTest.prototype = {
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]);
@ -206,7 +211,8 @@ AccessFuContentTest.prototype = {
aMessageManager.addMessageListener('AccessFu:Present', this);
aMessageManager.addMessageListener('AccessFu:Ready', function () {
aMessageManager.addMessageListener('AccessFu:ContentStarted', aCallback);
aMessageManager.sendAsyncMessage('AccessFu:Start', { buildApp: 'browser' });
aMessageManager.sendAsyncMessage('AccessFu:Start',
{ buildApp: 'browser', androidSdkVersion: Utils.AndroidSdkVersion});
});
aMessageManager.loadFrameScript(
@ -242,21 +248,46 @@ AccessFuContentTest.prototype = {
return;
}
var expected = this.currentPair[1];
if (expected) {
if (expected.speak !== undefined) {
var speech = this.extractUtterance(aMessage.json);
if (!speech) {
// Probably a visual highlight adjustment after a scroll.
return;
}
var checkFunc = SimpleTest[expected.speak_checkFunc] || is;
checkFunc(speech, expected.speak);
var expected = this.currentPair[1] || {};
var speech = this.extractUtterance(aMessage.json);
var android = this.extractAndroid(aMessage.json, expected.android);
if ((speech && expected.speak) || (android && expected.android)) {
if (expected.speak) {
(SimpleTest[expected.speak_checkFunc] || is)(speech, expected.speak);
}
if (expected.android) {
var checkFunc = SimpleTest[expected.android_checkFunc] || ok;
checkFunc.apply(SimpleTest,
this.lazyCompare(android, expected.android));
}
this.pump();
}
this.pump();
},
lazyCompare: function lazyCompare(aReceived, aExpected) {
var matches = true;
var delta = [];
for (var attr in aExpected) {
var expected = aExpected[attr];
var received = aReceived !== undefined ? aReceived[attr] : null;
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 ' + expected + ' got ' + received + ' ]');
matches = false;
}
}
}
return [matches, delta.join(' ')];
},
extractUtterance: function(aData) {
@ -270,6 +301,156 @@ AccessFuContentTest.prototype = {
}
}
return null;
},
extractAndroid: function(aData, aExpectedEvents) {
for (var output of aData) {
if (output && output.type === 'Android') {
for (var i in output.details) {
// Only extract if event types match expected event types.
var exp = aExpectedEvents ? aExpectedEvents[i] : null;
if (!exp || (output.details[i].eventType !== exp.eventType)) {
return null;
}
}
return output.details;
}
}
return null;
}
};
// Common content messages
var ContentMessages = {
simpleMoveFirst: {
name: 'AccessFu:MoveCursor',
json: {
action: 'moveFirst',
rule: 'Simple',
inputType: 'gesture',
origin: 'top'
}
},
simpleMoveLast: {
name: 'AccessFu:MoveCursor',
json: {
action: 'moveLast',
rule: 'Simple',
inputType: 'gesture',
origin: 'top'
}
},
simpleMoveNext: {
name: 'AccessFu:MoveCursor',
json: {
action: 'moveNext',
rule: 'Simple',
inputType: 'gesture',
origin: 'top'
}
},
simpleMovePrevious: {
name: 'AccessFu:MoveCursor',
json: {
action: 'movePrevious',
rule: 'Simple',
inputType: 'gesture',
origin: 'top'
}
},
clearCursor: {
name: 'AccessFu:ClearCursor',
json: {
origin: 'top'
}
},
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
}
};
var AndroidEvent = {
VIEW_CLICKED: 0x01,
VIEW_LONG_CLICKED: 0x02,
VIEW_SELECTED: 0x04,
VIEW_FOCUSED: 0x08,
VIEW_TEXT_CHANGED: 0x10,
WINDOW_STATE_CHANGED: 0x20,
VIEW_HOVER_ENTER: 0x80,
VIEW_HOVER_EXIT: 0x100,
VIEW_SCROLLED: 0x1000,
VIEW_TEXT_SELECTION_CHANGED: 0x2000,
ANNOUNCEMENT: 0x4000,
VIEW_ACCESSIBILITY_FOCUSED: 0x8000,
VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY: 0x20000
};

View File

@ -26,163 +26,162 @@
var iframe = doc.createElement("iframe");
iframe.mozbrowser = true;
iframe.addEventListener("mozbrowserloadend", function () {
var simpleMoveNext = { name: 'AccessFu:MoveCursor',
json: { action: 'moveNext',
rule: 'Simple',
inputType: 'gesture',
origin: 'top' }
};
var contentTest = new AccessFuContentTest(
[
// Simple traversal forward
[ContentMessages.simpleMoveNext, {
speak: 'Phone status bar Traversal Rule test document'
}],
[ContentMessages.simpleMoveNext, {
speak: 'wow heading level 1 such app'
}],
[ContentMessages.simpleMoveNext, {
speak: 'many option not checked check button'
}],
// check checkbox
[ContentMessages.activateCurrent(), {
speak: 'checked'
}],
[null, {
speak: 'checked',
speak_checkFunc: 'todo_isnot'
}],
// uncheck checkbox
[ContentMessages.simpleMoveNext, {
speak: 'Home button'
}],
var simpleMovePrevious = { name: 'AccessFu:MoveCursor',
json: { action: 'movePrevious',
rule: 'Simple',
inputType: 'gesture',
origin: 'top' }
};
// Simple traversal backward
[ContentMessages.simpleMovePrevious, {
speak: 'many option checked check button such app'
}],
[ContentMessages.activateCurrent(), {
speak: 'unchecked'
}],
[null, {
speak: 'unchecked',
speak_checkFunc: 'todo_isnot'
}],
[ContentMessages.simpleMovePrevious, {
speak: 'wow heading level 1'
}],
[ContentMessages.simpleMovePrevious, {
speak: 'Phone status bar'
}],
var activateCurrent = { name: 'AccessFu:Activate',
json: { origin: 'top' } };
// Moving to the absolute last item from an embedded document
// fails. Bug 972035.
[ContentMessages.simpleMoveNext, {
speak: 'wow heading level 1 such app'
}],
// Move from an inner frame to the last element in the parent doc
[ContentMessages.simpleMoveLast, {
speak: 'Home button',
speak_checkFunc: 'todo_is'
}],
var simpleMoveLast = { name: 'AccessFu:MoveCursor',
json: { action: 'moveLast',
rule: 'Simple',
inputType: 'gesture',
origin: 'top' }
};
[ContentMessages.clearCursor, null], // Reset cursors
var simpleMoveFirst = { name: 'AccessFu:MoveCursor',
json: { action: 'moveFirst',
rule: 'Simple',
inputType: 'gesture',
origin: 'top' }
};
// Moving to the absolute first item from an embedded document
// fails. Bug 972035.
[ContentMessages.simpleMoveNext, {
speak: 'Phone status bar Traversal Rule test document'
}],
[ContentMessages.simpleMoveNext, {
speak: 'wow heading level 1 such app'
}],
[ContentMessages.simpleMoveNext, {
speak: 'many option not checked check button'
}],
[ContentMessages.simpleMoveFirst, {
speak: 'Phone status bar',
speak_checkFunc: 'todo_is'
}],
var clearCursor = { name: 'AccessFu:ClearCursor',
json: { origin: 'top' }
};
// Reset cursors
[ContentMessages.clearCursor, null],
function focusFunc(aSelector, aBlur) {
return function (mm) {
mm.sendAsyncMessage(
'AccessFuTest:Focus', { selector: aSelector, blur: aBlur });
};
}
// Move cursor with focus in outside document
[ContentMessages.simpleMoveNext, {
speak: 'Phone status bar Traversal Rule test document'
}],
[ContentMessages.focusSelector('button#home', false), {
speak: 'Home button'
}],
var contentTest = new AccessFuContentTest(
[
// Simple traversal forward
[simpleMoveNext,
{ speak: 'Phone status bar Traversal Rule test document' }],
[simpleMoveNext,
{ speak: 'wow heading level 1 such app' }],
[simpleMoveNext,
{ speak: 'many option not checked check button' }],
// check checkbox
[activateCurrent,
{ speak: 'checked' }],
[null,
{ speak: 'checked', speak_checkFunc: 'todo_isnot' }],
// uncheck checkbox
[simpleMoveNext,
{ speak: 'Home button' }],
// Blur button and reset cursor
[ContentMessages.focusSelector('button#home', true), null],
[ContentMessages.clearCursor, null],
// Simple traversal backward
[simpleMovePrevious,
{ speak: 'many option checked check button such app' }],
[activateCurrent,
{ speak: 'unchecked' }],
[null,
{ speak: 'unchecked', speak_checkFunc: 'todo_isnot' }],
[simpleMovePrevious,
{ speak: 'wow heading level 1' }],
[simpleMovePrevious,
{ speak: 'Phone status bar' }],
// Set focus on element outside of embedded frame while
// cursor is in frame
[ContentMessages.simpleMoveNext, {
speak: 'Phone status bar Traversal Rule test document'
}],
[ContentMessages.simpleMoveNext, {
speak: 'wow heading level 1 such app'
}],
[ContentMessages.focusSelector('button#home', false), {
speak: 'Home button'
}]
// Moving to the absolute last item from an embedded document fails.
// Bug 972035.
[simpleMoveNext,
{ speak: 'wow heading level 1 such app' }],
// Move from an inner frame to the last element in the parent doc
[simpleMoveLast,
{ speak: 'Home button', speak_checkFunc: 'todo_is' }],
// Blur button and reset cursor
[ContentMessages.focusSelector('button#home', true), null],
[ContentMessages.clearCursor, null],
[clearCursor, null], // Reset cursors
// 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.
// Moving to the absolute first item from an embedded document fails.
// Bug 972035.
[simpleMoveNext,
{ speak: 'Phone status bar Traversal Rule test document' }],
[simpleMoveNext,
{ speak: 'wow heading level 1 such app' }],
[simpleMoveNext,
{ speak: 'many option not checked check button' }],
[simpleMoveFirst,
{ speak: 'Phone status bar', speak_checkFunc: 'todo_is' }],
// Open dialog in outer doc, while cursor is also in outer doc
[ContentMessages.simpleMoveNext, {
speak: 'Phone status bar Traversal Rule test document'
}],
[doc.defaultView.showAlert, {
speak: 'This is an alert! heading level 1 dialog'
}],
// Reset cursors
[clearCursor, null],
[function() {
doc.defaultView.hideAlert()
}, {
speak: 'wow heading level 1 such app'
}],
// Move cursor with focus in outside document
[simpleMoveNext,
{ speak: 'Phone status bar Traversal Rule test document' }],
[ focusFunc('button#home', false), { speak: 'Home button' }],
[ContentMessages.clearCursor, null],
// Blur button and reset cursor
[focusFunc('button#home', true), null],
[clearCursor, null],
// Open dialog in outer doc, while cursor is in inner frame
[ContentMessages.simpleMoveNext, {
speak: 'Phone status bar Traversal Rule test document'
}],
[ContentMessages.simpleMoveNext, {
speak: 'wow heading level 1 such app'
}],
[doc.defaultView.showAlert, {
speak: 'This is an alert! heading level 1 dialog'
}],
// Set focus on element outside of embedded frame while cursor is in frame
[simpleMoveNext,
{ speak: 'Phone status bar Traversal Rule test document' }],
[simpleMoveNext,
{ speak: 'wow heading level 1 such app' }],
[focusFunc('button#home', false), { speak: 'Home button' }]
// XXX: Place cursor back where it was.
[doc.defaultView.hideAlert, {
speak: 'many option not checked check button such app'
}],
// Blur button and reset cursor
[focusFunc('button#home', true), null],
[clearCursor, null],
[ContentMessages.clearCursor, null],
// 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.
// Open dialog, then focus on something when closing
[ContentMessages.simpleMoveNext, {
speak: 'Phone status bar Traversal Rule test document'
}],
[doc.defaultView.showAlert, {
speak: 'This is an alert! heading level 1 dialog'
}],
// Open dialog in outer doc, while cursor is also in outer doc
[simpleMoveNext,
{ speak: 'Phone status bar Traversal Rule test document' }],
[doc.defaultView.showAlert,
{ speak: 'This is an alert! heading level 1 dialog' }],
[function () { doc.defaultView.hideAlert() },
{ speak: 'wow heading level 1 such app' }],
[clearCursor, null],
// Open dialog in outer doc, while cursor is in inner frame
[simpleMoveNext,
{ speak: 'Phone status bar Traversal Rule test document' }],
[simpleMoveNext,
{ speak: 'wow heading level 1 such app' }],
[doc.defaultView.showAlert,
{ speak: 'This is an alert! heading level 1 dialog' }],
// XXX: Place cursor back where it was.
[doc.defaultView.hideAlert,
{ speak: 'many option not checked check button such app' }],
[clearCursor, null],
// Open dialog, then focus on something when closing
[simpleMoveNext,
{ speak: 'Phone status bar Traversal Rule test document' }],
[doc.defaultView.showAlert,
{ speak: 'This is an alert! heading level 1 dialog' }],
[function () {
doc.defaultView.hideAlert();
doc.querySelector('button#home').focus();
},
{ speak: 'Home button Traversal Rule test document' }]
]);
[function() {
doc.defaultView.hideAlert();
doc.querySelector('button#home').focus();
}, {
speak: 'Home button Traversal Rule test document'
}]
]);
contentTest.start(function () {
closeBrowserWindow();

View File

@ -0,0 +1,259 @@
<!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/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, {
speak: 'These are my awards, Mother. From Army. ' +
'The seal is for marksmanship, and the gorilla is ' +
'for sand racing. Text content test document'
}],
[ContentMessages.moveNextBy('word'), {
speak: 'These',
speak_checkFunc: 'todo_is', // Bug 980509
android: [{
eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: 0,
toIndex: 5
}]
}],
[ContentMessages.moveNextBy('word'), {
speak: 'are',
speak_checkFunc: 'todo_is', // Bug 980509
android: [{
eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: 6,
toIndex: 9
}]
}],
[ContentMessages.moveNextBy('word'), {
speak: 'my',
speak_checkFunc: 'todo_is', // Bug 980509
android: [{
eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: 10,
toIndex: 12
}]
}],
[ContentMessages.moveNextBy('word'), {
speak: 'awards,',
speak_checkFunc: 'todo_is', // Bug 980509
android: [{
eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: 13,
toIndex: 20
}]
}],
[ContentMessages.moveNextBy('word'), {
speak: 'Mother.',
speak_checkFunc: 'todo_is', // Bug 980509
android: [{
eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: 21,
toIndex: 28
}]
}],
[ContentMessages.movePreviousBy('word'), {
speak: 'awards,',
speak_checkFunc: 'todo_is', // Bug 980509
android: [{
eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: 13,
toIndex: 20
}]
}],
[ContentMessages.movePreviousBy('word'), {
speak: 'my',
speak_checkFunc: 'todo_is', // Bug 980509
android: [{
eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: 10,
toIndex: 12
}]
}],
[ContentMessages.movePreviousBy('word'), {
speak: 'are',
speak_checkFunc: 'todo_is', // Bug 980509
android: [{
eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: 6,
toIndex: 9
}]
}],
[ContentMessages.movePreviousBy('word'), {
speak: 'These',
speak_checkFunc: 'todo_is', // Bug 980509
android: [{
eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: 0,
toIndex: 5
}]
}],
// XXX: Bug 980510: doing next after text traversal should
// bring us to the next paragraph.
[ContentMessages.simpleMoveNext, {
speak: '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.',
speak_checkFunc: 'todo_is' // Bug 980510
}],
// XXX: extra move op here because of bug 980510.
[ContentMessages.simpleMoveNext, {
speak: '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'), {
speak: 'You\'re',
speak_checkFunc: 'todo_is', // Bug 980509
android: [{
eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: 0,
toIndex: 6
}],
android_checkFunc: 'todo' // Bug 980512
}],
// Editable text tests.
[ContentMessages.focusSelector('textarea'), {
speak: 'Please refrain from Mayoneggs during this ' +
'salmonella scare. text area'
}],
[null, { // When we first focus, caret is at 0.
android: [{
eventType: AndroidEvent.VIEW_TEXT_SELECTION_CHANGED,
brailleOutput: {
selectionStart: 0,
selectionEnd: 0
}
}]
}
],
[ContentMessages.activateCurrent(10), {
android: [{
eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: 0,
toIndex: 10
}]
}],
[null, {
android: [{
eventType: AndroidEvent.VIEW_TEXT_SELECTION_CHANGED,
brailleOutput: {
selectionStart: 10,
selectionEnd: 10
}
}]
}],
[ContentMessages.activateCurrent(20), {
android: [{
eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: 10,
toIndex: 20
}]
}],
[null, {
android: [{
eventType: AndroidEvent.VIEW_TEXT_SELECTION_CHANGED,
brailleOutput: {
selectionStart: 20,
selectionEnd: 20
}
}]
}],
[ContentMessages.moveCaretNextBy('word'), {
android: [{
eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: 20,
toIndex: 29
}]
}],
[ContentMessages.moveCaretNextBy('word'), {
android: [{
eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: 29,
toIndex: 36
}]
}],
[ContentMessages.moveCaretNextBy('character'), {
android: [{
eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: 36,
toIndex: 37
}]
}],
[ContentMessages.moveCaretNextBy('character'), {
android: [{
eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: 37,
toIndex: 38
}]
}],
[ContentMessages.moveCaretNextBy('paragraph'), {
android: [{
eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: 38,
toIndex: 59
}]
}],
[ContentMessages.moveCaretPreviousBy('word'), {
android: [{
eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
fromIndex: 53,
toIndex: 59
}]
}]
]);
textTest.start(function () {
closeBrowserWindow();
SimpleTest.finish();
});
}
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>