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) { Android: function Android(aDetails, aBrowser) {
const ANDROID_VIEW_TEXT_CHANGED = 0x10; const ANDROID_VIEW_TEXT_CHANGED = 0x10;
const ANDROID_VIEW_TEXT_SELECTION_CHANGED = 0x2000; const ANDROID_VIEW_TEXT_SELECTION_CHANGED = 0x2000;
if (!this._bridge) if (!this.androidBridge) {
this._bridge = Cc['@mozilla.org/android/bridge;1'].getService(Ci.nsIAndroidBridge); return;
}
for each (let androidEvent in aDetails) { for each (let androidEvent in aDetails) {
androidEvent.type = 'Accessibility:Event'; androidEvent.type = 'Accessibility:Event';
@ -722,7 +734,7 @@ var Output = {
androidEvent.brailleOutput = this.brailleState.init(androidEvent.brailleOutput); androidEvent.brailleOutput = this.brailleState.init(androidEvent.brailleOutput);
break; 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. // 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 // XXX: this means the checked state is always appended to the end, regardless
// of the utterance ordering preference. // 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) ? let statetr = aState.contains(States.CHECKED) ?
'stateChecked' : 'stateNotChecked'; 'stateChecked' : 'stateNotChecked';
stateUtterances.push(Utils.stringBundle.GetStringFromName(statetr)); stateUtterances.push(Utils.stringBundle.GetStringFromName(statetr));

View File

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

View File

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

View File

@ -6,9 +6,11 @@ support-files =
output.js output.js
doc_traversal.html doc_traversal.html
doc_content_integration.html doc_content_integration.html
doc_content_text.html
[test_alive.html] [test_alive.html]
[test_content_integration.html] [test_content_integration.html]
[test_content_text.html]
[test_explicit_names.html] [test_explicit_names.html]
[test_landmarks.html] [test_landmarks.html]
[test_live_regions.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 () { this.setupMessageManager(this.mms[0], function () {
// Get child message managers and set them up // Get child message managers and set them up
var frames = currentTabDocument().querySelectorAll('iframe'); var frames = currentTabDocument().querySelectorAll('iframe');
if (frames.length === 0) {
self.pump();
return;
}
var toSetup = 0; var toSetup = 0;
for (var i = 0; i < frames.length; i++ ) { for (var i = 0; i < frames.length; i++ ) {
var mm = Utils.getMessageManager(frames[i]); var mm = Utils.getMessageManager(frames[i]);
@ -206,7 +211,8 @@ AccessFuContentTest.prototype = {
aMessageManager.addMessageListener('AccessFu:Present', this); aMessageManager.addMessageListener('AccessFu:Present', this);
aMessageManager.addMessageListener('AccessFu:Ready', function () { aMessageManager.addMessageListener('AccessFu:Ready', function () {
aMessageManager.addMessageListener('AccessFu:ContentStarted', aCallback); aMessageManager.addMessageListener('AccessFu:ContentStarted', aCallback);
aMessageManager.sendAsyncMessage('AccessFu:Start', { buildApp: 'browser' }); aMessageManager.sendAsyncMessage('AccessFu:Start',
{ buildApp: 'browser', androidSdkVersion: Utils.AndroidSdkVersion});
}); });
aMessageManager.loadFrameScript( aMessageManager.loadFrameScript(
@ -242,21 +248,46 @@ AccessFuContentTest.prototype = {
return; return;
} }
var expected = this.currentPair[1]; var expected = this.currentPair[1] || {};
var speech = this.extractUtterance(aMessage.json);
if (expected) { var android = this.extractAndroid(aMessage.json, expected.android);
if (expected.speak !== undefined) { if ((speech && expected.speak) || (android && expected.android)) {
var speech = this.extractUtterance(aMessage.json); if (expected.speak) {
if (!speech) { (SimpleTest[expected.speak_checkFunc] || is)(speech, expected.speak);
// Probably a visual highlight adjustment after a scroll.
return;
}
var checkFunc = SimpleTest[expected.speak_checkFunc] || is;
checkFunc(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) { 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; 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"); var iframe = doc.createElement("iframe");
iframe.mozbrowser = true; iframe.mozbrowser = true;
iframe.addEventListener("mozbrowserloadend", function () { iframe.addEventListener("mozbrowserloadend", function () {
var simpleMoveNext = { name: 'AccessFu:MoveCursor', var contentTest = new AccessFuContentTest(
json: { action: 'moveNext', [
rule: 'Simple', // Simple traversal forward
inputType: 'gesture', [ContentMessages.simpleMoveNext, {
origin: 'top' } 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', // Simple traversal backward
json: { action: 'movePrevious', [ContentMessages.simpleMovePrevious, {
rule: 'Simple', speak: 'many option checked check button such app'
inputType: 'gesture', }],
origin: 'top' } [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', // Moving to the absolute last item from an embedded document
json: { origin: 'top' } }; // 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', [ContentMessages.clearCursor, null], // Reset cursors
json: { action: 'moveLast',
rule: 'Simple',
inputType: 'gesture',
origin: 'top' }
};
var simpleMoveFirst = { name: 'AccessFu:MoveCursor', // Moving to the absolute first item from an embedded document
json: { action: 'moveFirst', // fails. Bug 972035.
rule: 'Simple', [ContentMessages.simpleMoveNext, {
inputType: 'gesture', speak: 'Phone status bar Traversal Rule test document'
origin: 'top' } }],
}; [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', // Reset cursors
json: { origin: 'top' } [ContentMessages.clearCursor, null],
};
function focusFunc(aSelector, aBlur) { // Move cursor with focus in outside document
return function (mm) { [ContentMessages.simpleMoveNext, {
mm.sendAsyncMessage( speak: 'Phone status bar Traversal Rule test document'
'AccessFuTest:Focus', { selector: aSelector, blur: aBlur }); }],
}; [ContentMessages.focusSelector('button#home', false), {
} speak: 'Home button'
}],
var contentTest = new AccessFuContentTest( // Blur button and reset cursor
[ [ContentMessages.focusSelector('button#home', true), null],
// Simple traversal forward [ContentMessages.clearCursor, null],
[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' }],
// Simple traversal backward // Set focus on element outside of embedded frame while
[simpleMovePrevious, // cursor is in frame
{ speak: 'many option checked check button such app' }], [ContentMessages.simpleMoveNext, {
[activateCurrent, speak: 'Phone status bar Traversal Rule test document'
{ speak: 'unchecked' }], }],
[null, [ContentMessages.simpleMoveNext, {
{ speak: 'unchecked', speak_checkFunc: 'todo_isnot' }], speak: 'wow heading level 1 such app'
[simpleMovePrevious, }],
{ speak: 'wow heading level 1' }], [ContentMessages.focusSelector('button#home', false), {
[simpleMovePrevious, speak: 'Home button'
{ speak: 'Phone status bar' }], }]
// Moving to the absolute last item from an embedded document fails. // Blur button and reset cursor
// Bug 972035. [ContentMessages.focusSelector('button#home', true), null],
[simpleMoveNext, [ContentMessages.clearCursor, null],
{ 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' }],
[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. // Open dialog in outer doc, while cursor is also in outer doc
// Bug 972035. [ContentMessages.simpleMoveNext, {
[simpleMoveNext, speak: 'Phone status bar Traversal Rule test document'
{ speak: 'Phone status bar Traversal Rule test document' }], }],
[simpleMoveNext, [doc.defaultView.showAlert, {
{ speak: 'wow heading level 1 such app' }], speak: 'This is an alert! heading level 1 dialog'
[simpleMoveNext, }],
{ speak: 'many option not checked check button' }],
[simpleMoveFirst,
{ speak: 'Phone status bar', speak_checkFunc: 'todo_is' }],
// Reset cursors [function() {
[clearCursor, null], doc.defaultView.hideAlert()
}, {
speak: 'wow heading level 1 such app'
}],
// Move cursor with focus in outside document [ContentMessages.clearCursor, null],
[simpleMoveNext,
{ speak: 'Phone status bar Traversal Rule test document' }],
[ focusFunc('button#home', false), { speak: 'Home button' }],
// Blur button and reset cursor // Open dialog in outer doc, while cursor is in inner frame
[focusFunc('button#home', true), null], [ContentMessages.simpleMoveNext, {
[clearCursor, null], 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 // XXX: Place cursor back where it was.
[simpleMoveNext, [doc.defaultView.hideAlert, {
{ speak: 'Phone status bar Traversal Rule test document' }], speak: 'many option not checked check button such app'
[simpleMoveNext, }],
{ speak: 'wow heading level 1 such app' }],
[focusFunc('button#home', false), { speak: 'Home button' }]
// Blur button and reset cursor [ContentMessages.clearCursor, null],
[focusFunc('button#home', true), null],
[clearCursor, null],
// XXX: Set focus on iframe itself. // Open dialog, then focus on something when closing
// XXX: Set focus on element in iframe when cursor is outside of it. [ContentMessages.simpleMoveNext, {
// XXX: Set focus on element in iframe when cursor is in iframe. 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 [function() {
[simpleMoveNext, doc.defaultView.hideAlert();
{ speak: 'Phone status bar Traversal Rule test document' }], doc.querySelector('button#home').focus();
[doc.defaultView.showAlert, }, {
{ speak: 'This is an alert! heading level 1 dialog' }], speak: 'Home button Traversal Rule test document'
}]
[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' }]
]);
contentTest.start(function () { contentTest.start(function () {
closeBrowserWindow(); 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>