• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package com.android.settings.widget;
18 
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;
27 
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.ApplicationInfo;
35 import android.content.pm.PackageInfo;
36 import android.content.pm.ResolveInfo;
37 import android.graphics.drawable.ColorDrawable;
38 import android.os.UserHandle;
39 import android.support.v7.preference.Preference;
40 import android.view.LayoutInflater;
41 import android.view.View;
42 import android.widget.ImageButton;
43 import android.widget.ImageView;
44 import android.widget.TextView;
45 
46 import com.android.settings.R;
47 import com.android.settings.applications.LayoutPreference;
48 import com.android.settings.testutils.SettingsRobolectricTestRunner;
49 import com.android.settings.testutils.ShadowIconDrawableFactory;
50 import com.android.settingslib.applications.ApplicationsState;
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 @RunWith(SettingsRobolectricTestRunner.class)
62 public class EntityHeaderControllerTest {
63 
64     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
65     private Context mContext;
66     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
67     private Activity mActivity;
68     @Mock
69     private Fragment mFragment;
70 
71     private Context mShadowContext;
72     private LayoutInflater mLayoutInflater;
73     private PackageInfo mInfo;
74     private EntityHeaderController mController;
75 
76     @Before
setUp()77     public void setUp() {
78         MockitoAnnotations.initMocks(this);
79         mShadowContext = RuntimeEnvironment.application;
80         when(mActivity.getApplicationContext()).thenReturn(mShadowContext);
81         when(mContext.getApplicationContext()).thenReturn(mContext);
82         when(mFragment.getContext()).thenReturn(mShadowContext);
83         mLayoutInflater = LayoutInflater.from(mShadowContext);
84         mInfo = new PackageInfo();
85         mInfo.versionName = "1234";
86     }
87 
88     @Test
testBuildView_constructedWithoutView_shouldCreateNewView()89     public void testBuildView_constructedWithoutView_shouldCreateNewView() {
90         mController = EntityHeaderController.newInstance(mActivity, mFragment, null);
91         View view = mController.done(mActivity);
92 
93         assertThat(view).isNotNull();
94     }
95 
96     @Test
testBuildView_withContext_shouldBuildPreference()97     public void testBuildView_withContext_shouldBuildPreference() {
98         mController = EntityHeaderController.newInstance(mActivity, mFragment, null);
99         Preference preference = mController.done(mActivity, mShadowContext);
100 
101         assertThat(preference instanceof LayoutPreference).isTrue();
102     }
103 
104     @Test
testBuildView_constructedWithView_shouldReturnSameView()105     public void testBuildView_constructedWithView_shouldReturnSameView() {
106         View inputView = mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
107         mController = EntityHeaderController.newInstance(mActivity, mFragment, inputView);
108         View view = mController.done(mActivity);
109 
110         assertThat(view).isSameAs(inputView);
111     }
112 
113     @Test
bindViews_shouldBindAllData()114     public void bindViews_shouldBindAllData() {
115         final String testString = "test";
116         final View header =
117                 mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
118         final TextView label = header.findViewById(R.id.entity_header_title);
119         final TextView summary = header.findViewById(R.id.entity_header_summary);
120         final TextView secondSummary = header.findViewById(R.id.entity_header_second_summary);
121 
122         mController = EntityHeaderController.newInstance(mActivity, mFragment, header);
123         mController.setLabel(testString);
124         mController.setSummary(testString);
125         mController.setSecondSummary(testString);
126         mController.setIcon(mShadowContext.getDrawable(R.drawable.ic_add));
127         mController.done(mActivity);
128 
129         assertThat(label).isNotNull();
130         assertThat(label.getText()).isEqualTo(testString);
131         assertThat(summary).isNotNull();
132         assertThat(summary.getText()).isEqualTo(testString);
133         assertThat(secondSummary).isNotNull();
134         assertThat(secondSummary.getText()).isEqualTo(testString);
135     }
136 
137     @Test
bindButton_hasEditRuleNameClickListener_shouldShowButton()138     public void bindButton_hasEditRuleNameClickListener_shouldShowButton() {
139         final ResolveInfo info = new ResolveInfo();
140         info.activityInfo = new ActivityInfo();
141         info.activityInfo.packageName = "123";
142         info.activityInfo.name = "321";
143         final View view = mLayoutInflater
144                 .inflate(R.layout.settings_entity_header, null /* root */);
145         when(mActivity.getApplicationContext()).thenReturn(mContext);
146 
147         mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
148         mController.setEditZenRuleNameListener(new View.OnClickListener() {
149             public void onClick(View v) {
150                 // do nothing
151             }
152         });
153         mController.setButtonActions(
154                 EntityHeaderController.ActionType.ACTION_DND_RULE_PREFERENCE,
155                 EntityHeaderController.ActionType.ACTION_NONE);
156         mController.done(mActivity);
157 
158         final ImageButton button1 = view.findViewById(android.R.id.button1);
159         assertThat(button1).isNotNull();
160         assertThat(button1.getVisibility()).isEqualTo(View.VISIBLE);
161         assertThat(button1.getDrawable()).isNotNull();
162         assertThat(view.findViewById(android.R.id.button2).getVisibility()).isEqualTo(View.GONE);
163     }
164 
165     @Test
bindButton_noEditRuleNameClickListener_shouldNotShowButton()166     public void bindButton_noEditRuleNameClickListener_shouldNotShowButton() {
167         final ResolveInfo info = new ResolveInfo();
168         info.activityInfo = new ActivityInfo();
169         info.activityInfo.packageName = "123";
170         info.activityInfo.name = "321";
171         final View view = mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
172         when(mActivity.getApplicationContext()).thenReturn(mContext);
173 
174         mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
175         mController.setButtonActions(
176                 EntityHeaderController.ActionType.ACTION_DND_RULE_PREFERENCE,
177                 EntityHeaderController.ActionType.ACTION_NONE);
178         mController.done(mActivity);
179 
180         assertThat(view.findViewById(android.R.id.button1).getVisibility()).isEqualTo(View.GONE);
181         assertThat(view.findViewById(android.R.id.button2).getVisibility()).isEqualTo(View.GONE);
182     }
183 
184 
185     @Test
bindButton_noAppInfo_shouldNotAttachClickListener()186     public void bindButton_noAppInfo_shouldNotAttachClickListener() {
187         final View appLinks =
188                 mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
189         final Activity activity = mock(Activity.class);
190         when(mFragment.getActivity()).thenReturn(activity);
191 
192         mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
193         mController.setPackageName(null)
194                 .setHasAppInfoLink(true)
195                 .setButtonActions(
196                         EntityHeaderController.ActionType.ACTION_NONE,
197                         EntityHeaderController.ActionType.ACTION_NONE);
198         mController.done(mActivity);
199 
200         assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
201                 .isEqualTo(View.GONE);
202         assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
203                 .isEqualTo(View.GONE);
204 
205         appLinks.findViewById(R.id.entity_header_content).performClick();
206         verify(mFragment, never()).getActivity();
207         verify(activity, never()).startActivity(any(Intent.class));
208     }
209 
210     @Test
bindButton_hasAppInfo_shouldAttachClickListener()211     public void bindButton_hasAppInfo_shouldAttachClickListener() {
212         final View appLinks =
213                 mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
214         final Activity activity = mock(Activity.class);
215         when(mFragment.getActivity()).thenReturn(activity);
216         when(mContext.getString(eq(R.string.application_info_label))).thenReturn("App Info");
217 
218         mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
219         mController.setPackageName("123")
220                 .setUid(123321)
221                 .setHasAppInfoLink(true)
222                 .setButtonActions(
223                         EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE,
224                         EntityHeaderController.ActionType.ACTION_NONE);
225         mController.done(mActivity);
226 
227         appLinks.findViewById(R.id.entity_header_content).performClick();
228         verify(activity)
229                 .startActivityForResultAsUser(any(Intent.class), anyInt(), any(UserHandle.class));
230     }
231 
232     @Test
iconContentDescription_shouldWorkWithSetIcon()233     public void iconContentDescription_shouldWorkWithSetIcon() {
234         final View view =
235                 mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
236         when(mFragment.getActivity()).thenReturn(mock(Activity.class));
237         mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
238         String description = "Fake Description";
239         mController.setIcon(mShadowContext.getDrawable(R.drawable.ic_add));
240         mController.setIconContentDescription(description);
241         mController.done(mActivity);
242         assertThat(view.findViewById(R.id.entity_header_icon).getContentDescription().toString())
243                 .isEqualTo(description);
244     }
245 
246     @Test
iconContentDescription_shouldWorkWithoutSetIcon()247     public void iconContentDescription_shouldWorkWithoutSetIcon() {
248         final View view = mLayoutInflater
249                 .inflate(R.layout.settings_entity_header, null /* root */);
250         when(mFragment.getActivity()).thenReturn(mock(Activity.class));
251         mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
252         String description = "Fake Description";
253         mController.setIconContentDescription(description);
254         mController.done(mActivity);
255         assertThat(view.findViewById(R.id.entity_header_icon).getContentDescription().toString())
256                 .isEqualTo(description);
257     }
258 
259     @Test
260     @Config(shadows = ShadowIconDrawableFactory.class)
setIcon_usingAppEntry_shouldLoadIconFromDrawableFactory()261     public void setIcon_usingAppEntry_shouldLoadIconFromDrawableFactory() {
262         final View view = mLayoutInflater
263                 .inflate(R.layout.settings_entity_header, null /* root */);
264         final ApplicationsState.AppEntry entry = mock(ApplicationsState.AppEntry.class);
265         entry.info = new ApplicationInfo();
266         mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
267         mController.setIcon(entry).done(mActivity);
268         final ImageView iconView = view.findViewById(R.id.entity_header_icon);
269 
270         // Icon is set
271         assertThat(iconView.getDrawable()).isNotNull();
272         // ... and entry.icon is still empty. This means the icon didn't come from cache.
273         assertThat(entry.icon).isNull();
274     }
275 
276     @Test
bindButton_hasAppNotifIntent_shouldShowButton()277     public void bindButton_hasAppNotifIntent_shouldShowButton() {
278         final View appLinks = mLayoutInflater
279                 .inflate(R.layout.settings_entity_header, null /* root */);
280 
281         mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
282         mController.setAppNotifPrefIntent(new Intent())
283                 .setButtonActions(
284                         EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE,
285                         EntityHeaderController.ActionType.ACTION_NONE);
286         mController.done(mActivity);
287 
288         assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
289                 .isEqualTo(View.VISIBLE);
290         assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
291                 .isEqualTo(View.GONE);
292     }
293 
294     // Ensure that the instant app label does not show up when we haven't told the controller the
295     // app is instant.
296     @Test
instantApps_normalAppsDontGetLabel()297     public void instantApps_normalAppsDontGetLabel() {
298         final View header = mLayoutInflater.inflate(
299                 R.layout.settings_entity_header, null /* root */);
300         mController = EntityHeaderController.newInstance(mActivity, mFragment, header);
301         mController.done(mActivity);
302 
303         assertThat(header.findViewById(R.id.install_type).getVisibility())
304                 .isEqualTo(View.GONE);
305     }
306 
307     // Test that the "instant apps" label is present in the header when we have an instant app.
308     @Test
instantApps_expectedHeaderItem()309     public void instantApps_expectedHeaderItem() {
310         final View header = mLayoutInflater.inflate(
311                 R.layout.settings_entity_header, null /* root */);
312         mController = EntityHeaderController.newInstance(mActivity, mFragment, header);
313         mController.setIsInstantApp(true);
314         mController.done(mActivity);
315         TextView label = header.findViewById(R.id.install_type);
316 
317         assertThat(label.getVisibility()).isEqualTo(View.VISIBLE);
318         assertThat(label.getText()).isEqualTo(
319                 header.getResources().getString(R.string.install_type_instant));
320         assertThat(header.findViewById(R.id.entity_header_summary).getVisibility())
321                 .isEqualTo(View.GONE);
322     }
323 
324     @Test
styleActionBar_invalidObjects_shouldNotCrash()325     public void styleActionBar_invalidObjects_shouldNotCrash() {
326         mController = EntityHeaderController.newInstance(mActivity, mFragment, null);
327         mController.styleActionBar(null);
328 
329         when(mActivity.getActionBar()).thenReturn(null);
330         mController.styleActionBar(mActivity);
331 
332         verify(mActivity).getActionBar();
333     }
334 
335     @Test
styleActionBar_setElevationAndBackground()336     public void styleActionBar_setElevationAndBackground() {
337         final ActionBar actionBar = mActivity.getActionBar();
338 
339         mController = EntityHeaderController.newInstance(mActivity, mFragment, null);
340         mController.styleActionBar(mActivity);
341 
342         verify(actionBar).setElevation(0);
343         // Enforce a color drawable as background here, as image based drawables might not be
344         // wide enough to cover entire action bar.
345         verify(actionBar).setBackgroundDrawable(any(ColorDrawable.class));
346     }
347 
348     @Test
initAppHeaderController_appHeaderNull_useFragmentContext()349     public void initAppHeaderController_appHeaderNull_useFragmentContext() {
350         mController = EntityHeaderController.newInstance(mActivity, mFragment, null);
351 
352         // Fragment.getContext() is invoked to inflate the view
353         verify(mFragment).getContext();
354     }
355 }
356