1 /* 2 * Copyright (C) 2017 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.search; 18 19 import static android.content.Context.INPUT_METHOD_SERVICE; 20 import static com.android.settings.search.InputDeviceResultLoader.PHYSICAL_KEYBOARD_FRAGMENT; 21 import static com.android.settings.search.InputDeviceResultLoader.VIRTUAL_KEYBOARD_FRAGMENT; 22 import static com.google.common.truth.Truth.assertThat; 23 import static org.mockito.Matchers.anyInt; 24 import static org.mockito.Mockito.mock; 25 import static org.mockito.Mockito.verifyZeroInteractions; 26 import static org.mockito.Mockito.when; 27 28 import android.content.Context; 29 import android.content.pm.PackageManager; 30 import android.content.pm.ServiceInfo; 31 import android.hardware.input.InputManager; 32 import android.view.InputDevice; 33 import android.view.inputmethod.InputMethodInfo; 34 import android.view.inputmethod.InputMethodManager; 35 36 import com.android.settings.R; 37 import com.android.settings.TestConfig; 38 import com.android.settings.dashboard.SiteMapManager; 39 import com.android.settings.testutils.SettingsRobolectricTestRunner; 40 import com.android.settings.testutils.shadow.ShadowInputDevice; 41 42 import org.junit.After; 43 import org.junit.Before; 44 import org.junit.Test; 45 import org.junit.runner.RunWith; 46 import org.mockito.Answers; 47 import org.mockito.Mock; 48 import org.mockito.MockitoAnnotations; 49 import org.robolectric.RuntimeEnvironment; 50 import org.robolectric.annotation.Config; 51 52 import java.util.ArrayList; 53 import java.util.List; 54 55 @RunWith(SettingsRobolectricTestRunner.class) 56 @Config(manifest = TestConfig.MANIFEST_PATH, 57 sdk = TestConfig.SDK_VERSION, 58 shadows = { 59 ShadowInputDevice.class 60 }) 61 public class InputDeviceResultLoaderTest { 62 63 private static final String QUERY = "test_query"; 64 private static final List<String> PHYSICAL_KEYBOARD_BREADCRUMB; 65 private static final List<String> VIRTUAL_KEYBOARD_BREADCRUMB; 66 67 static { 68 PHYSICAL_KEYBOARD_BREADCRUMB = new ArrayList<>(); 69 VIRTUAL_KEYBOARD_BREADCRUMB = new ArrayList<>(); 70 PHYSICAL_KEYBOARD_BREADCRUMB.add("Settings"); 71 PHYSICAL_KEYBOARD_BREADCRUMB.add("physical keyboard"); 72 VIRTUAL_KEYBOARD_BREADCRUMB.add("Settings"); 73 VIRTUAL_KEYBOARD_BREADCRUMB.add("virtual keyboard"); 74 } 75 76 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 77 private Context mContext; 78 @Mock 79 private SiteMapManager mSiteMapManager; 80 @Mock 81 private InputManager mInputManager; 82 @Mock 83 private InputMethodManager mImm; 84 @Mock 85 private PackageManager mPackageManager; 86 87 private InputDeviceResultLoader mLoader; 88 89 @Before setUp()90 public void setUp() { 91 MockitoAnnotations.initMocks(this); 92 when(mContext.getApplicationContext()).thenReturn(mContext); 93 when(mContext.getSystemService(Context.INPUT_SERVICE)) 94 .thenReturn(mInputManager); 95 when(mContext.getSystemService(INPUT_METHOD_SERVICE)) 96 .thenReturn(mImm); 97 when(mContext.getPackageManager()) 98 .thenReturn(mPackageManager); 99 when(mContext.getString(anyInt())) 100 .thenAnswer(invocation -> RuntimeEnvironment.application.getString( 101 (Integer) invocation.getArguments()[0])); 102 mLoader = new InputDeviceResultLoader(mContext, QUERY, mSiteMapManager); 103 } 104 105 @After tearDown()106 public void tearDown() { 107 ShadowInputDevice.reset(); 108 } 109 110 @Test query_noKeyboard_shouldNotReturnAnything()111 public void query_noKeyboard_shouldNotReturnAnything() { 112 assertThat(mLoader.loadInBackground()).isEmpty(); 113 } 114 115 @Test query_hasPhysicalKeyboard_match()116 public void query_hasPhysicalKeyboard_match() { 117 addPhysicalKeyboard(QUERY); 118 when(mSiteMapManager.buildBreadCrumb(mContext, PHYSICAL_KEYBOARD_FRAGMENT, 119 RuntimeEnvironment.application.getString(R.string.physical_keyboard_title))) 120 .thenReturn(PHYSICAL_KEYBOARD_BREADCRUMB); 121 122 final List<SearchResult> results = new ArrayList<>(mLoader.loadInBackground()); 123 124 assertThat(results).hasSize(1); 125 assertThat(results.get(0).title).isEqualTo(QUERY); 126 assertThat(results.get(0).breadcrumbs) 127 .containsExactlyElementsIn(PHYSICAL_KEYBOARD_BREADCRUMB); 128 } 129 130 @Test query_hasVirtualKeyboard_match()131 public void query_hasVirtualKeyboard_match() { 132 addVirtualKeyboard(QUERY); 133 when(mSiteMapManager.buildBreadCrumb(mContext, VIRTUAL_KEYBOARD_FRAGMENT, 134 RuntimeEnvironment.application.getString(R.string.add_virtual_keyboard))) 135 .thenReturn(VIRTUAL_KEYBOARD_BREADCRUMB); 136 137 final List<SearchResult> results = new ArrayList<>(mLoader.loadInBackground()); 138 assertThat(results).hasSize(1); 139 assertThat(results.get(0).title).isEqualTo(QUERY); 140 assertThat(results.get(0).breadcrumbs) 141 .containsExactlyElementsIn(VIRTUAL_KEYBOARD_BREADCRUMB); 142 } 143 144 @Test query_hasPhysicalVirtualKeyboard_doNotMatch()145 public void query_hasPhysicalVirtualKeyboard_doNotMatch() { 146 addPhysicalKeyboard("abc"); 147 addVirtualKeyboard("def"); 148 149 assertThat(mLoader.loadInBackground()).isEmpty(); 150 verifyZeroInteractions(mSiteMapManager); 151 } 152 addPhysicalKeyboard(String name)153 private void addPhysicalKeyboard(String name) { 154 final InputDevice device = mock(InputDevice.class); 155 when(device.isVirtual()).thenReturn(false); 156 when(device.isFullKeyboard()).thenReturn(true); 157 when(device.getName()).thenReturn(name); 158 ShadowInputDevice.sDeviceIds = new int[]{0}; 159 ShadowInputDevice.addDevice(0, device); 160 } 161 addVirtualKeyboard(String name)162 private void addVirtualKeyboard(String name) { 163 final List<InputMethodInfo> imis = new ArrayList<>(); 164 final InputMethodInfo info = mock(InputMethodInfo.class); 165 imis.add(info); 166 when(info.getServiceInfo()).thenReturn(new ServiceInfo()); 167 when(info.loadLabel(mPackageManager)).thenReturn(name); 168 info.getServiceInfo().packageName = "pkg"; 169 info.getServiceInfo().name = "class"; 170 when(mImm.getInputMethodList()).thenReturn(imis); 171 } 172 173 } 174