1 /* 2 * Copyright (C) 2016 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 18 package com.android.settings.search; 19 20 import static com.google.common.truth.Truth.assertThat; 21 22 import static org.mockito.Matchers.any; 23 import static org.mockito.Matchers.eq; 24 import static org.mockito.Mockito.doReturn; 25 import static org.mockito.Mockito.spy; 26 import static org.mockito.Mockito.verify; 27 import static org.mockito.Mockito.when; 28 29 import android.content.ComponentName; 30 import android.content.Context; 31 import android.content.Intent; 32 import android.content.pm.ApplicationInfo; 33 import android.content.pm.PackageManager; 34 import android.graphics.drawable.Drawable; 35 import android.os.UserHandle; 36 import android.util.Pair; 37 import android.view.LayoutInflater; 38 import android.view.View; 39 40 import com.android.internal.logging.nano.MetricsProto; 41 import com.android.settings.R; 42 import com.android.settings.SettingsRobolectricTestRunner; 43 import com.android.settings.TestConfig; 44 import com.android.settings.search2.AppSearchResult; 45 import com.android.settings.search2.IntentPayload; 46 import com.android.settings.search2.IntentSearchViewHolder; 47 import com.android.settings.search2.SearchFragment; 48 import com.android.settings.search2.SearchResult; 49 import com.android.settings.search2.SearchResult.Builder; 50 import com.android.settings.testutils.FakeFeatureFactory; 51 52 import org.junit.Before; 53 import org.junit.Test; 54 import org.junit.runner.RunWith; 55 import org.mockito.Answers; 56 import org.mockito.Mock; 57 import org.mockito.MockitoAnnotations; 58 import org.robolectric.RuntimeEnvironment; 59 import org.robolectric.annotation.Config; 60 61 import java.util.ArrayList; 62 import java.util.List; 63 64 @RunWith(SettingsRobolectricTestRunner.class) 65 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) 66 public class IntentSearchViewHolderTest { 67 68 private static final String TITLE = "title"; 69 private static final String SUMMARY = "summary"; 70 private static final int USER_ID = 10; 71 private static final String BADGED_LABEL = "work title"; 72 73 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 74 private Context mContext; 75 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 76 private SearchFragment mFragment; 77 @Mock 78 private PackageManager mPackageManager; 79 private FakeFeatureFactory mFeatureFactory; 80 private IntentSearchViewHolder mHolder; 81 private Drawable mIcon; 82 private Drawable mBadgedIcon; 83 84 @Before setUp()85 public void setUp() { 86 MockitoAnnotations.initMocks(this); 87 FakeFeatureFactory.setupForTest(mContext); 88 mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext); 89 90 final Context context = RuntimeEnvironment.application; 91 View view = LayoutInflater.from(context).inflate(R.layout.search_intent_item, null); 92 mHolder = new IntentSearchViewHolder(view); 93 94 mIcon = context.getDrawable(R.drawable.ic_search_history); 95 mBadgedIcon = context.getDrawable(R.drawable.ic_add); 96 when(mFragment.getActivity().getPackageManager()).thenReturn(mPackageManager); 97 } 98 99 @Test testConstructor_membersNotNull()100 public void testConstructor_membersNotNull() { 101 assertThat(mHolder.titleView).isNotNull(); 102 assertThat(mHolder.summaryView).isNotNull(); 103 assertThat(mHolder.iconView).isNotNull(); 104 assertThat(mHolder.breadcrumbView).isNotNull(); 105 } 106 107 @Test testBindViewElements_allUpdated()108 public void testBindViewElements_allUpdated() { 109 SearchResult result = getSearchResult(TITLE, SUMMARY, mIcon); 110 mHolder.onBind(mFragment, result); 111 mHolder.itemView.performClick(); 112 113 assertThat(mHolder.titleView.getText()).isEqualTo(TITLE); 114 assertThat(mHolder.summaryView.getText()).isEqualTo(SUMMARY); 115 assertThat(mHolder.iconView.getDrawable()).isEqualTo(mIcon); 116 assertThat(mHolder.summaryView.getVisibility()).isEqualTo(View.VISIBLE); 117 assertThat(mHolder.breadcrumbView.getVisibility()).isEqualTo(View.GONE); 118 119 verify(mFragment).onSearchResultClicked(); 120 verify(mFragment).startActivity(any(Intent.class)); 121 verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class), 122 eq(MetricsProto.MetricsEvent.ACTION_CLICK_SETTINGS_SEARCH_RESULT), 123 eq(((IntentPayload)result.payload).intent.getComponent().flattenToString()), 124 any(Pair.class)); 125 } 126 127 @Test testBindViewIcon_nullIcon_imageDrawableIsNull()128 public void testBindViewIcon_nullIcon_imageDrawableIsNull() { 129 final SearchResult result = getSearchResult(TITLE, SUMMARY, null); 130 mHolder.onBind(mFragment, result); 131 132 assertThat(mHolder.iconView.getDrawable()).isNull(); 133 } 134 135 @Test testBindViewElements_emptySummary_hideSummaryView()136 public void testBindViewElements_emptySummary_hideSummaryView() { 137 final SearchResult result = new Builder() 138 .addTitle(TITLE) 139 .addRank(1) 140 .addPayload(new IntentPayload(null)) 141 .addIcon(mIcon) 142 .build(); 143 144 mHolder.onBind(mFragment, result); 145 assertThat(mHolder.summaryView.getVisibility()).isEqualTo(View.GONE); 146 } 147 148 @Test testBindViewElements_withBreadcrumb_shouldFormatBreadcrumb()149 public void testBindViewElements_withBreadcrumb_shouldFormatBreadcrumb() { 150 final List<String> breadcrumbs = new ArrayList<>(); 151 breadcrumbs.add("a"); 152 breadcrumbs.add("b"); 153 breadcrumbs.add("c"); 154 final SearchResult result = new Builder() 155 .addTitle(TITLE) 156 .addRank(1) 157 .addPayload(new IntentPayload(null)) 158 .addBreadcrumbs(breadcrumbs) 159 .addIcon(mIcon) 160 .build(); 161 162 mHolder.onBind(mFragment, result); 163 assertThat(mHolder.breadcrumbView.getVisibility()).isEqualTo(View.VISIBLE); 164 assertThat(mHolder.breadcrumbView.getText()).isEqualTo("a > b > c"); 165 } 166 167 @Test testBindElements_placeholderSummary_visibilityIsGone()168 public void testBindElements_placeholderSummary_visibilityIsGone() { 169 String nonBreakingSpace = mContext.getString(R.string.summary_placeholder); 170 SearchResult result = new Builder() 171 .addTitle(TITLE) 172 .addSummary(nonBreakingSpace) 173 .addPayload(new IntentPayload(null)) 174 .build(); 175 176 mHolder.onBind(mFragment, result); 177 178 assertThat(mHolder.summaryView.getVisibility()).isEqualTo(View.GONE); 179 } 180 181 @Test testBindElements_dynamicSummary_visibilityIsGone()182 public void testBindElements_dynamicSummary_visibilityIsGone() { 183 String dynamicSummary = "%s"; 184 SearchResult result = new Builder() 185 .addTitle(TITLE) 186 .addSummary(dynamicSummary) 187 .addPayload(new IntentPayload(null)) 188 .build(); 189 190 mHolder.onBind(mFragment, result); 191 192 assertThat(mHolder.summaryView.getVisibility()).isEqualTo(View.GONE); 193 } 194 testBindViewElements_appSearchResult()195 public void testBindViewElements_appSearchResult() { 196 when(mPackageManager.getUserBadgedLabel(any(CharSequence.class), 197 eq(new UserHandle(USER_ID)))).thenReturn(BADGED_LABEL); 198 199 SearchResult result = getAppSearchResult( 200 TITLE, SUMMARY, mIcon, getApplicationInfo(USER_ID, TITLE, mIcon)); 201 mHolder.onBind(mFragment, result); 202 mHolder.itemView.performClick(); 203 204 assertThat(mHolder.titleView.getText()).isEqualTo(TITLE); 205 assertThat(mHolder.summaryView.getText()).isEqualTo(SUMMARY); 206 assertThat(mHolder.summaryView.getVisibility()).isEqualTo(View.VISIBLE); 207 assertThat(mHolder.breadcrumbView.getVisibility()).isEqualTo(View.GONE); 208 assertThat(mHolder.titleView.getContentDescription()).isEqualTo(BADGED_LABEL); 209 210 verify(mFragment).onSearchResultClicked(); 211 verify(mFragment.getActivity()).startActivityAsUser( 212 any(Intent.class), eq(new UserHandle(USER_ID))); 213 verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class), 214 eq(MetricsProto.MetricsEvent.ACTION_CLICK_SETTINGS_SEARCH_RESULT), 215 eq(((IntentPayload)result.payload).intent.getComponent().flattenToString()), 216 any(Pair.class)); 217 } 218 getSearchResult(String title, String summary, Drawable icon)219 private SearchResult getSearchResult(String title, String summary, Drawable icon) { 220 Builder builder = new Builder(); 221 builder.addTitle(title) 222 .addSummary(summary) 223 .addRank(1) 224 .addPayload(new IntentPayload( 225 new Intent().setComponent(new ComponentName("pkg", "class")))) 226 .addBreadcrumbs(new ArrayList<>()) 227 .addIcon(icon); 228 229 return builder.build(); 230 } 231 getAppSearchResult( String title, String summary, Drawable icon, ApplicationInfo applicationInfo)232 private SearchResult getAppSearchResult( 233 String title, String summary, Drawable icon, ApplicationInfo applicationInfo) { 234 AppSearchResult.Builder builder = new AppSearchResult.Builder(); 235 builder.addTitle(title) 236 .addSummary(summary) 237 .addRank(1) 238 .addPayload(new IntentPayload( 239 new Intent().setComponent(new ComponentName("pkg", "class")))) 240 .addBreadcrumbs(new ArrayList<>()) 241 .addIcon(icon); 242 builder.setAppInfo(applicationInfo); 243 return builder.build(); 244 } 245 getApplicationInfo(int userId, CharSequence appLabel, Drawable icon)246 private ApplicationInfo getApplicationInfo(int userId, CharSequence appLabel, Drawable icon) { 247 ApplicationInfo applicationInfo = spy(new ApplicationInfo()); 248 applicationInfo.uid = UserHandle.getUid(userId, 12345); 249 doReturn(icon).when(applicationInfo).loadIcon(any(PackageManager.class)); 250 doReturn(appLabel).when(applicationInfo).loadLabel(any(PackageManager.class)); 251 return applicationInfo; 252 } 253 } 254