• 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 
21 import static org.mockito.ArgumentMatchers.any;
22 import static org.mockito.ArgumentMatchers.anyInt;
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.verify;
27 import static org.mockito.Mockito.when;
28 
29 import android.content.Context;
30 import android.content.Intent;
31 import android.content.pm.ActivityInfo;
32 import android.content.pm.PackageInfo;
33 import android.content.pm.ResolveInfo;
34 import android.os.UserHandle;
35 import android.view.LayoutInflater;
36 import android.view.View;
37 import android.widget.ImageButton;
38 import android.widget.TextView;
39 
40 import androidx.fragment.app.Fragment;
41 import androidx.fragment.app.FragmentActivity;
42 import androidx.preference.Preference;
43 
44 import com.android.settings.R;
45 import com.android.settingslib.widget.LayoutPreference;
46 
47 import org.junit.Before;
48 import org.junit.Test;
49 import org.junit.runner.RunWith;
50 import org.mockito.Answers;
51 import org.mockito.Mock;
52 import org.mockito.MockitoAnnotations;
53 import org.robolectric.RobolectricTestRunner;
54 import org.robolectric.RuntimeEnvironment;
55 
56 @RunWith(RobolectricTestRunner.class)
57 public class EntityHeaderControllerTest {
58 
59     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
60     private Context mContext;
61     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
62     private FragmentActivity mActivity;
63     @Mock
64     private Fragment mFragment;
65 
66     private Context mShadowContext;
67     private LayoutInflater mLayoutInflater;
68     private PackageInfo mInfo;
69     private EntityHeaderController mController;
70 
71     @Before
setUp()72     public void setUp() {
73         MockitoAnnotations.initMocks(this);
74         mShadowContext = RuntimeEnvironment.application;
75         when(mActivity.getApplicationContext()).thenReturn(mShadowContext);
76         when(mContext.getApplicationContext()).thenReturn(mContext);
77         when(mFragment.getContext()).thenReturn(mShadowContext);
78         mLayoutInflater = LayoutInflater.from(mShadowContext);
79         mInfo = new PackageInfo();
80         mInfo.versionName = "1234";
81     }
82 
83     @Test
testBuildView_constructedWithoutView_shouldCreateNewView()84     public void testBuildView_constructedWithoutView_shouldCreateNewView() {
85         mController = EntityHeaderController.newInstance(mActivity, mFragment, null);
86         View view = mController.done(mActivity);
87 
88         assertThat(view).isNotNull();
89     }
90 
91     @Test
testBuildView_withContext_shouldBuildPreferenceAllowedBelowDivider()92     public void testBuildView_withContext_shouldBuildPreferenceAllowedBelowDivider() {
93         mController = EntityHeaderController.newInstance(mActivity, mFragment, null);
94         Preference preference = mController.done(mActivity, mShadowContext);
95 
96         assertThat(preference instanceof LayoutPreference).isTrue();
97         assertThat(((LayoutPreference)preference).isAllowDividerBelow()).isTrue();
98     }
99 
100     @Test
testBuildView_constructedWithView_shouldReturnSameView()101     public void testBuildView_constructedWithView_shouldReturnSameView() {
102         View inputView = mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
103         mController = EntityHeaderController.newInstance(mActivity, mFragment, inputView);
104         View view = mController.done(mActivity);
105 
106         assertThat(view).isSameInstanceAs(inputView);
107     }
108 
109     @Test
bindViews_shouldBindAllData()110     public void bindViews_shouldBindAllData() {
111         final String testString = "test";
112         final View header =
113                 mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
114         final TextView label = header.findViewById(R.id.entity_header_title);
115         final TextView summary = header.findViewById(R.id.entity_header_summary);
116         final TextView secondSummary = header.findViewById(R.id.entity_header_second_summary);
117 
118         mController = EntityHeaderController.newInstance(mActivity, mFragment, header);
119         mController.setLabel(testString);
120         mController.setSummary(testString);
121         mController.setSecondSummary(testString);
122         mController.setIcon(mShadowContext.getDrawable(R.drawable.ic_add_24dp));
123         mController.done(mActivity);
124 
125         assertThat(label).isNotNull();
126         assertThat(label.getText()).isEqualTo(testString);
127         assertThat(summary).isNotNull();
128         assertThat(summary.getText()).isEqualTo(testString);
129         assertThat(secondSummary).isNotNull();
130         assertThat(secondSummary.getText()).isEqualTo(testString);
131     }
132 
133     @Test
bindButton_hasEditClickListener_shouldShowButton()134     public void bindButton_hasEditClickListener_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 view = mLayoutInflater
140                 .inflate(R.layout.settings_entity_header, null /* root */);
141         when(mActivity.getApplicationContext()).thenReturn(mContext);
142 
143         mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
144         mController.setEditListener(new View.OnClickListener() {
145             public void onClick(View v) {
146                 // do nothing
147             }
148         });
149         mController.setButtonActions(
150                 EntityHeaderController.ActionType.ACTION_EDIT_PREFERENCE,
151                 EntityHeaderController.ActionType.ACTION_NONE);
152         mController.done(mActivity);
153 
154         final ImageButton button1 = view.findViewById(android.R.id.button1);
155         assertThat(button1).isNotNull();
156         assertThat(button1.getVisibility()).isEqualTo(View.VISIBLE);
157         assertThat(button1.getDrawable()).isNotNull();
158         assertThat(view.findViewById(android.R.id.button2).getVisibility()).isEqualTo(View.GONE);
159     }
160 
161     @Test
bindButton_noEditClickListener_shouldNotShowButton()162     public void bindButton_noEditClickListener_shouldNotShowButton() {
163         final ResolveInfo info = new ResolveInfo();
164         info.activityInfo = new ActivityInfo();
165         info.activityInfo.packageName = "123";
166         info.activityInfo.name = "321";
167         final View view = mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
168         when(mActivity.getApplicationContext()).thenReturn(mContext);
169 
170         mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
171         mController.setButtonActions(
172                 EntityHeaderController.ActionType.ACTION_EDIT_PREFERENCE,
173                 EntityHeaderController.ActionType.ACTION_NONE);
174         mController.done(mActivity);
175 
176         assertThat(view.findViewById(android.R.id.button1).getVisibility()).isEqualTo(View.GONE);
177         assertThat(view.findViewById(android.R.id.button2).getVisibility()).isEqualTo(View.GONE);
178     }
179 
180 
181     @Test
bindButton_noAppInfo_shouldNotAttachClickListener()182     public void bindButton_noAppInfo_shouldNotAttachClickListener() {
183         final View appLinks =
184                 mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
185         final FragmentActivity activity = mock(FragmentActivity.class);
186         when(mFragment.getActivity()).thenReturn(activity);
187 
188         mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
189         mController.setPackageName(null)
190                 .setHasAppInfoLink(true)
191                 .setButtonActions(
192                         EntityHeaderController.ActionType.ACTION_NONE,
193                         EntityHeaderController.ActionType.ACTION_NONE);
194         mController.done(mActivity);
195 
196         assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
197                 .isEqualTo(View.GONE);
198         assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
199                 .isEqualTo(View.GONE);
200 
201         appLinks.findViewById(R.id.entity_header_content).performClick();
202         verify(mFragment, never()).getActivity();
203         verify(activity, never()).startActivity(any(Intent.class));
204     }
205 
206     @Test
bindButton_hasAppInfo_shouldAttachClickListener()207     public void bindButton_hasAppInfo_shouldAttachClickListener() {
208         final View appLinks =
209                 mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
210         final FragmentActivity activity = mock(FragmentActivity.class);
211         when(mFragment.getActivity()).thenReturn(activity);
212         when(mContext.getString(eq(R.string.application_info_label))).thenReturn("App Info");
213 
214         mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
215         mController.setPackageName("123")
216                 .setUid(123321)
217                 .setHasAppInfoLink(true)
218                 .setButtonActions(
219                         EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE,
220                         EntityHeaderController.ActionType.ACTION_NONE);
221         mController.done(mActivity);
222 
223         appLinks.findViewById(R.id.entity_header_content).performClick();
224         verify(activity)
225                 .startActivityForResultAsUser(any(Intent.class), anyInt(), any(UserHandle.class));
226     }
227 
228     @Test
iconContentDescription_shouldWorkWithSetIcon()229     public void iconContentDescription_shouldWorkWithSetIcon() {
230         final View view =
231                 mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
232         when(mFragment.getActivity()).thenReturn(mock(FragmentActivity.class));
233         mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
234         String description = "Fake Description";
235         mController.setIcon(mShadowContext.getDrawable(R.drawable.ic_add_24dp));
236         mController.setIconContentDescription(description);
237         mController.done(mActivity);
238         assertThat(view.findViewById(R.id.entity_header_icon).getContentDescription().toString())
239                 .isEqualTo(description);
240     }
241 
242     @Test
iconContentDescription_shouldWorkWithoutSetIcon()243     public void iconContentDescription_shouldWorkWithoutSetIcon() {
244         final View view = mLayoutInflater
245                 .inflate(R.layout.settings_entity_header, null /* root */);
246         when(mFragment.getActivity()).thenReturn(mock(FragmentActivity.class));
247         mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
248         String description = "Fake Description";
249         mController.setIconContentDescription(description);
250         mController.done(mActivity);
251         assertThat(view.findViewById(R.id.entity_header_icon).getContentDescription().toString())
252                 .isEqualTo(description);
253     }
254 
255     @Test
bindButton_hasAppNotifIntent_shouldShowButton()256     public void bindButton_hasAppNotifIntent_shouldShowButton() {
257         final View appLinks = mLayoutInflater
258                 .inflate(R.layout.settings_entity_header, null /* root */);
259 
260         mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
261         mController.setAppNotifPrefIntent(new Intent())
262                 .setButtonActions(
263                         EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE,
264                         EntityHeaderController.ActionType.ACTION_NONE);
265         mController.done(mActivity);
266 
267         assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
268                 .isEqualTo(View.VISIBLE);
269         assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
270                 .isEqualTo(View.GONE);
271     }
272 
273     // Ensure that the instant app label does not show up when we haven't told the controller the
274     // app is instant.
275     @Test
instantApps_normalAppsDontGetLabel()276     public void instantApps_normalAppsDontGetLabel() {
277         final View header = mLayoutInflater.inflate(
278                 R.layout.settings_entity_header, null /* root */);
279         mController = EntityHeaderController.newInstance(mActivity, mFragment, header);
280         mController.done(mActivity);
281 
282         assertThat(header.findViewById(R.id.install_type).getVisibility())
283                 .isEqualTo(View.GONE);
284     }
285 
286     // Test that the "instant apps" label is present in the header when we have an instant app.
287     @Test
instantApps_expectedHeaderItem()288     public void instantApps_expectedHeaderItem() {
289         final View header = mLayoutInflater.inflate(
290                 R.layout.settings_entity_header, null /* root */);
291         mController = EntityHeaderController.newInstance(mActivity, mFragment, header);
292         mController.setIsInstantApp(true);
293         mController.done(mActivity);
294         TextView label = header.findViewById(R.id.install_type);
295 
296         assertThat(label.getVisibility()).isEqualTo(View.VISIBLE);
297         assertThat(label.getText()).isEqualTo(
298                 header.getResources().getString(R.string.install_type_instant));
299         assertThat(header.findViewById(R.id.entity_header_summary).getVisibility())
300                 .isEqualTo(View.GONE);
301     }
302 
303     @Test
initAppHeaderController_appHeaderNull_useFragmentContext()304     public void initAppHeaderController_appHeaderNull_useFragmentContext() {
305         mController = EntityHeaderController.newInstance(mActivity, mFragment, null);
306 
307         // Fragment.getContext() is invoked to inflate the view
308         verify(mFragment).getContext();
309     }
310 }
311