1 /*
2  * Copyright (C) 2018 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.panel;
19 
20 import static com.google.common.truth.Truth.assertThat;
21 
22 import static org.mockito.ArgumentMatchers.any;
23 import static org.mockito.Mockito.doReturn;
24 import static org.mockito.Mockito.spy;
25 import static org.mockito.Mockito.verify;
26 import static org.mockito.Mockito.when;
27 
28 import android.app.settings.SettingsEnums;
29 import android.content.Context;
30 import android.net.Uri;
31 import android.os.Bundle;
32 import android.view.LayoutInflater;
33 import android.view.View;
34 import android.widget.Button;
35 import android.widget.LinearLayout;
36 import android.widget.ProgressBar;
37 import android.widget.TextView;
38 
39 import androidx.core.graphics.drawable.IconCompat;
40 
41 import com.android.settings.R;
42 import com.android.settings.testutils.FakeFeatureFactory;
43 
44 import org.junit.Before;
45 import org.junit.Test;
46 import org.junit.runner.RunWith;
47 import org.mockito.ArgumentCaptor;
48 import org.robolectric.Robolectric;
49 import org.robolectric.RobolectricTestRunner;
50 import org.robolectric.RuntimeEnvironment;
51 import org.robolectric.android.controller.ActivityController;
52 
53 import java.util.Objects;
54 
55 @RunWith(RobolectricTestRunner.class)
56 public class PanelFragmentTest {
57 
58     private static final String TITLE = "title";
59     private static final String TITLE2 = "title2";
60     private static final String SUBTITLE = "subtitle";
61     private static final String SUBTITLE2 = "subtitle2";
62 
63     private Context mContext;
64     private PanelFragment mPanelFragment;
65     private FakeSettingsPanelActivity mActivity;
66     private FakeFeatureFactory mFakeFeatureFactory;
67     private PanelFeatureProvider mPanelFeatureProvider;
68     private FakePanelContent mFakePanelContent;
69     private ArgumentCaptor<PanelContentCallback> mPanelContentCbs = ArgumentCaptor.forClass(
70             PanelContentCallback.class);
71 
72     private final String FAKE_EXTRA = "fake_extra";
73 
74     @Before
setUp()75     public void setUp() {
76         mContext = RuntimeEnvironment.application;
77 
78         mPanelFeatureProvider = spy(new PanelFeatureProviderImpl());
79         mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
80         mFakeFeatureFactory.panelFeatureProvider = mPanelFeatureProvider;
81         mFakePanelContent = spy(new FakePanelContent());
82         doReturn(mFakePanelContent).when(mPanelFeatureProvider).getPanel(any(), any());
83     }
84 
initFakeActivity()85     private void initFakeActivity() {
86         mActivity = spy(Robolectric.buildActivity(FakeSettingsPanelActivity.class).setup().get());
87 
88         mPanelFragment =
89                 spy((PanelFragment)
90                         mActivity.getSupportFragmentManager().findFragmentById(R.id.main_content));
91         doReturn(mActivity).when(mPanelFragment).getActivity();
92 
93         final Bundle bundle = new Bundle();
94         bundle.putString(SettingsPanelActivity.KEY_PANEL_TYPE_ARGUMENT, FAKE_EXTRA);
95         doReturn(bundle).when(mPanelFragment).getArguments();
96     }
97 
98     @Test
onCreateView_countdownLatch_setup()99     public void onCreateView_countdownLatch_setup() {
100         initFakeActivity();
101         mPanelFragment.onCreateView(LayoutInflater.from(mContext),
102                 new LinearLayout(mContext), null);
103         PanelSlicesLoaderCountdownLatch countdownLatch =
104                 mPanelFragment.mPanelSlicesLoaderCountdownLatch;
105         for (Uri sliecUri : mFakePanelContent.getSlices()) {
106             countdownLatch.markSliceLoaded(sliecUri);
107         }
108 
109         assertThat(countdownLatch.isPanelReadyToLoad()).isTrue();
110     }
111 
112     @Test
onCreate_logsOpenEvent()113     public void onCreate_logsOpenEvent() {
114         initFakeActivity();
115         verify(mFakeFeatureFactory.metricsFeatureProvider).action(
116                 0,
117                 SettingsEnums.PAGE_VISIBLE,
118                 mFakePanelContent.getMetricsCategory(),
119                 null,
120                 0);
121     }
122 
123     @Test
onDestroy_logCloseEvent()124     public void onDestroy_logCloseEvent() {
125         initFakeActivity();
126         mPanelFragment.onDestroyView();
127         verify(mFakeFeatureFactory.metricsFeatureProvider).action(
128                 0,
129                 SettingsEnums.PAGE_HIDE,
130                 mFakePanelContent.getMetricsCategory(),
131                 PanelLoggingContract.PanelClosedKeys.KEY_OTHERS,
132                 0);
133     }
134 
135     @Test
panelSeeMoreClick_logsCloseEvent()136     public void panelSeeMoreClick_logsCloseEvent() {
137         initFakeActivity();
138         final View.OnClickListener listener = mPanelFragment.getSeeMoreListener();
139         listener.onClick(null);
140         verify(mActivity).finish();
141 
142         mPanelFragment.onDestroyView();
143         verify(mFakeFeatureFactory.metricsFeatureProvider).action(
144                 0,
145                 SettingsEnums.PAGE_HIDE,
146                 mFakePanelContent.getMetricsCategory(),
147                 PanelLoggingContract.PanelClosedKeys.KEY_SEE_MORE,
148                 0
149         );
150     }
151 
152     @Test
panelDoneClick_logsCloseEvent()153     public void panelDoneClick_logsCloseEvent() {
154         initFakeActivity();
155         final View.OnClickListener listener = mPanelFragment.getCloseListener();
156         listener.onClick(null);
157         verify(mActivity).finish();
158 
159         mPanelFragment.onDestroyView();
160         verify(mFakeFeatureFactory.metricsFeatureProvider).action(
161                 0,
162                 SettingsEnums.PAGE_HIDE,
163                 mFakePanelContent.getMetricsCategory(),
164                 PanelLoggingContract.PanelClosedKeys.KEY_DONE,
165                 0
166         );
167     }
168 
169     @Test
supportIcon_displayIconHeaderLayout()170     public void supportIcon_displayIconHeaderLayout() {
171         final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_android);
172         mFakePanelContent.setIcon(icon);
173         mFakePanelContent.setSubTitle(SUBTITLE);
174         final ActivityController<FakeSettingsPanelActivity> activityController =
175                 Robolectric.buildActivity(FakeSettingsPanelActivity.class);
176         activityController.setup();
177         final PanelFragment panelFragment = (PanelFragment)
178                 Objects.requireNonNull(activityController
179                         .get()
180                         .getSupportFragmentManager()
181                         .findFragmentById(R.id.main_content));
182         final View titleView = panelFragment.mLayoutView.findViewById(R.id.panel_title);
183         final LinearLayout panelHeader = panelFragment.mLayoutView.findViewById(R.id.panel_header);
184         final TextView headerTitle = panelFragment.mLayoutView.findViewById(R.id.header_title);
185         final TextView headerSubtitle = panelFragment.mLayoutView.findViewById(
186                 R.id.header_subtitle);
187         // Check visibility
188         assertThat(panelHeader.getVisibility()).isEqualTo(View.VISIBLE);
189         assertThat(titleView.getVisibility()).isEqualTo(View.GONE);
190         // Check content
191         assertThat(headerTitle.getText()).isEqualTo(FakePanelContent.TITLE);
192         assertThat(headerSubtitle.getText()).isEqualTo(SUBTITLE);
193     }
194 
195     @Test
notSupportIcon_displayDefaultHeaderLayout()196     public void notSupportIcon_displayDefaultHeaderLayout() {
197         final ActivityController<FakeSettingsPanelActivity> activityController =
198                 Robolectric.buildActivity(FakeSettingsPanelActivity.class);
199         activityController.setup();
200         final PanelFragment panelFragment = (PanelFragment)
201                 Objects.requireNonNull(activityController
202                         .get()
203                         .getSupportFragmentManager()
204                         .findFragmentById(R.id.main_content));
205 
206         final View titleView = panelFragment.mLayoutView.findViewById(R.id.panel_title);
207         final View panelHeader = panelFragment.mLayoutView.findViewById(R.id.panel_header);
208 
209         assertThat(panelHeader.getVisibility()).isEqualTo(View.GONE);
210         assertThat(titleView.getVisibility()).isEqualTo(View.VISIBLE);
211     }
212 
213     @Test
onHeaderChanged_updateHeader_verifyTitle()214     public void onHeaderChanged_updateHeader_verifyTitle() {
215         mFakePanelContent.setIcon(IconCompat.createWithResource(mContext, R.drawable.ic_android));
216         mFakePanelContent.setTitle(TITLE);
217         mFakePanelContent.setSubTitle(SUBTITLE);
218         final ActivityController<FakeSettingsPanelActivity> activityController =
219                 Robolectric.buildActivity(FakeSettingsPanelActivity.class);
220         activityController.setup();
221         final PanelFragment panelFragment = (PanelFragment)
222                 Objects.requireNonNull(activityController
223                         .get()
224                         .getSupportFragmentManager()
225                         .findFragmentById(R.id.main_content));
226         final TextView headerTitle = panelFragment.mLayoutView.findViewById(R.id.header_title);
227         final TextView headerSubtitle = panelFragment.mLayoutView.findViewById(
228                 R.id.header_subtitle);
229 
230         assertThat(headerTitle.getText()).isEqualTo(TITLE);
231         assertThat(headerSubtitle.getText()).isEqualTo(SUBTITLE);
232 
233         mFakePanelContent.setTitle(TITLE2);
234         mFakePanelContent.setSubTitle(SUBTITLE2);
235         verify(mFakePanelContent).registerCallback(mPanelContentCbs.capture());
236         final PanelContentCallback panelContentCallbacks = mPanelContentCbs.getValue();
237         panelContentCallbacks.onHeaderChanged();
238 
239         assertThat(headerTitle.getText()).isEqualTo(TITLE2);
240         assertThat(headerSubtitle.getText()).isEqualTo(SUBTITLE2);
241     }
242 
243     @Test
forceClose_verifyFinish()244     public void forceClose_verifyFinish() {
245         initFakeActivity();
246         verify(mFakePanelContent).registerCallback(mPanelContentCbs.capture());
247         final PanelContentCallback panelContentCallbacks = spy(mPanelContentCbs.getValue());
248         when(((PanelFragment.LocalPanelCallback) panelContentCallbacks).getFragmentActivity())
249                 .thenReturn(mActivity);
250 
251         panelContentCallbacks.forceClose();
252 
253         verify(mActivity).finish();
254     }
255 
256     @Test
onCustomizedButtonStateChanged_isCustomized_showCustomizedTitle()257     public void onCustomizedButtonStateChanged_isCustomized_showCustomizedTitle() {
258         final ActivityController<FakeSettingsPanelActivity> activityController =
259                 Robolectric.buildActivity(FakeSettingsPanelActivity.class);
260         activityController.setup();
261         final PanelFragment panelFragment = (PanelFragment)
262                 Objects.requireNonNull(activityController
263                         .get()
264                         .getSupportFragmentManager()
265                         .findFragmentById(R.id.main_content));
266 
267         final Button seeMoreButton = panelFragment.mLayoutView.findViewById(R.id.see_more);
268 
269         mFakePanelContent.setIsCustomizedButtonUsed(true);
270         mFakePanelContent.setCustomizedButtonTitle("test_title");
271         verify(mFakePanelContent).registerCallback(mPanelContentCbs.capture());
272         final PanelContentCallback panelContentCallbacks = mPanelContentCbs.getValue();
273         panelContentCallbacks.onCustomizedButtonStateChanged();
274 
275         assertThat(seeMoreButton.getVisibility()).isEqualTo(View.VISIBLE);
276         assertThat(seeMoreButton.getText()).isEqualTo("test_title");
277     }
278 
279     @Test
onProgressBarVisibleChanged_isProgressBarVisible_showProgressBar()280     public void onProgressBarVisibleChanged_isProgressBarVisible_showProgressBar() {
281         final ActivityController<FakeSettingsPanelActivity> activityController =
282                 Robolectric.buildActivity(FakeSettingsPanelActivity.class);
283         activityController.setup();
284         final PanelFragment panelFragment = (PanelFragment)
285                 Objects.requireNonNull(activityController
286                         .get()
287                         .getSupportFragmentManager()
288                         .findFragmentById(R.id.main_content));
289 
290         final ProgressBar progressBar = panelFragment.mLayoutView.findViewById(R.id.progress_bar);
291 
292         mFakePanelContent.setIsProgressBarVisible(true);
293         verify(mFakePanelContent).registerCallback(mPanelContentCbs.capture());
294         final PanelContentCallback panelContentCallbacks = mPanelContentCbs.getValue();
295         panelContentCallbacks.onProgressBarVisibleChanged();
296 
297         assertThat(progressBar.getVisibility()).isEqualTo(View.VISIBLE);
298     }
299 }