2 * Copyright (C) 2016 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.settings.widget;
19 import static com.google.common.truth.Truth.assertThat;
20 import static org.mockito.Matchers.any;
21 import static org.mockito.Matchers.anyInt;
22 import static org.mockito.Matchers.eq;
23 import static org.mockito.Mockito.mock;
24 import static org.mockito.Mockito.never;
25 import static org.mockito.Mockito.verify;
26 import static org.mockito.Mockito.when;
28 import android.app.ActionBar;
29 import android.app.Activity;
30 import android.app.Fragment;
31 import android.content.Context;
32 import android.content.Intent;
33 import android.content.pm.ActivityInfo;
34 import android.content.pm.PackageInfo;
35 import android.content.pm.ResolveInfo;
36 import android.graphics.drawable.ColorDrawable;
37 import android.os.UserHandle;
38 import android.support.v7.preference.Preference;
39 import android.view.LayoutInflater;
40 import android.view.View;
41 import android.widget.ImageButton;
42 import android.widget.TextView;
44 import com.android.internal.logging.nano.MetricsProto;
45 import com.android.settings.R;
46 import com.android.settings.TestConfig;
47 import com.android.settings.applications.LayoutPreference;
48 import com.android.settings.testutils.FakeFeatureFactory;
49 import com.android.settings.testutils.SettingsRobolectricTestRunner;
51 import org.junit.Before;
52 import org.junit.Test;
53 import org.junit.runner.RunWith;
54 import org.mockito.Answers;
55 import org.mockito.Mock;
56 import org.mockito.MockitoAnnotations;
57 import org.robolectric.RuntimeEnvironment;
58 import org.robolectric.annotation.Config;
60 @RunWith(SettingsRobolectricTestRunner.class)
61 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
62 public class EntityHeaderControllerTest {
64 @Mock(answer = Answers.RETURNS_DEEP_STUBS)
65 private Context mContext;
66 @Mock(answer = Answers.RETURNS_DEEP_STUBS)
67 private Activity mActivity;
69 private Fragment mFragment;
71 private Context mShadowContext;
72 private LayoutInflater mLayoutInflater;
73 private PackageInfo mInfo;
74 private EntityHeaderController mController;
75 private FakeFeatureFactory mFeatureFactory;
79 MockitoAnnotations.initMocks(this);
80 mFeatureFactory = FakeFeatureFactory.setupForTest();
81 mShadowContext = RuntimeEnvironment.application;
82 when(mActivity.getApplicationContext()).thenReturn(mShadowContext);
83 when(mContext.getApplicationContext()).thenReturn(mContext);
84 when(mFragment.getContext()).thenReturn(mShadowContext);
85 mLayoutInflater = LayoutInflater.from(mShadowContext);
86 mInfo = new PackageInfo();
87 mInfo.versionName = "1234";
91 public void testBuildView_constructedWithoutView_shouldCreateNewView() {
92 mController = EntityHeaderController.newInstance(mActivity, mFragment, null);
93 View view = mController.done(mActivity);
95 assertThat(view).isNotNull();
99 public void testBuildView_withContext_shouldBuildPreference() {
100 mController = EntityHeaderController.newInstance(mActivity, mFragment, null);
101 Preference preference = mController.done(mActivity, mShadowContext);
103 assertThat(preference instanceof LayoutPreference).isTrue();
107 public void testBuildView_constructedWithView_shouldReturnSameView() {
108 View inputView = mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
109 mController = EntityHeaderController.newInstance(mActivity, mFragment, inputView);
110 View view = mController.done(mActivity);
112 assertThat(view).isSameAs(inputView);
116 public void bindViews_shouldBindAllData() {
117 final String testString = "test";
118 final View header = mLayoutInflater.inflate(
119 R.layout.settings_entity_header, null /* root */);
120 final TextView label = header.findViewById(R.id.entity_header_title);
121 final TextView version = header.findViewById(R.id.entity_header_summary);
123 mController = EntityHeaderController.newInstance(mActivity, mFragment, header);
124 mController.setLabel(testString);
125 mController.setSummary(testString);
126 mController.setIcon(mShadowContext.getDrawable(R.drawable.ic_add));
127 mController.done(mActivity);
129 assertThat(label.getText()).isEqualTo(testString);
130 assertThat(version.getText()).isEqualTo(testString);
134 public void bindButton_hasAppPref_shouldShowButton() {
135 final ResolveInfo info = new ResolveInfo();
136 info.activityInfo = new ActivityInfo();
137 info.activityInfo.packageName = "123";
138 info.activityInfo.name = "321";
139 final View appLinks = mLayoutInflater
140 .inflate(R.layout.settings_entity_header, null /* root */);
141 when(mActivity.getApplicationContext()).thenReturn(mContext);
142 when(mContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
145 mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
146 mController.setButtonActions(
147 EntityHeaderController.ActionType.ACTION_APP_PREFERENCE,
148 EntityHeaderController.ActionType.ACTION_NONE);
149 mController.done(mActivity);
151 final ImageButton button1 = appLinks.findViewById(android.R.id.button1);
152 assertThat(button1.getVisibility()).isEqualTo(View.VISIBLE);
153 assertThat(button1.getDrawable()).isNotNull();
154 assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
155 .isEqualTo(View.GONE);
157 appLinks.findViewById(android.R.id.button1).performClick();
158 } catch (Exception e) {
159 // Ignore exception because the launching intent is fake.
161 verify(mFeatureFactory.metricsFeatureProvider).actionWithSource(mContext,
162 MetricsProto.MetricsEvent.VIEW_UNKNOWN,
163 MetricsProto.MetricsEvent.ACTION_OPEN_APP_SETTING);
164 verify(mFragment).startActivity(any(Intent.class));
168 public void bindButton_noAppPref_shouldNotShowButton() {
169 final View appLinks = mLayoutInflater
170 .inflate(R.layout.settings_entity_header, null /* root */);
171 when(mContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
174 mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
175 mController.setButtonActions(
176 EntityHeaderController.ActionType.ACTION_APP_PREFERENCE,
177 EntityHeaderController.ActionType.ACTION_NONE);
178 mController.done(mActivity);
180 final ImageButton button1 = appLinks.findViewById(android.R.id.button1);
181 assertThat(button1.getVisibility()).isEqualTo(View.GONE);
182 assertThat(button1.getDrawable()).isNull();
183 assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
184 .isEqualTo(View.GONE);
188 public void bindButton_noAppInfo_shouldNotAttachClickListener() {
189 final View appLinks = mLayoutInflater
190 .inflate(R.layout.settings_entity_header, null /* root */);
191 final Activity activity = mock(Activity.class);
192 when(mFragment.getActivity()).thenReturn(activity);
194 mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
195 mController.setPackageName(null)
196 .setHasAppInfoLink(true)
198 EntityHeaderController.ActionType.ACTION_NONE,
199 EntityHeaderController.ActionType.ACTION_NONE);
200 mController.done(mActivity);
202 assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
203 .isEqualTo(View.GONE);
204 assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
205 .isEqualTo(View.GONE);
207 appLinks.findViewById(R.id.entity_header_content).performClick();
208 verify(mFragment, never()).getActivity();
209 verify(activity, never()).startActivity(any(Intent.class));
213 public void bindButton_hasAppInfo_shouldAttachClickListener() {
214 final View appLinks = mLayoutInflater
215 .inflate(R.layout.settings_entity_header, null /* root */);
216 final Activity activity = mock(Activity.class);
217 when(mFragment.getActivity()).thenReturn(activity);
218 when(mContext.getString(eq(R.string.application_info_label))).thenReturn("App Info");
220 mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
221 mController.setPackageName("123")
222 .setUid(UserHandle.USER_SYSTEM)
223 .setHasAppInfoLink(true)
225 EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE,
226 EntityHeaderController.ActionType.ACTION_NONE);
227 mController.done(mActivity);
229 appLinks.findViewById(R.id.entity_header_content).performClick();
230 verify(activity).startActivityForResultAsUser(
231 any(Intent.class), anyInt(), any(UserHandle.class));
235 public void iconContentDescription_shouldWorkWithSetIcon() {
236 final View view = mLayoutInflater
237 .inflate(R.layout.settings_entity_header, null /* root */);
238 when(mFragment.getActivity()).thenReturn(mock(Activity.class));
239 mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
240 String description = "Fake Description";
241 mController.setIcon(mShadowContext.getDrawable(R.drawable.ic_add));
242 mController.setIconContentDescription(description);
243 mController.done(mActivity);
244 assertThat(view.findViewById(R.id.entity_header_icon).getContentDescription().toString())
245 .isEqualTo(description);
249 public void iconContentDescription_shouldWorkWithoutSetIcon() {
250 final View view = mLayoutInflater
251 .inflate(R.layout.settings_entity_header, null /* root */);
252 when(mFragment.getActivity()).thenReturn(mock(Activity.class));
253 mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
254 String description = "Fake Description";
255 mController.setIconContentDescription(description);
256 mController.done(mActivity);
257 assertThat(view.findViewById(R.id.entity_header_icon).getContentDescription().toString())
258 .isEqualTo(description);
262 public void bindButton_hasAppNotifIntent_shouldShowButton() {
263 final View appLinks = mLayoutInflater
264 .inflate(R.layout.settings_entity_header, null /* root */);
266 mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
267 mController.setAppNotifPrefIntent(new Intent())
269 EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE,
270 EntityHeaderController.ActionType.ACTION_NONE);
271 mController.done(mActivity);
273 assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
274 .isEqualTo(View.VISIBLE);
275 assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
276 .isEqualTo(View.GONE);
279 // Ensure that the instant app label does not show up when we haven't told the controller the
282 public void instantApps_normalAppsDontGetLabel() {
283 final View header = mLayoutInflater.inflate(
284 R.layout.settings_entity_header, null /* root */);
285 mController = EntityHeaderController.newInstance(mActivity, mFragment, header);
286 mController.done(mActivity);
288 assertThat(header.findViewById(R.id.install_type).getVisibility())
289 .isEqualTo(View.GONE);
292 // Test that the "instant apps" label is present in the header when we have an instant app.
294 public void instantApps_expectedHeaderItem() {
295 final View header = mLayoutInflater.inflate(
296 R.layout.settings_entity_header, null /* root */);
297 mController = EntityHeaderController.newInstance(mActivity, mFragment, header);
298 mController.setIsInstantApp(true);
299 mController.done(mActivity);
300 TextView label = header.findViewById(R.id.install_type);
302 assertThat(label.getVisibility()).isEqualTo(View.VISIBLE);
303 assertThat(label.getText()).isEqualTo(
304 header.getResources().getString(R.string.install_type_instant));
305 assertThat(header.findViewById(R.id.entity_header_summary).getVisibility())
306 .isEqualTo(View.GONE);
310 public void styleActionBar_invalidObjects_shouldNotCrash() {
311 mController = EntityHeaderController.newInstance(mActivity, mFragment, null);
312 mController.styleActionBar(null);
314 when(mActivity.getActionBar()).thenReturn(null);
315 mController.styleActionBar(mActivity);
317 verify(mActivity).getActionBar();
321 public void styleActionBar_setElevationAndBackground() {
322 final ActionBar actionBar = mActivity.getActionBar();
324 mController = EntityHeaderController.newInstance(mActivity, mFragment, null);
325 mController.styleActionBar(mActivity);
327 verify(actionBar).setElevation(0);
328 // Enforce a color drawable as background here, as image based drawables might not be
329 // wide enough to cover entire action bar.
330 verify(actionBar).setBackgroundDrawable(any(ColorDrawable.class));
334 public void initAppHeaderController_appHeaderNull_useFragmentContext() {
335 mController = EntityHeaderController.newInstance(mActivity, mFragment, null);
337 // Fragment.getContext() is invoked to inflate the view
338 verify(mFragment).getContext();