m87: Add test coverage for editable events
This change precisely stipulates the events handled for each type of editable
encountered through tests.
TBR=[email protected]
pressing 'e' would also cause sticky mode to turn off.
(cherry picked from commit 788cc609e1a8f386aec22cfbf8d06fe8dc984a5f)
Fixed: 1135118
AX-Relnotes: fixes an issue in Smart Sticky mode where jumping to a text field by
Change-Id: I56de4cebc0a1a942d99c5d0c9445b5b33f9d4e00
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2448053
Reviewed-by: Akihiro Ota <[email protected]>
Commit-Queue: David Tseng <[email protected]>
Cr-Original-Commit-Position: refs/heads/master@{#814056}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2461607
Reviewed-by: David Tseng <[email protected]>
Cr-Commit-Position: refs/branch-heads/4280@{#148}
Cr-Branched-From: ea420fb963f9658c9969b6513c56b8f47efa1a2a-refs/heads/master@{#812852}
diff --git a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
index 8a574a4..7b55449 100644
--- a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
+++ b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
@@ -871,6 +871,26 @@
sm_.ExpectSpeech("Sticky mode enabled");
sm_.ExpectSpeech("start");
+ // Try a few jump commands and linear nav with no Search modifier. We never
+ // leave sticky mode.
+ sm_.Call([this]() { SendKeyPress(ui::VKEY_E); });
+ sm_.ExpectSpeech("Edit text");
+
+ sm_.Call([this]() { SendKeyPressWithShift(ui::VKEY_F); });
+ sm_.ExpectSpeech("Edit text");
+
+ sm_.Call([this]() { SendKeyPress(ui::VKEY_RIGHT); });
+ sm_.ExpectSpeech("end");
+
+ sm_.Call([this]() { SendKeyPress(ui::VKEY_F); });
+ sm_.ExpectSpeech("Edit text");
+
+ sm_.Call([this]() { SendKeyPressWithShift(ui::VKEY_E); });
+ sm_.ExpectSpeech("Edit text");
+
+ sm_.Call([this]() { SendKeyPressWithSearch(ui::VKEY_LEFT); });
+ sm_.ExpectSpeech("start");
+
// Now, navigate with sticky mode off.
sm_.Call([this]() { SendStickyKeyCommand(); });
sm_.ExpectSpeech("Sticky mode disabled");
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js
index 3ffa8ee5..5380e31 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js
@@ -361,14 +361,37 @@
* @private
*/
onEditableChanged_(evt) {
- // Document selections only apply to rich editables, text selections to
- // non-rich editables.
- if (evt.type != EventType.DOCUMENT_SELECTION_CHANGED &&
- (evt.target.state[StateType.RICHLY_EDITABLE] ||
- evt.target.htmlTag === 'textarea')) {
+ if (!evt.target.state.editable) {
return;
}
+ const isInput = evt.target.htmlTag == 'input';
+ const isTextArea = evt.target.htmlTag == 'textarea';
+ const isContentEditable = evt.target.state[StateType.RICHLY_EDITABLE];
+
+ switch (evt.type) {
+ case EventType.TEXT_CHANGED:
+ case EventType.TEXT_SELECTION_CHANGED:
+ case EventType.VALUE_CHANGED:
+ // Known to be duplicated by document selection changes for content
+ // editables and text areas.
+ if (isContentEditable || isTextArea) {
+ return;
+ }
+ break;
+ case EventType.DOCUMENT_SELECTION_CHANGED:
+ // Known to be duplicated by text selection changes.
+ if (isInput) {
+ return;
+ }
+ break;
+ case EventType.FOCUS:
+ // Allowed no matter what.
+ break;
+ default:
+ return;
+ }
+
if (!this.createTextEditHandlerIfNeeded_(evt.target)) {
return;
}
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing.js
index d83d976..ccaf98f 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing.js
@@ -87,14 +87,7 @@
* @param {!ChromeVoxEvent} evt
*/
onEvent(evt) {
- if (evt.type !== EventType.TEXT_CHANGED &&
- evt.type !== EventType.TEXT_SELECTION_CHANGED &&
- evt.type !== EventType.DOCUMENT_SELECTION_CHANGED &&
- evt.type !== EventType.VALUE_CHANGED && evt.type !== EventType.FOCUS) {
- return;
- }
- if (!evt.target.state.focused || !evt.target.state.editable ||
- evt.target != this.node_) {
+ if (!evt.target.state.focused || evt.target != this.node_) {
return;
}
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing_test.js
index 32f381d..3adaf17 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing_test.js
@@ -21,6 +21,13 @@
EventGenerator.sendKeyPress(keyCode, modifiers);
};
}
+
+ waitForEditableEvent() {
+ return new Promise(resolve => {
+ DesktopAutomationHandler.instance.textEditHandler_.onEvent = (e) =>
+ resolve(e);
+ });
+ }
};
@@ -96,7 +103,7 @@
if (input.selectionStart == 0) {
return;
}
- console.log('TIM' + 'ER');
+
input.value = 'text2';
window.clearInterval(timer);
}
@@ -1470,3 +1477,111 @@
input.focus();
});
});
+
+TEST_F('ChromeVoxEditingTest', 'InputEvents', function() {
+ const site = `<input type="text"></input>`;
+ this.runWithLoadedTree(site, async function(root) {
+ const input = root.find({role: RoleType.TEXT_FIELD});
+ input.focus();
+ await new Promise(resolve => {
+ this.listenOnce(input, 'focus', resolve);
+ });
+
+ let event = await this.waitForEditableEvent();
+ assertEquals(EventType.TEXT_SELECTION_CHANGED, event.type);
+ assertEquals(input, event.target);
+ assertEquals('', input.value);
+
+ this.press(KeyCode.A)();
+
+ // Important to note that there's no document selection changes below.
+ event = await this.waitForEditableEvent();
+ assertEquals(EventType.VALUE_CHANGED, event.type);
+ assertEquals(input, event.target);
+ assertEquals('a', input.value);
+
+ event = await this.waitForEditableEvent();
+ assertEquals(EventType.TEXT_SELECTION_CHANGED, event.type);
+ assertEquals(input, event.target);
+ assertEquals('a', input.value);
+
+ // TODO(accessibility): this extra value change shouldn't happen.
+ // http://crbug.com/1135249.
+ event = await this.waitForEditableEvent();
+ assertEquals(EventType.VALUE_CHANGED, event.type);
+ assertEquals(input, event.target);
+ assertEquals('a', input.value);
+
+ this.press(KeyCode.B)();
+
+ event = await this.waitForEditableEvent();
+ assertEquals(EventType.VALUE_CHANGED, event.type);
+ assertEquals(input, event.target);
+ assertEquals('ab', input.value);
+
+ event = await this.waitForEditableEvent();
+ assertEquals(EventType.TEXT_SELECTION_CHANGED, event.type);
+ assertEquals(input, event.target);
+ assertEquals('ab', input.value);
+ });
+});
+
+TEST_F('ChromeVoxEditingTest', 'TextAreaEvents', function() {
+ const site = `<textarea></textarea>`;
+ this.runWithLoadedTree(site, async function(root) {
+ const textArea = root.find({role: RoleType.TEXT_FIELD});
+ textArea.focus();
+ await new Promise(resolve => {
+ this.listenOnce(textArea, 'focus', resolve);
+ });
+
+ let event = await this.waitForEditableEvent();
+ assertEquals(EventType.DOCUMENT_SELECTION_CHANGED, event.type);
+ assertEquals(textArea, event.target);
+ assertEquals('', textArea.value);
+
+ this.press(KeyCode.A)();
+
+ event = await this.waitForEditableEvent();
+ assertEquals(EventType.DOCUMENT_SELECTION_CHANGED, event.type);
+ assertEquals(textArea, event.target);
+ assertEquals('a', textArea.value);
+
+ this.press(KeyCode.B)();
+
+ event = await this.waitForEditableEvent();
+ assertEquals(EventType.DOCUMENT_SELECTION_CHANGED, event.type);
+ assertEquals(textArea, event.target);
+ assertEquals('ab', textArea.value);
+ });
+});
+
+TEST_F('ChromeVoxEditingTest', 'ContentEditableEvents', function() {
+ const site = `<div role="textbox" contenteditable></div>`;
+ this.runWithLoadedTree(site, async function(root) {
+ const contentEditable = root.find({role: RoleType.TEXT_FIELD});
+ contentEditable.focus();
+ await new Promise(resolve => {
+ this.listenOnce(contentEditable, 'focus', resolve);
+ });
+
+ let event = await this.waitForEditableEvent();
+ assertEquals(EventType.DOCUMENT_SELECTION_CHANGED, event.type);
+ assertEquals(contentEditable, event.target);
+ assertEquals('', contentEditable.value);
+
+ this.press(KeyCode.A)();
+
+ event = await this.waitForEditableEvent();
+ assertEquals(EventType.DOCUMENT_SELECTION_CHANGED, event.type);
+ assertEquals(contentEditable, event.target);
+ assertEquals('a', contentEditable.value);
+
+ this.press(KeyCode.B)();
+
+ event = await this.waitForEditableEvent();
+ assertEquals(EventType.DOCUMENT_SELECTION_CHANGED, event.type);
+ assertEquals(contentEditable, event.target);
+ assertEquals('ab', contentEditable.value);
+ });
+});