diff --git a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java index b083aefee0b..8bef7086817 100644 --- a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java +++ b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java @@ -27,6 +27,7 @@ import android.provider.SearchIndexableResource; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; +import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.dashboard.DashboardFragment; @@ -43,16 +44,17 @@ import java.util.List; /** * The fragment for on-screen keyboard settings which used to display user installed IMEs. - * - * TODO(b/207452897): Add test for AvailableVirtualKeyboardFragment */ @SearchIndexable -public final class AvailableVirtualKeyboardFragment extends DashboardFragment +public class AvailableVirtualKeyboardFragment extends DashboardFragment implements InputMethodPreference.OnSavePreferenceListener { private static final String TAG = "AvailableVirtualKeyboardFragment"; - private final ArrayList mInputMethodPreferenceList = new ArrayList<>(); - private InputMethodSettingValuesWrapper mInputMethodSettingValues; + @VisibleForTesting + final ArrayList mInputMethodPreferenceList = new ArrayList<>(); + + @VisibleForTesting + InputMethodSettingValuesWrapper mInputMethodSettingValues; private Context mUserAwareContext; private int mUserId; @@ -118,7 +120,8 @@ public final class AvailableVirtualKeyboardFragment extends DashboardFragment return SettingsEnums.ENABLE_VIRTUAL_KEYBOARDS; } - private void updateInputMethodPreferenceViews() { + @VisibleForTesting + void updateInputMethodPreferenceViews() { mInputMethodSettingValues.refreshAllInputMethodAndSubtypes(); // Clear existing "InputMethodPreference"s mInputMethodPreferenceList.clear(); diff --git a/tests/robotests/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragmentTest.java b/tests/robotests/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragmentTest.java new file mode 100644 index 00000000000..c6c6a66b986 --- /dev/null +++ b/tests/robotests/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragmentTest.java @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.inputmethod; + +import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.EXTRA_PROFILE; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.os.Bundle; +import android.provider.SearchIndexableResource; +import android.view.inputmethod.InputMethodInfo; +import android.view.inputmethod.InputMethodManager; +import android.view.inputmethod.InputMethodSubtype; + +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.dashboard.profileselector.ProfileSelectFragment; +import com.android.settings.testutils.shadow.ShadowInputMethodManagerWithMethodList; +import com.android.settings.testutils.shadow.ShadowSecureSettings; +import com.android.settingslib.inputmethod.InputMethodPreference; +import com.android.settingslib.inputmethod.InputMethodSettingValuesWrapper; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; +import org.robolectric.util.ReflectionHelpers; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +@Config(shadows = { + ShadowSecureSettings.class, + ShadowInputMethodManagerWithMethodList.class +}) +public class AvailableVirtualKeyboardFragmentTest { + + @Mock + private InputMethodManager mInputMethodManager; + @Mock + private InputMethodSettingValuesWrapper mValuesWrapper; + @Mock + private PreferenceScreen mPreferenceScreen; + @Mock + private PreferenceManager mPreferenceManager; + @Mock + private InputMethodPreference mInputMethodPreference; + private Context mContext; + private AvailableVirtualKeyboardFragment mFragment; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + initFragment(); + initMock(); + } + + @Test + public void onCreatePreferences_shouldAddResource() { + mFragment.onAttach(mContext); + + mFragment.onCreatePreferences(new Bundle(), "test"); + + verify(mFragment).addPreferencesFromResource(R.xml.available_virtual_keyboard); + } + + @Test + public void onResume_refreshAllInputMethodAndSubtypes() { + mFragment.onAttach(mContext); + + mFragment.onResume(); + + // One invocation is in onResume(), another is in updateInputMethodPreferenceViews(). + verify(mValuesWrapper, times(2)).refreshAllInputMethodAndSubtypes(); + } + + @Test + public void onResume_updateInputMethodPreferenceViews() { + mFragment.onAttach(mContext); + + mFragment.onResume(); + + verify(mFragment).updateInputMethodPreferenceViews(); + } + + @Test + public void onSaveInputMethodPreference_refreshAllInputMethodAndSubtypes() { + mFragment.onAttach(mContext); + + mFragment.onSaveInputMethodPreference(mInputMethodPreference); + + verify(mValuesWrapper).refreshAllInputMethodAndSubtypes(); + } + + @Test + public void updateInputMethodPreferenceViews_callsExpectedMethods() { + mFragment.onAttach(mContext); + + mFragment.updateInputMethodPreferenceViews(); + + verify(mValuesWrapper).getInputMethodList(); + verify(mInputMethodManager).getEnabledInputMethodListAsUser(anyInt()); + } + + @Test + public void updateInputMethodPreferenceViews_addExpectedInputMethodPreference() { + final int inputMethodNums = 5; + mFragment.onAttach(mContext); + when(mValuesWrapper.getInputMethodList()).thenReturn(createFakeInputMethodInfoList( + "test", inputMethodNums)); + + mFragment.updateInputMethodPreferenceViews(); + + assertThat(mFragment.mInputMethodPreferenceList).hasSize(inputMethodNums); + } + + @Test + public void searchIndexProvider_shouldIndexResource() { + final List indexRes = + AvailableVirtualKeyboardFragment.SEARCH_INDEX_DATA_PROVIDER + .getXmlResourcesToIndex(RuntimeEnvironment.application, true /* enabled */); + + assertThat(indexRes).isNotNull(); + assertThat(indexRes.get(0).xmlResId).isEqualTo(mFragment.getPreferenceScreenResId()); + } + + private void initFragment() { + final Bundle bundle = new Bundle(); + bundle.putInt(EXTRA_PROFILE, ProfileSelectFragment.ProfileType.PERSONAL); + mFragment = spy(new AvailableVirtualKeyboardFragment()); + mFragment.setArguments(bundle); + mFragment.mInputMethodSettingValues = mValuesWrapper; + ReflectionHelpers.setField(mFragment, "mPreferenceManager", mPreferenceManager); + } + + private void initMock() { + when(mFragment.getContext()).thenReturn(mContext); + when(mFragment.getPreferenceScreen()).thenReturn(mPreferenceScreen); + when(mPreferenceManager.getContext()).thenReturn(mContext); + when(mContext.getSystemService(InputMethodManager.class)).thenReturn(mInputMethodManager); + } + + private List createFakeInputMethodInfoList(final String name, int num) { + List subtypes = new ArrayList<>(); + + subtypes.add(new InputMethodSubtype.InputMethodSubtypeBuilder() + .build()); + subtypes.add(new InputMethodSubtype.InputMethodSubtypeBuilder() + .build()); + + final ResolveInfo resolveInfo = new ResolveInfo(); + resolveInfo.serviceInfo = new ServiceInfo(); + resolveInfo.serviceInfo.packageName = "com.android.ime"; + resolveInfo.serviceInfo.name = name; + resolveInfo.serviceInfo.applicationInfo = new ApplicationInfo(); + resolveInfo.serviceInfo.applicationInfo.enabled = true; + + List inputMethodInfoList = new ArrayList<>(); + for (int i = 0; i < num; i++) { + inputMethodInfoList.add(new InputMethodInfo( + resolveInfo, + false /* isAuxIme */, + "TestSettingsActivity", + subtypes, + 0 /* isDefaultResId */, + true /* forceDefault */)); + } + return inputMethodInfoList; + } +}