1 /*
2  * Copyright (C) 2024 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.systemui.inputmethod.data.repository
18 
19 import android.os.UserHandle
20 import android.view.inputmethod.InputMethodInfo
21 import android.view.inputmethod.InputMethodManager
22 import android.view.inputmethod.InputMethodSubtype
23 import androidx.test.ext.junit.runners.AndroidJUnit4
24 import androidx.test.filters.SmallTest
25 import com.android.systemui.SysuiTestCase
26 import com.android.systemui.kosmos.Kosmos
27 import com.android.systemui.kosmos.testDispatcher
28 import com.android.systemui.kosmos.testScope
29 import com.android.systemui.util.mockito.any
30 import com.android.systemui.util.mockito.eq
31 import com.android.systemui.util.mockito.mock
32 import com.android.systemui.util.mockito.whenever
33 import com.google.common.truth.Truth.assertThat
34 import kotlinx.coroutines.flow.count
35 import kotlinx.coroutines.test.runTest
36 import org.junit.Before
37 import org.junit.Test
38 import org.junit.runner.RunWith
39 import org.mockito.ArgumentMatchers.anyBoolean
40 import org.mockito.Mock
41 import org.mockito.Mockito.verify
42 import org.mockito.MockitoAnnotations
43 
44 @SmallTest
45 @RunWith(AndroidJUnit4::class)
46 class InputMethodRepositoryTest : SysuiTestCase() {
47 
48     @Mock private lateinit var inputMethodManager: InputMethodManager
49 
50     private val kosmos = Kosmos()
51     private val testScope = kosmos.testScope
52 
53     private lateinit var underTest: InputMethodRepository
54 
55     @Before
setUpnull56     fun setUp() {
57         MockitoAnnotations.initMocks(this)
58 
59         underTest =
60             InputMethodRepositoryImpl(
61                 backgroundDispatcher = kosmos.testDispatcher,
62                 inputMethodManager = inputMethodManager,
63             )
64     }
65 
66     @Test
enabledInputMethods_noImes_emptyFlownull67     fun enabledInputMethods_noImes_emptyFlow() =
68         testScope.runTest {
69             whenever(inputMethodManager.getEnabledInputMethodListAsUser(eq(USER_HANDLE)))
70                 .thenReturn(listOf())
71             whenever(
72                     inputMethodManager.getEnabledInputMethodSubtypeListAsUser(
73                         any(),
74                         anyBoolean(),
75                         eq(USER_HANDLE)
76                     )
77                 )
78                 .thenReturn(listOf())
79 
80             assertThat(underTest.enabledInputMethods(USER_HANDLE, fetchSubtypes = true).count())
81                 .isEqualTo(0)
82         }
83 
84     @Test
selectedInputMethodSubtypes_returnsSubtypeListnull85     fun selectedInputMethodSubtypes_returnsSubtypeList() =
86         testScope.runTest {
87             val subtypeId = 123
88             val isAuxiliary = true
89             val selectedImiId = "imiId"
90             val selectedImi = mock<InputMethodInfo>()
91             whenever(selectedImi.id).thenReturn(selectedImiId)
92             whenever(inputMethodManager.getCurrentInputMethodInfoAsUser(eq(USER_HANDLE)))
93                 .thenReturn(selectedImi)
94             whenever(inputMethodManager.getEnabledInputMethodListAsUser(eq(USER_HANDLE)))
95                 .thenReturn(listOf(selectedImi))
96             whenever(
97                     inputMethodManager.getEnabledInputMethodSubtypeListAsUser(
98                         eq(selectedImiId),
99                         anyBoolean(),
100                         eq(USER_HANDLE)
101                     )
102                 )
103                 .thenReturn(
104                     listOf(
105                         InputMethodSubtype.InputMethodSubtypeBuilder()
106                             .setSubtypeId(subtypeId)
107                             .setIsAuxiliary(isAuxiliary)
108                             .build()
109                     )
110                 )
111 
112             val result = underTest.selectedInputMethodSubtypes(USER_HANDLE)
113             assertThat(result).hasSize(1)
114             assertThat(result.first().subtypeId).isEqualTo(subtypeId)
115             assertThat(result.first().isAuxiliary).isEqualTo(isAuxiliary)
116         }
117 
118     @Test
showImePicker_forwardsDisplayIdnull119     fun showImePicker_forwardsDisplayId() =
120         testScope.runTest {
121             val displayId = 7
122 
123             underTest.showInputMethodPicker(displayId, /* showAuxiliarySubtypes= */ true)
124 
125             verify(inputMethodManager)
126                 .showInputMethodPickerFromSystem(
127                     /* showAuxiliarySubtypes = */ eq(true),
128                     /* displayId = */ eq(displayId)
129                 )
130         }
131 
132     companion object {
133         private val USER_HANDLE = UserHandle.of(100)
134     }
135 }
136