blob: a37a63dd1553a022b9f544c369c70e6f1e1568d6 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
GEN_INCLUDE(['../dictation_test_base.js']);
/**
* Dictation tests for speech parsing with Pumpkin. These tests do not use the
* live Pumpkin DLC, but instead use a local tar archive that mirrors the DLC.
* It's important that we keep the live DLC and the local tar archive in sync.
*/
DictationPumpkinParseTest = class extends DictationE2ETestBase {
/** @override */
async setUpDeferred() {
await this.mockAccessibilityPrivate.initializePumpkinData();
// Re-initialize PumpkinParseStrategy after mock Pumpkin data has been
// created.
this.getPumpkinParseStrategy().init_();
await importModule(
'SpeechParser',
'/accessibility_common/dictation/parse/speech_parser.js');
await importModule(
'SUPPORTED_LOCALES',
'/accessibility_common/dictation/parse/pumpkin/pumpkin_constants.js');
await super.setUpDeferred();
// By default, Dictation JS tests use regex parsing. Enable Pumpkin for
// this test suite.
this.getPumpkinParseStrategy().setEnabled(true);
}
/**
* @return {!Promise}
* @param {string=} locale An optional locale. If the locale is provided,
* this method will wait for Pumpkin to initialize in that locale. If the
* locale isn't provided, then this method will wait for Pumpkin to
* initialize in any locale.
* @private
*/
async waitForPumpkinParseStrategy_(locale) {
const strategy = this.getPumpkinParseStrategy();
const isReady = () => {
let localeOk = true;
if (locale) {
const pumpkinLocale = SUPPORTED_LOCALES[locale] || null;
localeOk = pumpkinLocale === strategy.locale_;
}
return localeOk && strategy.pumpkinTaggerReady_;
};
if (isReady()) {
return;
}
await new Promise(resolve => {
strategy.onPumpkinTaggerReadyChangedForTesting_ = () => {
if (isReady()) {
strategy.onPumpkinTaggerReadyChangedForTesting_ = null;
resolve();
}
};
});
}
};
// Tests that we can use the SandboxedPumpkinTagger to convert speech into a
// macro. The text to macro mapping can be found in
// google3/chrome/chromeos/accessibility/dictation/grammars/\
// dictation_en_us.patterns
AX_TEST_F('DictationPumpkinParseTest', 'Parse', async function() {
await this.waitForPumpkinParseStrategy_();
/** @type {!Array<!ParseTestCase>} */
const testCases = [
new ParseTestCase('Hello world', {}),
new ParseTestCase('dictate delete', {name: 'INPUT_TEXT_VIEW'}),
new ParseTestCase('backspace', {name: 'DELETE_PREV_CHAR'}),
new ParseTestCase('left one character', {name: 'NAV_PREV_CHAR'}),
new ParseTestCase('right one character', {name: 'NAV_NEXT_CHAR'}),
new ParseTestCase('up one line', {name: 'NAV_PREV_LINE'}),
new ParseTestCase('down one line', {name: 'NAV_NEXT_LINE'}),
new ParseTestCase('copy selected text', {name: 'COPY_SELECTED_TEXT'}),
new ParseTestCase('paste copied text', {name: 'PASTE_TEXT'}),
new ParseTestCase('cut highlighted text', {name: 'CUT_SELECTED_TEXT'}),
new ParseTestCase('undo that', {name: 'UNDO_TEXT_EDIT'}),
new ParseTestCase('redo that', {name: 'REDO_ACTION'}),
new ParseTestCase('select everything', {name: 'SELECT_ALL_TEXT'}),
new ParseTestCase('deselect selection', {name: 'UNSELECT_TEXT'}),
new ParseTestCase('what can I say', {name: 'LIST_COMMANDS'}),
new ParseTestCase('new line', {}),
new ParseTestCase('avada kedavra', {name: 'STOP_LISTENING'}),
new ParseTestCase('clear one word', {name: 'DELETE_PREV_WORD'}),
new ParseTestCase('erase sentence', {name: 'DELETE_PREV_SENT'}),
new ParseTestCase('right one word', {name: 'NAV_NEXT_WORD'}),
new ParseTestCase('back one word', {name: 'NAV_PREV_WORD'}),
new ParseTestCase('delete avada kedavra', {name: 'SMART_DELETE_PHRASE'}),
new ParseTestCase(
'replace hello with goodbye', {name: 'SMART_REPLACE_PHRASE'}),
new ParseTestCase(
'insert hello in front of goodbye', {name: 'SMART_INSERT_BEFORE'}),
new ParseTestCase(
'highlight everything between hello and goodbye',
{name: 'SMART_SELECT_BTWN_INCL'}),
new ParseTestCase('forward one sentence', {name: 'NAV_NEXT_SENT'}),
new ParseTestCase('one sentence back', {name: 'NAV_PREV_SENT'}),
new ParseTestCase('clear', {name: 'DELETE_ALL_TEXT'}),
new ParseTestCase('to start', {name: 'NAV_START_TEXT'}),
new ParseTestCase('to end', {name: 'NAV_END_TEXT'}),
new ParseTestCase('highlight back one word', {name: 'SELECT_PREV_WORD'}),
new ParseTestCase('highlight right one word', {name: 'SELECT_NEXT_WORD'}),
new ParseTestCase('select next letter', {name: 'SELECT_NEXT_CHAR'}),
new ParseTestCase('select previous letter', {name: 'SELECT_PREV_CHAR'}),
new ParseTestCase('try that action again', {name: 'REPEAT'}),
];
for (const test of testCases) {
await this.runPumpkinParseTestCase(test);
}
});
// Tests that we can use the SandboxedPumpkinTagger to parse text and yield
// a RepeatableKeyPressMacro with a `repeat_` value greater than one.
AX_TEST_F(
'DictationPumpkinParseTest', 'RepeatableKeyPressMacro', async function() {
await this.waitForPumpkinParseStrategy_();
/** @type {!Array<!ParseTestCase>} */
const testCases = [
new ParseTestCase(
'remove two characters', {name: 'DELETE_PREV_CHAR', repeat: 2}),
new ParseTestCase(
'left five characters', {name: 'NAV_PREV_CHAR', repeat: 5}),
new ParseTestCase(
'clear five words', {name: 'DELETE_PREV_WORD', repeat: 5}),
new ParseTestCase(
'forward three words', {name: 'NAV_NEXT_WORD', repeat: 3}),
new ParseTestCase(
'backward three words', {name: 'NAV_PREV_WORD', repeat: 3}),
new ParseTestCase(
'highlight back three words',
{name: 'SELECT_PREV_WORD', repeat: 3}),
new ParseTestCase(
'highlight right three words',
{name: 'SELECT_NEXT_WORD', repeat: 3}),
new ParseTestCase(
'select next three letters', {name: 'SELECT_NEXT_CHAR', repeat: 3}),
new ParseTestCase(
'select previous three letters',
{name: 'SELECT_PREV_CHAR', repeat: 3}),
];
for (const test of testCases) {
await this.runPumpkinParseTestCase(test);
}
});
// Tests that smart macro properties are correctly parsed and set.
AX_TEST_F('DictationPumpkinParseTest', 'SmartMacros', async function() {
await this.waitForPumpkinParseStrategy_();
let macro =
await this.getPumpkinParseStrategy().parse('delete avada kedavra');
assertEquals('SMART_DELETE_PHRASE', macro.getNameAsString());
assertEquals('avada kedavra', macro.phrase_);
macro =
await this.getPumpkinParseStrategy().parse('replace hello with goodbye');
assertEquals('SMART_REPLACE_PHRASE', macro.getNameAsString());
assertEquals('hello', macro.deletePhrase_);
assertEquals('goodbye', macro.insertPhrase_);
macro = await this.getPumpkinParseStrategy().parse(
'insert hello in front of goodbye');
assertEquals('SMART_INSERT_BEFORE', macro.getNameAsString());
assertEquals('hello', macro.insertPhrase_);
assertEquals('goodbye', macro.beforePhrase_);
macro = await this.getPumpkinParseStrategy().parse(
'highlight everything between hello and goodbye');
assertEquals('SMART_SELECT_BTWN_INCL', macro.getNameAsString());
assertEquals('hello', macro.startPhrase_);
assertEquals('goodbye', macro.endPhrase_);
});
AX_TEST_F('DictationPumpkinParseTest', 'ChangeLocale', async function() {
await this.waitForPumpkinParseStrategy_();
this.alwaysEnableCommands();
const testCases = [
{
locale: 'fr-FR',
testCase: new ParseTestCase('copier', {name: 'COPY_SELECTED_TEXT'}),
},
{
locale: 'fr-FR',
testCase: new ParseTestCase(
'supprimer deux caractères précédent',
{name: 'DELETE_PREV_CHAR', repeat: 2}),
},
{
locale: 'it-IT',
testCase: new ParseTestCase('annulla', {name: 'UNDO_TEXT_EDIT'}),
},
{
locale: 'de-DE',
testCase: new ParseTestCase('hilf mir', {name: 'LIST_COMMANDS'}),
},
{
locale: 'es-ES',
testCase: new ParseTestCase('ayuda', {name: 'LIST_COMMANDS'}),
},
{
locale: 'en-GB',
testCase:
new ParseTestCase('copy selected text', {name: 'COPY_SELECTED_TEXT'}),
},
];
for (const {locale, testCase} of testCases) {
await this.setPref(Dictation.DICTATION_LOCALE_PREF, locale);
await this.waitForPumpkinParseStrategy_(locale);
await this.runPumpkinParseTestCase(testCase);
}
});
AX_TEST_F('DictationPumpkinParseTest', 'UnsupportedLocale', async function() {
await this.waitForPumpkinParseStrategy_();
this.alwaysEnableCommands();
await this.setPref(Dictation.DICTATION_LOCALE_PREF, 'ja');
// Don't pass in a locale below because 'ja' is an unsupported locale (and
// thus Pumpkin will never initialize in that locale).
await this.waitForPumpkinParseStrategy_();
await this.runPumpkinParseTestCase(
new ParseTestCase('copy selected text', {}));
// Would produce an UNDO_TEXT_EDIT macro if Japanese was supported.
await this.runPumpkinParseTestCase(new ParseTestCase('もとどおりにする', {}));
await this.setPref(Dictation.DICTATION_LOCALE_PREF, 'en-US');
await this.waitForPumpkinParseStrategy_('en-US');
await this.runPumpkinParseTestCase(
new ParseTestCase('copy selected text', {name: 'COPY_SELECTED_TEXT'}));
});