1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.accessibility;
18 
19 import static com.android.settings.accessibility.AccessibilityShortcutsTutorial.createAccessibilityTutorialDialog;
20 import static com.android.settings.accessibility.AccessibilityShortcutsTutorial.createAccessibilityTutorialDialogForSetupWizard;
21 import static com.android.settings.accessibility.AccessibilityShortcutsTutorial.createShortcutTutorialPages;
22 import static com.android.settings.accessibility.AccessibilityShortcutsTutorial.showGestureNavigationTutorialDialog;
23 import static com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
24 
25 import static com.google.common.truth.Truth.assertThat;
26 
27 import static org.mockito.Mockito.verify;
28 import static org.robolectric.Shadows.shadowOf;
29 
30 import android.app.Activity;
31 import android.app.settings.SettingsEnums;
32 import android.content.Context;
33 import android.content.DialogInterface;
34 import android.content.Intent;
35 import android.platform.test.annotations.EnableFlags;
36 import android.platform.test.flag.junit.SetFlagsRule;
37 import android.text.SpannableStringBuilder;
38 import android.util.ArrayMap;
39 import android.view.View;
40 import android.view.accessibility.AccessibilityManager;
41 import android.widget.Button;
42 import android.widget.TextSwitcher;
43 import android.widget.TextView;
44 
45 import androidx.appcompat.app.AlertDialog;
46 import androidx.test.core.app.ApplicationProvider;
47 
48 import com.android.server.accessibility.Flags;
49 import com.android.settings.R;
50 import com.android.settings.SettingsActivity;
51 import com.android.settings.SubSettings;
52 import com.android.settings.testutils.AccessibilityTestUtils;
53 import com.android.settings.testutils.shadow.SettingsShadowResources;
54 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
55 import com.android.settingslib.utils.StringUtil;
56 
57 import org.junit.Before;
58 import org.junit.Rule;
59 import org.junit.Test;
60 import org.junit.runner.RunWith;
61 import org.mockito.Mock;
62 import org.mockito.junit.MockitoJUnit;
63 import org.mockito.junit.MockitoRule;
64 import org.robolectric.Robolectric;
65 import org.robolectric.RobolectricTestRunner;
66 import org.robolectric.annotation.Config;
67 import org.robolectric.shadows.ShadowAccessibilityManager;
68 import org.robolectric.shadows.ShadowLooper;
69 
70 import java.util.Map;
71 
72 /** Tests for {@link AccessibilityShortcutsTutorial}. */
73 @Config(shadows = SettingsShadowResources.class)
74 @RunWith(RobolectricTestRunner.class)
75 public final class AccessibilityShortcutsTutorialTest {
76     private static final String FAKE_FEATURE_NAME = "Fake Feature Name";
77 
78     @Rule
79     public final MockitoRule mMockitoRule = MockitoJUnit.rule();
80     @Rule
81     public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
82     @Mock
83     private DialogInterface.OnClickListener mOnClickListener;
84     @Mock
85     private DialogInterface.OnDismissListener mOnDismissListener;
86     private final Context mContext = ApplicationProvider.getApplicationContext();
87     private int mShortcutTypes;
88 
89     @Before
setUp()90     public void setUp() {
91         mContext.setTheme(androidx.appcompat.R.style.Theme_AppCompat);
92         mShortcutTypes = /* initial */ 0;
93     }
94 
95     @Test(expected = IllegalArgumentException.class)
createTutorialPages_shortcutListIsEmpty_throwsException()96     public void createTutorialPages_shortcutListIsEmpty_throwsException() {
97         createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME);
98     }
99 
100     @Test
createTutorialPages_turnOnTripleTapShortcut_hasOnePage()101     public void createTutorialPages_turnOnTripleTapShortcut_hasOnePage() {
102         mShortcutTypes |= UserShortcutType.TRIPLETAP;
103 
104         final AlertDialog alertDialog =
105                 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME);
106 
107         assertThat(
108                 createShortcutTutorialPages(
109                         mContext, mShortcutTypes, FAKE_FEATURE_NAME, /* inSetupWizard= */ false)
110         ).hasSize(/* expectedSize= */ 1);
111         assertThat(alertDialog).isNotNull();
112     }
113 
114     @Test
115     @EnableFlags(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
createTutorialPages_turnOnTwoFingerTripleTapShortcut_hasOnePage()116     public void createTutorialPages_turnOnTwoFingerTripleTapShortcut_hasOnePage() {
117         mShortcutTypes |= UserShortcutType.TWOFINGER_DOUBLETAP;
118 
119         final AlertDialog alertDialog =
120                 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME);
121 
122         assertThat(
123                 createShortcutTutorialPages(
124                         mContext, mShortcutTypes, FAKE_FEATURE_NAME, /* inSetupWizard= */ false)
125         ).hasSize(/* expectedSize= */ 1);
126         assertThat(alertDialog).isNotNull();
127     }
128 
129     @Test
130     @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
createTutorialPages_turnOnQuickSettingShortcut_hasOnePage()131     public void createTutorialPages_turnOnQuickSettingShortcut_hasOnePage() {
132         mShortcutTypes |= UserShortcutType.QUICK_SETTINGS;
133 
134         final AlertDialog alertDialog =
135                 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME);
136 
137         assertThat(
138                 createShortcutTutorialPages(
139                         mContext, mShortcutTypes, FAKE_FEATURE_NAME, /* inSetupWizard= */ false)
140         ).hasSize(/* expectedSize= */ 1);
141         assertThat(alertDialog).isNotNull();
142     }
143 
144     @Test
createTutorialPages_turnOnSoftwareShortcut_hasOnePage()145     public void createTutorialPages_turnOnSoftwareShortcut_hasOnePage() {
146         mShortcutTypes |= UserShortcutType.SOFTWARE;
147 
148         final AlertDialog alertDialog =
149                 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME);
150 
151         assertThat(
152                 createShortcutTutorialPages(
153                         mContext, mShortcutTypes, FAKE_FEATURE_NAME, /* inSetupWizard= */ false)
154         ).hasSize(/* expectedSize= */ 1);
155         assertThat(alertDialog).isNotNull();
156     }
157 
158     @Test
createTutorialPages_turnOnSoftwareAndHardwareShortcuts_hasTwoPages()159     public void createTutorialPages_turnOnSoftwareAndHardwareShortcuts_hasTwoPages() {
160         mShortcutTypes |= UserShortcutType.SOFTWARE;
161         mShortcutTypes |= UserShortcutType.HARDWARE;
162 
163         final AlertDialog alertDialog =
164                 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME);
165 
166         assertThat(
167                 createShortcutTutorialPages(
168                         mContext, mShortcutTypes, FAKE_FEATURE_NAME, /* inSetupWizard= */ false)
169         ).hasSize(/* expectedSize= */ 2);
170         assertThat(alertDialog).isNotNull();
171     }
172 
173     @Test
createTutorialPages_turnOnA11yGestureShortcut_linkButtonShownWithText()174     public void createTutorialPages_turnOnA11yGestureShortcut_linkButtonShownWithText() {
175         mShortcutTypes |= UserShortcutType.SOFTWARE;
176         AccessibilityTestUtils.setSoftwareShortcutMode(
177                 mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ false);
178 
179         final AlertDialog alertDialog =
180                 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME);
181         alertDialog.show();
182         ShadowLooper.idleMainLooper();
183 
184         Button btn = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
185         assertThat(btn).isNotNull();
186         assertThat(btn.getVisibility()).isEqualTo(View.VISIBLE);
187         assertThat(btn.getText().toString()).isEqualTo(
188                 mContext.getString(
189                         R.string.accessibility_tutorial_dialog_configure_software_shortcut_type));
190     }
191 
192     @Test
createTutorialPages_turnOnA11yNavButtonShortcut_linkButtonShownWithText()193     public void createTutorialPages_turnOnA11yNavButtonShortcut_linkButtonShownWithText() {
194         mShortcutTypes |= UserShortcutType.SOFTWARE;
195         AccessibilityTestUtils.setSoftwareShortcutMode(
196                 mContext, /* gestureNavEnabled= */ false, /* floatingButtonEnabled= */ false);
197 
198         final AlertDialog alertDialog =
199                 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME);
200         alertDialog.show();
201         ShadowLooper.idleMainLooper();
202 
203         Button btn = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
204         assertThat(btn).isNotNull();
205         assertThat(btn.getVisibility()).isEqualTo(View.VISIBLE);
206         assertThat(btn.getText().toString()).isEqualTo(
207                 mContext.getString(
208                         R.string.accessibility_tutorial_dialog_configure_software_shortcut_type));
209     }
210 
211     @Test
createTutorialPages_turnOnFloatingButtonShortcut_linkButtonShownWithText()212     public void createTutorialPages_turnOnFloatingButtonShortcut_linkButtonShownWithText() {
213         mShortcutTypes |= UserShortcutType.SOFTWARE;
214         AccessibilityTestUtils.setSoftwareShortcutMode(
215                 mContext, /* gestureNavEnabled= */ false, /* floatingButtonEnabled= */ true);
216 
217         final AlertDialog alertDialog =
218                 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME);
219         alertDialog.show();
220         ShadowLooper.idleMainLooper();
221 
222         Button btn = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
223         assertThat(btn).isNotNull();
224         assertThat(btn.getVisibility()).isEqualTo(View.VISIBLE);
225         assertThat(btn.getText().toString()).isEqualTo(
226                 mContext.getString(R.string.accessibility_tutorial_dialog_link_button));
227     }
228 
229     @Test
createTutorialPages_turnOnHardwareShortcut_linkButtonGone()230     public void createTutorialPages_turnOnHardwareShortcut_linkButtonGone() {
231         mShortcutTypes |= UserShortcutType.HARDWARE;
232 
233         final AlertDialog alertDialog =
234                 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME);
235         alertDialog.show();
236         ShadowLooper.idleMainLooper();
237 
238         assertThat(alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).getVisibility())
239                 .isEqualTo(View.GONE);
240     }
241 
242     @Test
createTutorialPages_turnOnSoftwareShortcut_showFromSuW_linkButtonGone()243     public void createTutorialPages_turnOnSoftwareShortcut_showFromSuW_linkButtonGone() {
244         mShortcutTypes |= UserShortcutType.SOFTWARE;
245 
246         final AlertDialog alertDialog =
247                 createAccessibilityTutorialDialogForSetupWizard(
248                         mContext, mShortcutTypes, FAKE_FEATURE_NAME);
249         alertDialog.show();
250         ShadowLooper.idleMainLooper();
251 
252         assertThat(alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).getVisibility())
253                 .isEqualTo(View.GONE);
254     }
255 
256     @Test
257     @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
createAccessibilityTutorialDialog_qsShortcut_inSuwTalkbackOn_verifyText()258     public void createAccessibilityTutorialDialog_qsShortcut_inSuwTalkbackOn_verifyText() {
259         mShortcutTypes |= UserShortcutType.QUICK_SETTINGS;
260         setTouchExplorationEnabled(true);
261         final String expectedTitle = mContext.getString(
262                 R.string.accessibility_tutorial_dialog_title_quick_setting);
263         Map<String, Object> arguments = new ArrayMap<>();
264         arguments.put("count", 2);
265         arguments.put("featureName", FAKE_FEATURE_NAME);
266         final CharSequence instruction = StringUtil.getIcuPluralsString(mContext,
267                 arguments,
268                 R.string.accessibility_tutorial_dialog_message_quick_setting);
269         final SpannableStringBuilder expectedInstruction = new SpannableStringBuilder();
270         expectedInstruction
271                 .append(mContext.getText(
272                         R.string.accessibility_tutorial_dialog_shortcut_unavailable_in_suw))
273                 .append("\n\n");
274         expectedInstruction.append(instruction);
275 
276         final AlertDialog alertDialog =
277                 createAccessibilityTutorialDialogForSetupWizard(
278                         mContext, mShortcutTypes, FAKE_FEATURE_NAME);
279         alertDialog.show();
280         ShadowLooper.idleMainLooper();
281 
282         verifyTutorialTitleAndInstruction(
283                 alertDialog,
284                 expectedTitle,
285                 expectedInstruction.toString());
286     }
287 
288     @Test
289     @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
createAccessibilityTutorialDialog_qsShortcut_notInSuwTalkbackOn_verifyText()290     public void createAccessibilityTutorialDialog_qsShortcut_notInSuwTalkbackOn_verifyText() {
291         mShortcutTypes |= UserShortcutType.QUICK_SETTINGS;
292         setTouchExplorationEnabled(true);
293         final String expectedTitle = mContext.getString(
294                 R.string.accessibility_tutorial_dialog_title_quick_setting);
295         Map<String, Object> arguments = new ArrayMap<>();
296         arguments.put("count", 2);
297         arguments.put("featureName", FAKE_FEATURE_NAME);
298         final CharSequence expectedInstruction = StringUtil.getIcuPluralsString(mContext,
299                 arguments,
300                 R.string.accessibility_tutorial_dialog_message_quick_setting);
301 
302         final AlertDialog alertDialog =
303                 createAccessibilityTutorialDialog(
304                         mContext, mShortcutTypes, FAKE_FEATURE_NAME);
305         alertDialog.show();
306         ShadowLooper.idleMainLooper();
307 
308         verifyTutorialTitleAndInstruction(
309                 alertDialog,
310                 expectedTitle,
311                 expectedInstruction.toString());
312     }
313 
314     @Test
315     @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
createAccessibilityTutorialDialog_qsShortcut_inSuwTalkbackOff_verifyText()316     public void createAccessibilityTutorialDialog_qsShortcut_inSuwTalkbackOff_verifyText() {
317         mShortcutTypes |= UserShortcutType.QUICK_SETTINGS;
318         setTouchExplorationEnabled(false);
319         final String expectedTitle = mContext.getString(
320                 R.string.accessibility_tutorial_dialog_title_quick_setting);
321         Map<String, Object> arguments = new ArrayMap<>();
322         arguments.put("count", 1);
323         arguments.put("featureName", FAKE_FEATURE_NAME);
324         final CharSequence instruction = StringUtil.getIcuPluralsString(mContext,
325                 arguments,
326                 R.string.accessibility_tutorial_dialog_message_quick_setting);
327         final SpannableStringBuilder expectedInstruction = new SpannableStringBuilder();
328         expectedInstruction.append(mContext.getText(
329                         R.string.accessibility_tutorial_dialog_shortcut_unavailable_in_suw))
330                 .append("\n\n");
331         expectedInstruction.append(instruction);
332 
333         final AlertDialog alertDialog =
334                 createAccessibilityTutorialDialogForSetupWizard(
335                         mContext, mShortcutTypes, FAKE_FEATURE_NAME);
336         alertDialog.show();
337         ShadowLooper.idleMainLooper();
338 
339         verifyTutorialTitleAndInstruction(
340                 alertDialog,
341                 expectedTitle,
342                 expectedInstruction.toString());
343     }
344 
345     @Test
346     @EnableFlags(android.view.accessibility.Flags.FLAG_A11Y_QS_SHORTCUT)
createAccessibilityTutorialDialog_qsShortcut_notInSuwTalkbackOff_verifyText()347     public void createAccessibilityTutorialDialog_qsShortcut_notInSuwTalkbackOff_verifyText() {
348         mShortcutTypes |= UserShortcutType.QUICK_SETTINGS;
349         setTouchExplorationEnabled(false);
350         final String expectedTitle = mContext.getString(
351                 R.string.accessibility_tutorial_dialog_title_quick_setting);
352         Map<String, Object> arguments = new ArrayMap<>();
353         arguments.put("count", 1);
354         arguments.put("featureName", FAKE_FEATURE_NAME);
355         final CharSequence expectedInstruction = StringUtil.getIcuPluralsString(mContext,
356                 arguments,
357                 R.string.accessibility_tutorial_dialog_message_quick_setting);
358 
359         final AlertDialog alertDialog =
360                 createAccessibilityTutorialDialog(
361                         mContext, mShortcutTypes, FAKE_FEATURE_NAME);
362         alertDialog.show();
363         ShadowLooper.idleMainLooper();
364 
365         verifyTutorialTitleAndInstruction(
366                 alertDialog,
367                 expectedTitle,
368                 expectedInstruction.toString());
369     }
370 
371     @Test
createAccessibilityTutorialDialog_volumeKeysShortcut_verifyText()372     public void createAccessibilityTutorialDialog_volumeKeysShortcut_verifyText() {
373         mShortcutTypes |= UserShortcutType.HARDWARE;
374         final String expectedTitle = mContext.getString(
375                 R.string.accessibility_tutorial_dialog_title_volume);
376         final CharSequence expectedInstruction = mContext.getString(
377                 R.string.accessibility_tutorial_dialog_message_volume);
378 
379         final AlertDialog alertDialog =
380                 createAccessibilityTutorialDialog(
381                         mContext, mShortcutTypes, FAKE_FEATURE_NAME);
382         alertDialog.show();
383         ShadowLooper.idleMainLooper();
384 
385         verifyTutorialTitleAndInstruction(
386                 alertDialog,
387                 expectedTitle,
388                 expectedInstruction.toString());
389     }
390 
391     @Test
createAccessibilityTutorialDialog_tripleTapShortcut_verifyText()392     public void createAccessibilityTutorialDialog_tripleTapShortcut_verifyText() {
393         mShortcutTypes |= UserShortcutType.TRIPLETAP;
394         final String expectedTitle = mContext.getString(
395                 R.string.accessibility_tutorial_dialog_title_triple);
396         final CharSequence expectedInstruction = mContext.getString(
397                 R.string.accessibility_tutorial_dialog_tripletap_instruction, 3);
398 
399         final AlertDialog alertDialog =
400                 createAccessibilityTutorialDialog(
401                         mContext, mShortcutTypes, FAKE_FEATURE_NAME);
402         alertDialog.show();
403         ShadowLooper.idleMainLooper();
404 
405         verifyTutorialTitleAndInstruction(
406                 alertDialog,
407                 expectedTitle,
408                 expectedInstruction.toString());
409     }
410 
411     @Test
412     @EnableFlags(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
createAccessibilityTutorialDialog_twoFingerDoubleTapShortcut_verifyText()413     public void createAccessibilityTutorialDialog_twoFingerDoubleTapShortcut_verifyText() {
414         mShortcutTypes |= UserShortcutType.TWOFINGER_DOUBLETAP;
415         final int numFingers = 2;
416         final String expectedTitle = mContext.getString(
417                 R.string.accessibility_tutorial_dialog_title_two_finger_double, numFingers);
418         final String expectedInstruction = mContext.getString(
419                 R.string.accessibility_tutorial_dialog_twofinger_doubletap_instruction, numFingers);
420 
421         final AlertDialog alertDialog =
422                 createAccessibilityTutorialDialog(
423                         mContext, mShortcutTypes, FAKE_FEATURE_NAME);
424         alertDialog.show();
425         ShadowLooper.idleMainLooper();
426 
427         verifyTutorialTitleAndInstruction(
428                 alertDialog,
429                 expectedTitle,
430                 expectedInstruction);
431     }
432 
433     @Test
createAccessibilityTutorialDialog_floatingButtonShortcut_verifyText()434     public void createAccessibilityTutorialDialog_floatingButtonShortcut_verifyText() {
435         mShortcutTypes |= UserShortcutType.SOFTWARE;
436         AccessibilityTestUtils.setSoftwareShortcutMode(
437                 mContext, /* gestureNavEnabled= */ false, /* floatingButtonEnabled= */ true);
438         final String expectedTitle = mContext.getString(
439                 R.string.accessibility_tutorial_dialog_title_button);
440         final String expectedInstruction = mContext.getString(
441                 R.string.accessibility_tutorial_dialog_message_floating_button);
442 
443         final AlertDialog alertDialog =
444                 createAccessibilityTutorialDialog(
445                         mContext, mShortcutTypes, FAKE_FEATURE_NAME);
446         alertDialog.show();
447         ShadowLooper.idleMainLooper();
448 
449         verifyTutorialTitleAndInstruction(
450                 alertDialog,
451                 expectedTitle,
452                 expectedInstruction);
453     }
454 
455     @Test
createAccessibilityTutorialDialog_navA11yButtonShortcut_verifyText()456     public void createAccessibilityTutorialDialog_navA11yButtonShortcut_verifyText() {
457         mShortcutTypes |= UserShortcutType.SOFTWARE;
458         AccessibilityTestUtils.setSoftwareShortcutMode(
459                 mContext, /* gestureNavEnabled= */ false, /* floatingButtonEnabled= */ false);
460         final String expectedTitle = mContext.getString(
461                 R.string.accessibility_tutorial_dialog_title_button);
462         final String expectedInstruction = mContext.getString(
463                 R.string.accessibility_tutorial_dialog_message_button);
464 
465         final AlertDialog alertDialog =
466                 createAccessibilityTutorialDialog(
467                         mContext, mShortcutTypes, FAKE_FEATURE_NAME);
468         alertDialog.show();
469         ShadowLooper.idleMainLooper();
470 
471         verifyTutorialTitleAndInstruction(
472                 alertDialog,
473                 expectedTitle,
474                 expectedInstruction);
475     }
476 
477     @Test
createAccessibilityTutorialDialog_gestureShortcut_talkbackOn_verifyText()478     public void createAccessibilityTutorialDialog_gestureShortcut_talkbackOn_verifyText() {
479         mShortcutTypes |= UserShortcutType.SOFTWARE;
480         setTouchExplorationEnabled(true);
481         AccessibilityTestUtils.setSoftwareShortcutMode(
482                 mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ false);
483         final String expectedTitle = mContext.getString(
484                 R.string.accessibility_tutorial_dialog_title_gesture);
485         final String expectedInstruction = StringUtil.getIcuPluralsString(
486                 mContext,
487                 /* count= */ 3,
488                 R.string.accessibility_tutorial_dialog_gesture_shortcut_instruction);
489 
490         final AlertDialog alertDialog =
491                 createAccessibilityTutorialDialog(
492                         mContext, mShortcutTypes, FAKE_FEATURE_NAME);
493         alertDialog.show();
494         ShadowLooper.idleMainLooper();
495 
496         verifyTutorialTitleAndInstruction(
497                 alertDialog,
498                 expectedTitle,
499                 expectedInstruction);
500     }
501 
502     @Test
createAccessibilityTutorialDialog_gestureShortcut_talkbackOff_verifyText()503     public void createAccessibilityTutorialDialog_gestureShortcut_talkbackOff_verifyText() {
504         mShortcutTypes |= UserShortcutType.SOFTWARE;
505         setTouchExplorationEnabled(false);
506         AccessibilityTestUtils.setSoftwareShortcutMode(
507                 mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ false);
508         final String expectedTitle = mContext.getString(
509                 R.string.accessibility_tutorial_dialog_title_gesture);
510         final String expectedInstruction = StringUtil.getIcuPluralsString(
511                 mContext,
512                 /* count= */ 2,
513                 R.string.accessibility_tutorial_dialog_gesture_shortcut_instruction);
514 
515         final AlertDialog alertDialog =
516                 createAccessibilityTutorialDialog(
517                         mContext, mShortcutTypes, FAKE_FEATURE_NAME);
518         alertDialog.show();
519         ShadowLooper.idleMainLooper();
520 
521         verifyTutorialTitleAndInstruction(
522                 alertDialog,
523                 expectedTitle,
524                 expectedInstruction);
525     }
526 
527     @Test
performClickOnPositiveButton_turnOnSoftwareShortcut_dismiss()528     public void performClickOnPositiveButton_turnOnSoftwareShortcut_dismiss() {
529         mShortcutTypes |= UserShortcutType.SOFTWARE;
530         final AlertDialog alertDialog =
531                 createAccessibilityTutorialDialog(mContext, mShortcutTypes, FAKE_FEATURE_NAME);
532         alertDialog.show();
533         ShadowLooper.idleMainLooper();
534 
535         alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick();
536         ShadowLooper.idleMainLooper();
537 
538         assertThat(alertDialog.isShowing()).isFalse();
539     }
540 
541     @Test
performClickOnPositiveButton_turnOnSoftwareShortcut_callOnClickListener()542     public void performClickOnPositiveButton_turnOnSoftwareShortcut_callOnClickListener() {
543         mShortcutTypes |= UserShortcutType.SOFTWARE;
544         final AlertDialog alertDialog =
545                 createAccessibilityTutorialDialog(
546                         mContext, mShortcutTypes, mOnClickListener, FAKE_FEATURE_NAME);
547         alertDialog.show();
548         ShadowLooper.idleMainLooper();
549 
550         alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick();
551         ShadowLooper.idleMainLooper();
552 
553         verify(mOnClickListener).onClick(alertDialog, DialogInterface.BUTTON_POSITIVE);
554     }
555 
556     @Test
performClickOnNegativeButton_turnOnSoftwareShortcut_directToSettingsPage()557     public void performClickOnNegativeButton_turnOnSoftwareShortcut_directToSettingsPage() {
558         mShortcutTypes |= UserShortcutType.SOFTWARE;
559         Activity activity = Robolectric.buildActivity(Activity.class).create().get();
560         final AlertDialog alertDialog =
561                 createAccessibilityTutorialDialog(activity, mShortcutTypes, FAKE_FEATURE_NAME);
562         alertDialog.show();
563 
564         alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).performClick();
565         ShadowLooper.idleMainLooper();
566 
567         final Intent intent = shadowOf(activity).peekNextStartedActivity();
568         assertThat(intent.getComponent().getClassName()).isEqualTo(SubSettings.class.getName());
569         assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
570                 .isEqualTo(AccessibilityButtonFragment.class.getName());
571         assertThat(intent.getIntExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, -1))
572                 .isEqualTo(SettingsEnums.SWITCH_SHORTCUT_DIALOG_ACCESSIBILITY_BUTTON_SETTINGS);
573     }
574 
575     @Test
performClickOnPositiveButton_turnOnGestureShortcut_callOnDismissListener()576     public void performClickOnPositiveButton_turnOnGestureShortcut_callOnDismissListener() {
577         final AlertDialog alertDialog =
578                 showGestureNavigationTutorialDialog(mContext, mOnDismissListener);
579 
580         alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick();
581         ShadowLooper.idleMainLooper();
582 
583         assertThat(alertDialog.isShowing()).isFalse();
584         verify(mOnDismissListener).onDismiss(alertDialog);
585     }
586 
setTouchExplorationEnabled(boolean enable)587     private void setTouchExplorationEnabled(boolean enable) {
588         ShadowAccessibilityManager am = shadowOf(
589                 mContext.getSystemService(AccessibilityManager.class));
590         am.setTouchExplorationEnabled(enable);
591     }
592 
verifyTutorialTitleAndInstruction(AlertDialog alertDialog, String expectedTitle, String expectedInstruction)593     private void verifyTutorialTitleAndInstruction(AlertDialog alertDialog, String expectedTitle,
594             String expectedInstruction) {
595         TextSwitcher titleView = alertDialog.findViewById(R.id.title);
596         assertThat(titleView).isNotNull();
597         assertThat(((TextView) titleView.getCurrentView()).getText().toString()).isEqualTo(
598                 expectedTitle);
599         TextSwitcher instructionView = alertDialog.findViewById(R.id.instruction);
600         assertThat(instructionView).isNotNull();
601         assertThat(((TextView) instructionView.getCurrentView()).getText().toString()).isEqualTo(
602                 expectedInstruction);
603     }
604 }
605