1 /*
2  * Copyright (C) 2019 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.tts;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.ArgumentMatchers.any;
22 import static org.mockito.Mockito.doReturn;
23 import static org.mockito.Mockito.mock;
24 import static org.mockito.Mockito.spy;
25 import static org.mockito.Mockito.verify;
26 import static org.mockito.Mockito.when;
27 import static org.robolectric.Shadows.shadowOf;
28 
29 import android.content.Context;
30 import android.content.Intent;
31 import android.content.pm.PackageManager;
32 import android.content.pm.ResolveInfo;
33 import android.content.pm.ServiceInfo;
34 import android.os.Bundle;
35 import android.os.Looper;
36 import android.speech.tts.TextToSpeech;
37 import android.speech.tts.TtsEngines;
38 
39 import com.android.settings.testutils.shadow.ShadowTtsEngines;
40 
41 import org.junit.After;
42 import org.junit.Before;
43 import org.junit.Test;
44 import org.junit.runner.RunWith;
45 import org.robolectric.RobolectricTestRunner;
46 import org.robolectric.RuntimeEnvironment;
47 import org.robolectric.annotation.Config;
48 import org.robolectric.annotation.Implements;
49 import org.robolectric.shadow.api.Shadow;
50 import org.robolectric.shadows.ShadowPackageManager;
51 import org.robolectric.shadows.androidx.fragment.FragmentController;
52 
53 @RunWith(RobolectricTestRunner.class)
54 public class TtsEnginePreferenceFragmentTest {
55 
56     @Implements(TextToSpeech.class)
57     public static class NoOpShadowTextToSpeech {}
58 
59     private Context mContext;
60     private TtsEnginePreferenceFragment mTtsEnginePreferenceFragment;
61 
62     @Before
setUp()63     public void setUp() {
64         mContext = RuntimeEnvironment.systemContext;
65 
66         final ResolveInfo info = new ResolveInfo();
67         final ServiceInfo serviceInfo = spy(new ServiceInfo());
68         serviceInfo.packageName = mContext.getPackageName();
69         serviceInfo.name = mContext.getClass().getName();
70         info.serviceInfo = serviceInfo;
71         doReturn("title").when(serviceInfo).loadLabel(any(PackageManager.class));
72         doReturn(1).when(serviceInfo).getIconResource();
73 
74         final ShadowPackageManager spm = Shadow.extract(mContext.getPackageManager());
75         spm.addResolveInfoForIntent(
76                 new Intent(TextToSpeech.Engine.INTENT_ACTION_TTS_SERVICE), info);
77     }
78 
79     @After
tearDown()80     public void tearDown() {
81         ShadowTtsEngines.reset();
82     }
83 
84     @Test
85     @Config(shadows = {NoOpShadowTextToSpeech.class})
getCandidates_AddEngines_returnCorrectEngines()86     public void getCandidates_AddEngines_returnCorrectEngines() {
87         mTtsEnginePreferenceFragment = FragmentController.of(new TtsEnginePreferenceFragment(),
88                 new Bundle())
89                 .create()
90                 .get();
91         shadowOf(Looper.getMainLooper()).idle();
92 
93         assertThat(mTtsEnginePreferenceFragment.getCandidates().size()).isEqualTo(1);
94     }
95 
96     @Test
97     @Config(shadows = {ShadowTtsEngines.class, NoOpShadowTextToSpeech.class})
getDefaultKey_validKey_returnCorrectKey()98     public void getDefaultKey_validKey_returnCorrectKey() {
99         final String TEST_ENGINE = "test_engine";
100         final TtsEngines engine = mock(TtsEngines.class);
101         ShadowTtsEngines.setInstance(engine);
102         mTtsEnginePreferenceFragment = FragmentController.of(new TtsEnginePreferenceFragment(),
103                 new Bundle())
104                 .create()
105                 .get();
106         shadowOf(Looper.getMainLooper()).idle();
107         when(engine.getDefaultEngine()).thenReturn(TEST_ENGINE);
108 
109         assertThat(mTtsEnginePreferenceFragment.getDefaultKey()).isEqualTo(TEST_ENGINE);
110     }
111 
112     @Test
113     @Config(shadows = {ShadowTtsEngines.class, NoOpShadowTextToSpeech.class})
setDefaultKey_validKey_callingTtsEngineFunction()114     public void setDefaultKey_validKey_callingTtsEngineFunction() {
115         final TtsEngines engine = mock(TtsEngines.class);
116         ShadowTtsEngines.setInstance(engine);
117         mTtsEnginePreferenceFragment = FragmentController.of(new TtsEnginePreferenceFragment(),
118                 new Bundle())
119                 .create()
120                 .get();
121         shadowOf(Looper.getMainLooper()).idle();
122 
123         mTtsEnginePreferenceFragment.setDefaultKey(mContext.getPackageName());
124 
125         verify(engine).isEngineInstalled(mContext.getPackageName());
126     }
127 
128     @Test
129     @Config(shadows = {NoOpShadowTextToSpeech.class})
setDefaultKey_validKey_updateCheckedState()130     public void setDefaultKey_validKey_updateCheckedState() {
131         mTtsEnginePreferenceFragment = FragmentController.of(new TtsEnginePreferenceFragment(),
132                 new Bundle())
133                 .create()
134                 .get();
135         shadowOf(Looper.getMainLooper()).idle();
136         TtsEnginePreferenceFragment fragmentSpy = spy(mTtsEnginePreferenceFragment);
137 
138         fragmentSpy.setDefaultKey(mContext.getPackageName());
139 
140         verify(fragmentSpy).updateCheckedState(mContext.getPackageName());
141     }
142 }
143