Home | History | Annotate | Download | only in appinfo
      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.applications.appinfo;
     18 
     19 import static com.google.common.truth.Truth.assertThat;
     20 import static org.mockito.ArgumentMatchers.any;
     21 import static org.mockito.ArgumentMatchers.anyInt;
     22 import static org.mockito.ArgumentMatchers.argThat;
     23 import static org.mockito.ArgumentMatchers.eq;
     24 import static org.mockito.Mockito.mock;
     25 import static org.mockito.Mockito.never;
     26 import static org.mockito.Mockito.spy;
     27 import static org.mockito.Mockito.verify;
     28 import static org.mockito.Mockito.when;
     29 
     30 import android.content.ComponentName;
     31 import android.content.Context;
     32 import android.content.DialogInterface;
     33 import android.content.Intent;
     34 import android.content.pm.ActivityInfo;
     35 import android.content.pm.ApplicationInfo;
     36 import android.content.pm.PackageInfo;
     37 import android.content.pm.PackageManager;
     38 import android.content.pm.ResolveInfo;
     39 import android.support.v7.preference.PreferenceManager;
     40 import android.support.v7.preference.PreferenceScreen;
     41 import android.text.TextUtils;
     42 import android.view.Menu;
     43 import android.view.MenuItem;
     44 import android.view.View;
     45 import android.widget.Button;
     46 
     47 import com.android.settings.R;
     48 import com.android.settings.applications.LayoutPreference;
     49 import com.android.settings.core.BasePreferenceController;
     50 import com.android.settings.testutils.SettingsRobolectricTestRunner;
     51 import com.android.settingslib.applications.AppUtils;
     52 import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
     53 import com.android.settingslib.wrapper.PackageManagerWrapper;
     54 
     55 import org.junit.Before;
     56 import org.junit.Test;
     57 import org.junit.runner.RunWith;
     58 import org.mockito.Mock;
     59 import org.mockito.MockitoAnnotations;
     60 import org.robolectric.RuntimeEnvironment;
     61 import org.robolectric.util.ReflectionHelpers;
     62 
     63 @RunWith(SettingsRobolectricTestRunner.class)
     64 public class InstantAppButtonsPreferenceControllerTest {
     65 
     66     private static final String TEST_INSTALLER_PACKAGE_NAME = "com.installer";
     67     private static final String TEST_INSTALLER_ACTIVITY_NAME = "com.installer.InstallerActivity";
     68     private static final String TEST_AIA_PACKAGE_NAME = "test.aia.package";
     69 
     70     @Mock
     71     private PackageManager mPackageManager;
     72     @Mock
     73     private ApplicationInfo mAppInfo;
     74     @Mock
     75     private AppInfoDashboardFragment mFragment;
     76     @Mock
     77     private LayoutPreference mPreference;
     78 
     79     private Context mContext;
     80     private PreferenceScreen mScreen;
     81     private PreferenceManager mPreferenceManager;
     82     private Button mLaunchButton;
     83     private Button mInstallButton;
     84     private Button mClearAppButton;
     85     private InstantAppButtonsPreferenceController mController;
     86 
     87     @Before
     88     public void setUp() throws PackageManager.NameNotFoundException {
     89         MockitoAnnotations.initMocks(this);
     90         mContext = spy(RuntimeEnvironment.application);
     91         when(mContext.getPackageManager()).thenReturn(mPackageManager);
     92         final PackageInfo packageInfo = mock(PackageInfo.class);
     93         packageInfo.applicationInfo = mAppInfo;
     94         when(mFragment.getPackageInfo()).thenReturn(packageInfo);
     95         mPreferenceManager = new PreferenceManager(mContext);
     96         mScreen = mPreferenceManager.createPreferenceScreen(mContext);
     97         when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager);
     98         final View buttons = View.inflate(
     99             RuntimeEnvironment.application, R.layout.instant_app_buttons, null /* parent */);
    100         mLaunchButton = buttons.findViewById(R.id.launch);
    101         mInstallButton = buttons.findViewById(R.id.install);
    102         mClearAppButton = buttons.findViewById(R.id.clear_data);
    103         mController = spy(new InstantAppButtonsPreferenceController(
    104             mContext, mFragment, TEST_AIA_PACKAGE_NAME, null /* lifecycle */));
    105         when(mPreference.getKey()).thenReturn("instant_app_buttons");
    106         mScreen.addPreference(mPreference);
    107         when(mPreference.findViewById(R.id.instant_app_button_container)).thenReturn(buttons);
    108     }
    109 
    110     @Test
    111     public void getAvailabilityStatus_notInstantApp_shouldReturnDisabled() {
    112         ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
    113                 (InstantAppDataProvider) (i -> false));
    114 
    115         assertThat(mController.getAvailabilityStatus())
    116             .isEqualTo(BasePreferenceController.DISABLED_FOR_USER);
    117     }
    118 
    119     @Test
    120     public void getAvailabilityStatus_isInstantApp_shouldReturnAvailable() {
    121         ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
    122                 (InstantAppDataProvider) (i -> true));
    123 
    124         assertThat(mController.getAvailabilityStatus())
    125             .isEqualTo(BasePreferenceController.AVAILABLE);
    126     }
    127 
    128     @Test
    129     public void onCreateOptionsMenu_noLaunchUri_shouldNotAddInstallInstantAppMenu() {
    130         final Menu menu = mock(Menu.class);
    131         when(menu.add(anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(mock(MenuItem.class));
    132 
    133         mController.onCreateOptionsMenu(menu, null /* inflater */);
    134 
    135         verify(menu, never()).add(anyInt(), eq(AppInfoDashboardFragment.INSTALL_INSTANT_APP_MENU),
    136             anyInt(), eq(R.string.install_text));
    137     }
    138 
    139     @Test
    140     public void onCreateOptionsMenu_hasLaunchUri_shouldAddForceStop() {
    141         ReflectionHelpers.setField(mController, "mLaunchUri", "www.test.launch");
    142         final Menu menu = mock(Menu.class);
    143         when(menu.add(anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(mock(MenuItem.class));
    144 
    145         mController.onCreateOptionsMenu(menu, null /* inflater */);
    146 
    147         verify(menu).add(anyInt(), eq(AppInfoDashboardFragment.INSTALL_INSTANT_APP_MENU),
    148             anyInt(), eq(R.string.install_text));
    149     }
    150 
    151     @Test
    152     public void onPrepareOptionsMenu_noAppStoreLink_shoulDisableInstallInstantAppMenu() {
    153         ReflectionHelpers.setField(mController, "mLaunchUri", "www.test.launch");
    154         final Menu menu = mock(Menu.class);
    155         final MenuItem menuItem = mock(MenuItem.class);
    156         when(menu.findItem(AppInfoDashboardFragment.INSTALL_INSTANT_APP_MENU)).thenReturn(menuItem);
    157 
    158         mController.onPrepareOptionsMenu(menu);
    159 
    160         verify(menuItem).setEnabled(false);
    161     }
    162 
    163     @Test
    164     public void onPrepareOptionsMenu_hasAppStoreLink_shoulNotDisableInstallInstantAppMenu() {
    165         ReflectionHelpers.setField(mController, "mLaunchUri", "www.test.launch");
    166         final ResolveInfo resolveInfo = mock(ResolveInfo.class);
    167         final ActivityInfo activityInfo = mock(ActivityInfo.class);
    168         resolveInfo.activityInfo = activityInfo;
    169         activityInfo.packageName = TEST_INSTALLER_PACKAGE_NAME;
    170         activityInfo.name = TEST_INSTALLER_ACTIVITY_NAME;
    171         when(mPackageManager.resolveActivity(any(), anyInt())).thenReturn(resolveInfo);
    172         final Menu menu = mock(Menu.class);
    173         final MenuItem menuItem = mock(MenuItem.class);
    174         when(menu.findItem(AppInfoDashboardFragment.INSTALL_INSTANT_APP_MENU)).thenReturn(menuItem);
    175 
    176         mController.onPrepareOptionsMenu(menu);
    177 
    178         verify(menuItem, never()).setEnabled(false);
    179     }
    180 
    181     @Test
    182     public void onPrepareOptionsMenu_installMenuNotFound_shoulNotCrash() {
    183         final Menu menu = mock(Menu.class);
    184 
    185         mController.onPrepareOptionsMenu(menu);
    186 
    187         // no crash
    188     }
    189 
    190     @Test
    191     public void onOptionsItemSelected_shouldOpenAppStore() {
    192         final ResolveInfo resolveInfo = mock(ResolveInfo.class);
    193         final ActivityInfo activityInfo = mock(ActivityInfo.class);
    194         resolveInfo.activityInfo = activityInfo;
    195         activityInfo.packageName = TEST_INSTALLER_PACKAGE_NAME;
    196         activityInfo.name = TEST_INSTALLER_ACTIVITY_NAME;
    197         when(mPackageManager.resolveActivity(any(), anyInt())).thenReturn(resolveInfo);
    198         mController.displayPreference(mScreen);
    199         final ComponentName componentName =
    200             new ComponentName(TEST_INSTALLER_PACKAGE_NAME, TEST_INSTALLER_ACTIVITY_NAME);
    201         final MenuItem menu = mock(MenuItem.class);
    202         when(menu.getItemId()).thenReturn(AppInfoDashboardFragment.INSTALL_INSTANT_APP_MENU);
    203 
    204         mController.onOptionsItemSelected(menu);
    205 
    206         verify(mFragment).startActivity(argThat(intent-> intent != null
    207             && intent.getAction().equals(Intent.ACTION_SHOW_APP_INFO)
    208             && intent.getComponent().equals(componentName)));
    209     }
    210 
    211     @Test
    212     public void displayPreference_noLaunchUri_shouldShowHideLaunchButton() {
    213         mController.displayPreference(mScreen);
    214 
    215         assertThat(mLaunchButton.getVisibility()).isEqualTo(View.GONE);
    216     }
    217 
    218     @Test
    219     public void displayPreference_hasLaunchUri_shouldShowHideInstallButton() {
    220         ReflectionHelpers.setField(mController, "mLaunchUri", "www.test.launch");
    221 
    222         mController.displayPreference(mScreen);
    223 
    224         assertThat(mInstallButton.getVisibility()).isEqualTo(View.GONE);
    225     }
    226 
    227     @Test
    228     public void displayPreference_noAppStoreLink_shoulDisableInstallButton() {
    229         mController.displayPreference(mScreen);
    230 
    231         assertThat(mInstallButton.isEnabled()).isFalse();
    232     }
    233 
    234     @Test
    235     public void displayPreference_hasAppStoreLink_shoulSetClickListenerForInstallButton() {
    236         final ResolveInfo resolveInfo = mock(ResolveInfo.class);
    237         final ActivityInfo activityInfo = mock(ActivityInfo.class);
    238         resolveInfo.activityInfo = activityInfo;
    239         activityInfo.packageName = TEST_INSTALLER_PACKAGE_NAME;
    240         activityInfo.name = TEST_INSTALLER_ACTIVITY_NAME;
    241         when(mPackageManager.resolveActivity(any(), anyInt())).thenReturn(resolveInfo);
    242 
    243         mController.displayPreference(mScreen);
    244 
    245         assertThat(mInstallButton.hasOnClickListeners()).isTrue();
    246     }
    247 
    248     @Test
    249     public void displayPreference_shoulSetClickListenerForClearButton() {
    250         mController.displayPreference(mScreen);
    251 
    252         assertThat(mClearAppButton.hasOnClickListeners()).isTrue();
    253     }
    254 
    255     @Test
    256     public void clickLaunchButton_shouldLaunchViewIntent() {
    257         final String launchUri = "www.test.launch";
    258         ReflectionHelpers.setField(mController, "mLaunchUri", launchUri);
    259         mController.displayPreference(mScreen);
    260 
    261         mLaunchButton.callOnClick();
    262 
    263         verify(mFragment).startActivity(argThat(intent-> intent != null
    264             && intent.getAction().equals(Intent.ACTION_VIEW)
    265             && intent.hasCategory(Intent.CATEGORY_BROWSABLE)
    266             && (intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0
    267             && TextUtils.equals(intent.getPackage(), TEST_AIA_PACKAGE_NAME)
    268             && TextUtils.equals(intent.getDataString(), launchUri)));
    269     }
    270 
    271     @Test
    272     public void clickInstallButton_shouldOpenAppStore() {
    273         final ResolveInfo resolveInfo = mock(ResolveInfo.class);
    274         final ActivityInfo activityInfo = mock(ActivityInfo.class);
    275         resolveInfo.activityInfo = activityInfo;
    276         activityInfo.packageName = TEST_INSTALLER_PACKAGE_NAME;
    277         activityInfo.name = TEST_INSTALLER_ACTIVITY_NAME;
    278         when(mPackageManager.resolveActivity(any(), anyInt())).thenReturn(resolveInfo);
    279         mController.displayPreference(mScreen);
    280         final ComponentName componentName =
    281             new ComponentName(TEST_INSTALLER_PACKAGE_NAME, TEST_INSTALLER_ACTIVITY_NAME);
    282 
    283         mInstallButton.callOnClick();
    284 
    285         verify(mFragment).startActivity(argThat(intent-> intent != null
    286             && intent.getAction().equals(Intent.ACTION_SHOW_APP_INFO)
    287             && intent.getComponent().equals(componentName)));
    288     }
    289 
    290     @Test
    291     public void onClick_shouldDeleteApp() {
    292         PackageManagerWrapper packageManagerWrapper = mock(PackageManagerWrapper.class);
    293         ReflectionHelpers.setField(mController, "mPackageManagerWrapper", packageManagerWrapper);
    294 
    295         mController.onClick(mock(DialogInterface.class), DialogInterface.BUTTON_POSITIVE);
    296 
    297         verify(packageManagerWrapper)
    298             .deletePackageAsUser(eq(TEST_AIA_PACKAGE_NAME), any(), anyInt(),anyInt());
    299     }
    300 }
    301