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_hasEditRuleNameClickListener_shouldShowButton() {
169 final ResolveInfo info = new ResolveInfo();
170 info.activityInfo = new ActivityInfo();
171 info.activityInfo.packageName = "123";
172 info.activityInfo.name = "321";
173 final View view = mLayoutInflater
174 .inflate(R.layout.settings_entity_header, null /* root */);
175 when(mActivity.getApplicationContext()).thenReturn(mContext);
177 mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
178 mController.setEditZenRuleNameListener(new View.OnClickListener() {
179 public void onClick(View v) {
183 mController.setButtonActions(
184 EntityHeaderController.ActionType.ACTION_DND_RULE_PREFERENCE,
185 EntityHeaderController.ActionType.ACTION_NONE);
186 mController.done(mActivity);
188 final ImageButton button1 = view.findViewById(android.R.id.button1);
189 assertThat(button1.getVisibility()).isEqualTo(View.VISIBLE);
190 assertThat(button1.getDrawable()).isNotNull();
191 assertThat(view.findViewById(android.R.id.button2).getVisibility())
192 .isEqualTo(View.GONE);
196 public void bindButton_noEditRuleNameClickListener_shouldNotShowButton() {
197 final ResolveInfo info = new ResolveInfo();
198 info.activityInfo = new ActivityInfo();
199 info.activityInfo.packageName = "123";
200 info.activityInfo.name = "321";
201 final View view = mLayoutInflater
202 .inflate(R.layout.settings_entity_header, null /* root */);
203 when(mActivity.getApplicationContext()).thenReturn(mContext);
205 mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
206 mController.setButtonActions(
207 EntityHeaderController.ActionType.ACTION_DND_RULE_PREFERENCE,
208 EntityHeaderController.ActionType.ACTION_NONE);
209 mController.done(mActivity);
211 assertThat(view.findViewById(android.R.id.button1).getVisibility())
212 .isEqualTo(View.GONE);
213 assertThat(view.findViewById(android.R.id.button2).getVisibility())
214 .isEqualTo(View.GONE);
219 public void bindButton_noAppPref_shouldNotShowButton() {
220 final View appLinks = mLayoutInflater
221 .inflate(R.layout.settings_entity_header, null /* root */);
222 when(mContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
225 mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
226 mController.setButtonActions(
227 EntityHeaderController.ActionType.ACTION_APP_PREFERENCE,
228 EntityHeaderController.ActionType.ACTION_NONE);
229 mController.done(mActivity);
231 final ImageButton button1 = appLinks.findViewById(android.R.id.button1);
232 assertThat(button1.getVisibility()).isEqualTo(View.GONE);
233 assertThat(button1.getDrawable()).isNull();
234 assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
235 .isEqualTo(View.GONE);
239 public void bindButton_noAppInfo_shouldNotAttachClickListener() {
240 final View appLinks = mLayoutInflater
241 .inflate(R.layout.settings_entity_header, null /* root */);
242 final Activity activity = mock(Activity.class);
243 when(mFragment.getActivity()).thenReturn(activity);
245 mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
246 mController.setPackageName(null)
247 .setHasAppInfoLink(true)
249 EntityHeaderController.ActionType.ACTION_NONE,
250 EntityHeaderController.ActionType.ACTION_NONE);
251 mController.done(mActivity);
253 assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
254 .isEqualTo(View.GONE);
255 assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
256 .isEqualTo(View.GONE);
258 appLinks.findViewById(R.id.entity_header_content).performClick();
259 verify(mFragment, never()).getActivity();
260 verify(activity, never()).startActivity(any(Intent.class));
264 public void bindButton_hasAppInfo_shouldAttachClickListener() {
265 final View appLinks = mLayoutInflater
266 .inflate(R.layout.settings_entity_header, null /* root */);
267 final Activity activity = mock(Activity.class);
268 when(mFragment.getActivity()).thenReturn(activity);
269 when(mContext.getString(eq(R.string.application_info_label))).thenReturn("App Info");
271 mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
272 mController.setPackageName("123")
273 .setUid(UserHandle.USER_SYSTEM)
274 .setHasAppInfoLink(true)
276 EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE,
277 EntityHeaderController.ActionType.ACTION_NONE);
278 mController.done(mActivity);
280 appLinks.findViewById(R.id.entity_header_content).performClick();
281 verify(activity).startActivityForResultAsUser(
282 any(Intent.class), anyInt(), any(UserHandle.class));
286 public void iconContentDescription_shouldWorkWithSetIcon() {
287 final View view = mLayoutInflater
288 .inflate(R.layout.settings_entity_header, null /* root */);
289 when(mFragment.getActivity()).thenReturn(mock(Activity.class));
290 mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
291 String description = "Fake Description";
292 mController.setIcon(mShadowContext.getDrawable(R.drawable.ic_add));
293 mController.setIconContentDescription(description);
294 mController.done(mActivity);
295 assertThat(view.findViewById(R.id.entity_header_icon).getContentDescription().toString())
296 .isEqualTo(description);
300 public void iconContentDescription_shouldWorkWithoutSetIcon() {
301 final View view = mLayoutInflater
302 .inflate(R.layout.settings_entity_header, null /* root */);
303 when(mFragment.getActivity()).thenReturn(mock(Activity.class));
304 mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
305 String description = "Fake Description";
306 mController.setIconContentDescription(description);
307 mController.done(mActivity);
308 assertThat(view.findViewById(R.id.entity_header_icon).getContentDescription().toString())
309 .isEqualTo(description);
313 public void bindButton_hasAppNotifIntent_shouldShowButton() {
314 final View appLinks = mLayoutInflater
315 .inflate(R.layout.settings_entity_header, null /* root */);
317 mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
318 mController.setAppNotifPrefIntent(new Intent())
320 EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE,
321 EntityHeaderController.ActionType.ACTION_NONE);
322 mController.done(mActivity);
324 assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
325 .isEqualTo(View.VISIBLE);
326 assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
327 .isEqualTo(View.GONE);
330 // Ensure that the instant app label does not show up when we haven't told the controller the
333 public void instantApps_normalAppsDontGetLabel() {
334 final View header = mLayoutInflater.inflate(
335 R.layout.settings_entity_header, null /* root */);
336 mController = EntityHeaderController.newInstance(mActivity, mFragment, header);
337 mController.done(mActivity);
339 assertThat(header.findViewById(R.id.install_type).getVisibility())
340 .isEqualTo(View.GONE);
343 // Test that the "instant apps" label is present in the header when we have an instant app.
345 public void instantApps_expectedHeaderItem() {
346 final View header = mLayoutInflater.inflate(
347 R.layout.settings_entity_header, null /* root */);
348 mController = EntityHeaderController.newInstance(mActivity, mFragment, header);
349 mController.setIsInstantApp(true);
350 mController.done(mActivity);
351 TextView label = header.findViewById(R.id.install_type);
353 assertThat(label.getVisibility()).isEqualTo(View.VISIBLE);
354 assertThat(label.getText()).isEqualTo(
355 header.getResources().getString(R.string.install_type_instant));
356 assertThat(header.findViewById(R.id.entity_header_summary).getVisibility())
357 .isEqualTo(View.GONE);
361 public void styleActionBar_invalidObjects_shouldNotCrash() {
362 mController = EntityHeaderController.newInstance(mActivity, mFragment, null);
363 mController.styleActionBar(null);
365 when(mActivity.getActionBar()).thenReturn(null);
366 mController.styleActionBar(mActivity);
368 verify(mActivity).getActionBar();
372 public void styleActionBar_setElevationAndBackground() {
373 final ActionBar actionBar = mActivity.getActionBar();
375 mController = EntityHeaderController.newInstance(mActivity, mFragment, null);
376 mController.styleActionBar(mActivity);
378 verify(actionBar).setElevation(0);
379 // Enforce a color drawable as background here, as image based drawables might not be
380 // wide enough to cover entire action bar.
381 verify(actionBar).setBackgroundDrawable(any(ColorDrawable.class));
385 public void initAppHeaderController_appHeaderNull_useFragmentContext() {
386 mController = EntityHeaderController.newInstance(mActivity, mFragment, null);
388 // Fragment.getContext() is invoked to inflate the view
389 verify(mFragment).getContext();