File: dictation_test.js

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (343 lines) | stat: -rw-r--r-- 12,970 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
// Copyright 2021 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 feature using accessibility common extension browser tests. */
DictationE2ETest = class extends DictationE2ETestBase {};

AX_TEST_F('DictationE2ETest', 'ResetsImeAfterToggleOff', async function() {
  // Set something as the active IME.
  this.mockInputMethodPrivate.setCurrentInputMethod('keyboard_cat');
  this.mockLanguageSettingsPrivate.addInputMethod('keyboard_cat');
  this.toggleDictationOn();
  this.toggleDictationOff();
  this.checkDictationImeInactive('keyboard_cat');
});

AX_TEST_F('DictationE2ETest', 'UpdateRecognitionProps', async function() {
  assertFalse(this.getSpeechRecognitionActive());
  assertEquals(undefined, this.getSpeechRecognitionLocale());
  assertEquals(undefined, this.getSpeechRecognitionInterimResults());

  const locale = await this.getPref(Dictation.DICTATION_LOCALE_PREF);
  this.updateSpeechRecognitionProperties(
      {locale: locale.value, interimResults: true});

  assertEquals(locale.value, this.getSpeechRecognitionLocale());
  assertTrue(this.getSpeechRecognitionInterimResults());
});

AX_TEST_F(
    'DictationE2ETest', 'UpdatesSpeechRecognitionLangOnLocaleChange',
    async function() {
      let locale = await this.getPref(Dictation.DICTATION_LOCALE_PREF);
      this.updateSpeechRecognitionProperties({locale: locale.value});
      assertEquals(locale.value, this.getSpeechRecognitionLocale());
      // Change the locale.
      await this.setPref(Dictation.DICTATION_LOCALE_PREF, 'es-ES');
      locale = await this.getPref(Dictation.DICTATION_LOCALE_PREF);
      this.updateSpeechRecognitionProperties({locale: locale.value});
      assertEquals('es-ES', this.getSpeechRecognitionLocale());
    });

AX_TEST_F('DictationE2ETest', 'StopsOnRecognitionError', async function() {
  this.toggleDictationOn();
  this.sendSpeechRecognitionErrorEvent();
  assertFalse(this.getDictationActive());
  assertFalse(this.getSpeechRecognitionActive());
});

AX_TEST_F('DictationE2ETest', 'StopsOnImeBlur', async function() {
  this.toggleDictationOn();
  this.blurInputContext();
  assertFalse(this.getSpeechRecognitionActive());
  assertFalse(this.getDictationActive());
  assertFalse(Boolean(this.mockInputIme.getLastCommittedParameters()));
});

AX_TEST_F('DictationE2ETest', 'CommitsFinalResults', async function() {
  this.toggleDictationOn();
  this.sendInterimSpeechResult('kittens');
  assertFalse(Boolean(this.mockInputIme.getLastCommittedParameters()));
  assertTrue(this.getDictationActive());

  this.mockInputIme.clearLastParameters();
  this.sendFinalSpeechResult('kittens!');
  await this.assertCommittedText('kittens!');
  assertTrue(this.getDictationActive());

  this.mockInputIme.clearLastParameters();
  this.sendFinalSpeechResult('puppies!');
  await this.assertCommittedText('puppies!');
  assertTrue(this.getDictationActive());

  this.mockInputIme.clearLastParameters();
  this.toggleDictationOff();
  assertFalse(this.getDictationActive());
  assertFalse(Boolean(this.mockInputIme.getLastCommittedParameters()));
});

AX_TEST_F(
    'DictationE2ETest', 'CommitsInterimResultsWhenRecognitionStops',
    async function() {
      this.toggleDictationOn();
      this.sendInterimSpeechResult('fish fly');
      this.sendSpeechRecognitionStopEvent();
      assertFalse(this.getDictationActive());
      await this.assertCommittedText('fish fly');
    });

AX_TEST_F(
    'DictationE2ETest', 'DoesNotCommitInterimResultsAfterImeBlur',
    async function() {
      this.toggleDictationOn();
      this.sendInterimSpeechResult('ducks dig');
      this.blurInputContext();
      assertFalse(this.getDictationActive());
      assertFalse(Boolean(this.mockInputIme.getLastCommittedParameters()));
    });

AX_TEST_F('DictationE2ETest', 'TimesOutWithNoImeContext', async function() {
  this.mockSetTimeoutMethod();
  this.toggleDictationOn();

  const callback =
      this.getCallbackWithDelay(Dictation.Timeouts.NO_FOCUSED_IME_MS);
  assertNotNullNorUndefined(callback);

  // Triggering the timeout should cause a request to toggle Dictation, but
  // nothing should be committed after AccessibilityPrivate toggle is received.
  callback();
  this.clearSetTimeoutData();
  assertFalse(this.getDictationActive());
  assertFalse(Boolean(this.mockInputIme.getLastCommittedParameters()));
});

AX_TEST_F('DictationE2ETest', 'TimesOutWithNoSpeechNetwork', async function() {
  this.mockSpeechRecognitionPrivate.setSpeechRecognitionType(
      SpeechRecognitionType.NETWORK);
  this.mockSetTimeoutMethod();
  this.toggleDictationOn();

  const callback =
      this.getCallbackWithDelay(Dictation.Timeouts.NO_SPEECH_NETWORK_MS);
  assertNotNullNorUndefined(callback);

  // Triggering the timeout should cause a request to toggle Dictation, but
  // nothing should be committed after AccessibilityPrivate toggle is received.
  callback();
  this.clearSetTimeoutData();
  assertFalse(this.getDictationActive());
  assertFalse(Boolean(this.mockInputIme.getLastCommittedParameters()));
});

AX_TEST_F('DictationE2ETest', 'TimesOutWithNoSpeechOnDevice', async function() {
  this.mockSpeechRecognitionPrivate.setSpeechRecognitionType(
      SpeechRecognitionType.ON_DEVICE);
  this.mockSetTimeoutMethod();
  this.toggleDictationOn();

  const callback =
      this.getCallbackWithDelay(Dictation.Timeouts.NO_SPEECH_ONDEVICE_MS);
  assertNotNullNorUndefined(callback);

  // Triggering the timeout should cause a request to toggle Dictation, but
  // nothing should be committed after AccessibilityPrivate toggle is received.
  callback();
  this.clearSetTimeoutData();
  assertFalse(this.getDictationActive());
  assertFalse(Boolean(this.mockInputIme.getLastCommittedParameters()));
});

AX_TEST_F(
    'DictationE2ETest', 'TimesOutAfterInterimResultsAndCommits',
    async function() {
      this.mockSetTimeoutMethod();
      this.toggleDictationOn();
      this.sendInterimSpeechResult('sheep sleep');
      this.mockInputIme.clearLastParameters();

      // The timeout should be set based on the interim result.
      const callback =
          this.getCallbackWithDelay(Dictation.Timeouts.NO_NEW_SPEECH_MS);
      assertNotNullNorUndefined(callback);

      // Triggering the timeout should cause a request to toggle Dictation, and
      // after AccessibilityPrivate calls toggleDictation, to commit the interim
      // text.
      callback();
      this.clearSetTimeoutData();
      assertFalse(this.getDictationActive());
      await this.assertCommittedText('sheep sleep');
    });

AX_TEST_F('DictationE2ETest', 'TimesOutAfterFinalResults', async function() {
  this.mockSetTimeoutMethod();
  this.toggleDictationOn();
  this.sendFinalSpeechResult('bats bounce');
  await this.assertCommittedText('bats bounce');
  this.mockInputIme.clearLastParameters();

  // The timeout should be set based on the final result.
  const callback =
      this.getCallbackWithDelay(Dictation.Timeouts.NO_SPEECH_NETWORK_MS);

  // Triggering the timeout should stop listening.
  callback();
  this.clearSetTimeoutData();
  assertFalse(this.getDictationActive());
  assertFalse(Boolean(this.mockInputIme.getLastCommittedParameters()));
});

AX_TEST_F(
    'DictationE2ETest', 'CommandsDoNotCommitThemselves', async function() {
      this.toggleDictationOn();
      for (const command of Object.values(this.commandStrings)) {
        this.sendInterimSpeechResult(command);
        if (command !== this.commandStrings.LIST_COMMANDS) {
          // LIST_COMMANDS opens a new tab and ends Dictation. Skip this.
          this.sendFinalSpeechResult(command);
        }
        if (command === this.commandStrings.NEW_LINE) {
          await this.assertCommittedText('\n');
          this.mockInputIme.clearLastParameters();
        } else {
          // On final result, nothing is committed; instead, an action is taken.
          assertFalse(Boolean(this.mockInputIme.getLastCommittedParameters()));
        }

        // Try to type the command e.g. "type delete".
        // The command should be entered but not the word "type".
        this.sendFinalSpeechResult(`type ${command}`);
        await this.assertCommittedText(command);
        this.mockInputIme.clearLastParameters();
      }
    });

AX_TEST_F(
    'DictationE2ETest', 'TypePrefixWorksForNonCommands', async function() {
      this.toggleDictationOn();
      this.sendFinalSpeechResult('type this is a test');
      await this.assertCommittedText('this is a test');
    });

AX_TEST_F('DictationE2ETest', 'DontCommitAfterMacroSuccess', async function() {
  this.toggleDictationOn();
  this.sendInterimSpeechResult('move to the next line');
  // Perform the next line command.
  this.sendFinalSpeechResult('move to the next line');
  // Wait for the UI to show macro success.
  await this.waitForUIProperties({
    visible: true,
    icon: this.iconType.MACRO_SUCCESS,
    text: this.commandStrings.NAV_NEXT_LINE,
  });
  this.toggleDictationOff();
  // No text should be committed.
  assertFalse(Boolean(this.mockInputIme.getLastCommittedParameters()));
});


AX_TEST_F('DictationE2ETest', 'NoCommandsWhenNotSupported', async function() {
  this.toggleDictationOn();
  this.sendFinalSpeechResult('New line');
  await this.assertCommittedText('\n');
  this.mockInputIme.clearLastParameters();

  // System language is en-US. If the Dictation locale doesn't match,
  // commands should not work.
  await this.setPref(Dictation.DICTATION_LOCALE_PREF, 'es-ES');

  // Now this text should just get typed in instead of reinterpreted.
  this.sendFinalSpeechResult('New line');
  await this.assertCommittedText('New line');
  this.mockInputIme.clearLastParameters();
});

// TODO(crbug.com/1442591) flaky test
AX_TEST_F(
    'DictationE2ETest', 'DISABLED_SilencesSpokenFeedbackWhenStarting',
    async function() {
      assertEquals(
          0, this.mockAccessibilityPrivate.getSpokenFeedbackSilencedCount());

      // Turn on ChromeVox
      await this.setPref(Dictation.SPOKEN_FEEDBACK_PREF, true);

      // Now silenceSpokenFeedback should get called when toggling Dictation on.
      this.toggleDictationOn();
      assertEquals(
          1, this.mockAccessibilityPrivate.getSpokenFeedbackSilencedCount());

      // It should not be called when turning Dictation off.
      this.toggleDictationOff();
      assertEquals(
          1, this.mockAccessibilityPrivate.getSpokenFeedbackSilencedCount());
    });

AX_TEST_F(
    'DictationE2ETest', 'DoesNotSilenceSpokenFeedbackUnnecessarily',
    async function() {
      assertEquals(
          0, this.mockAccessibilityPrivate.getSpokenFeedbackSilencedCount());

      // Check that when ChromeVox is disabled we don't try to silence it when
      // Dictation gets toggled.
      this.toggleDictationOn();
      assertEquals(
          0, this.mockAccessibilityPrivate.getSpokenFeedbackSilencedCount());
      this.toggleDictationOff();
      assertEquals(
          0, this.mockAccessibilityPrivate.getSpokenFeedbackSilencedCount());
    });

AX_TEST_F(
    'DictationE2ETest', 'SurroundingInfoResetsAfterToggleOff',
    async function() {
      assertEquals(null, this.getInputController().surroundingInfo_);
      this.toggleDictationOn();
      const value = 'This is a test';
      this.sendFinalSpeechResult(value);
      // A surroundingTextChanged event is fired whenever the editable value
      // or the caret index is changed.
      this.mockInputIme.callOnSurroundingTextChanged({
        anchor: value.length,
        focus: value.length,
        offset: 0,
        text: value,
      });
      assertNotNullNorUndefined(this.getInputController().surroundingInfo_);
      this.toggleDictationOff();
      assertEquals(null, this.getInputController().surroundingInfo_);
    });

AX_TEST_F('DictationE2ETest', 'ShowsToastWhenMicMuted', async function() {
  const StreamType = chrome.audio.StreamType;
  const ToastType = chrome.accessibilityPrivate.ToastType;

  assertEquals(
      0,
      this.mockAccessibilityPrivate.getShowToastCount(
          ToastType.DICTATION_MIC_MUTED));
  await new Promise(
      resolve =>
          chrome.audio.setMute(StreamType.INPUT, /*isMuted=*/ true, resolve));

  // Use callOnToggleDictation instead of toggleDictation because the latter
  // asserts that speech recognition successfully starts, which won't be the
  // case here.
  this.mockAccessibilityPrivate.callOnToggleDictation(true);
  assertTrue(this.getDictationActive());
  this.checkDictationImeActive();
  // Focus the input context so that we try to start speech recognition. We'll
  // fail to start since the device is muted.
  this.focusInputContext();
  // Confirm that a toast was shown and that Dictation is inactive.
  assertEquals(
      1,
      this.mockAccessibilityPrivate.getShowToastCount(
          ToastType.DICTATION_MIC_MUTED));
  assertFalse(this.getDictationActive());
});