1 /*
2  * Copyright (C) 2017 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;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.ArgumentMatchers.any;
22 import static org.mockito.Mockito.doReturn;
23 import static org.mockito.Mockito.mock;
24 import static org.mockito.Mockito.never;
25 import static org.mockito.Mockito.spy;
26 import static org.mockito.Mockito.verify;
27 import static org.mockito.Mockito.when;
28 
29 import android.content.Context;
30 import android.os.Bundle;
31 import android.view.View;
32 import android.widget.FrameLayout;
33 
34 import androidx.fragment.app.FragmentActivity;
35 import androidx.preference.Preference;
36 import androidx.preference.PreferenceCategory;
37 import androidx.preference.PreferenceManager;
38 import androidx.preference.PreferenceScreen;
39 
40 import com.android.settings.testutils.FakeFeatureFactory;
41 import com.android.settings.testutils.shadow.ShadowFragment;
42 import com.android.settings.widget.WorkOnlyCategory;
43 
44 import org.junit.Before;
45 import org.junit.Test;
46 import org.junit.runner.RunWith;
47 import org.mockito.Mock;
48 import org.mockito.MockitoAnnotations;
49 import org.robolectric.RobolectricTestRunner;
50 import org.robolectric.RuntimeEnvironment;
51 import org.robolectric.annotation.Config;
52 import org.robolectric.util.ReflectionHelpers;
53 
54 @RunWith(RobolectricTestRunner.class)
55 public class SettingsPreferenceFragmentTest {
56 
57     private static final int ITEM_COUNT = 5;
58 
59     @Mock
60     private FragmentActivity mActivity;
61     @Mock
62     private View mListContainer;
63     @Mock
64     private PreferenceScreen mPreferenceScreen;
65     private Context mContext;
66     private TestFragment mFragment;
67     private View mEmptyView;
68 
69     @Before
setUp()70     public void setUp() {
71         MockitoAnnotations.initMocks(this);
72         FakeFeatureFactory.setupForTest();
73         mContext = RuntimeEnvironment.application;
74         mFragment = spy(new TestFragment());
75         doReturn(mActivity).when(mFragment).getActivity();
76         when(mFragment.getContext()).thenReturn(mContext);
77 
78         mEmptyView = new View(mContext);
79         ReflectionHelpers.setField(mFragment, "mEmptyView", mEmptyView);
80 
81         doReturn(ITEM_COUNT).when(mPreferenceScreen).getPreferenceCount();
82     }
83 
84     @Test
removePreference_nested_shouldRemove()85     public void removePreference_nested_shouldRemove() {
86         final String key = "test_key";
87         final PreferenceScreen mScreen = spy(new PreferenceScreen(mContext, null));
88         when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
89 
90         final PreferenceCategory nestedCategory = new ProgressCategory(mContext);
91         final Preference preference = new Preference(mContext);
92         preference.setKey(key);
93         preference.setPersistent(false);
94 
95         mScreen.addPreference(nestedCategory);
96         nestedCategory.addPreference(preference);
97 
98         assertThat(mFragment.removePreference(mScreen, key)).isTrue();
99         assertThat(nestedCategory.getPreferenceCount()).isEqualTo(0);
100     }
101 
102     @Test
removePreference_flat_shouldRemove()103     public void removePreference_flat_shouldRemove() {
104         final String key = "test_key";
105         final PreferenceScreen mScreen = spy(new PreferenceScreen(mContext, null));
106         when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
107 
108         final Preference preference = mock(Preference.class);
109         when(preference.getKey()).thenReturn(key);
110 
111         mScreen.addPreference(preference);
112 
113         assertThat(mFragment.removePreference(mScreen, key)).isTrue();
114         assertThat(mScreen.getPreferenceCount()).isEqualTo(0);
115     }
116 
117     @Test
removePreference_doNotExist_shouldNotRemove()118     public void removePreference_doNotExist_shouldNotRemove() {
119         final String key = "test_key";
120         final PreferenceScreen mScreen = spy(new PreferenceScreen(mContext, null));
121         when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
122 
123         final Preference preference = mock(Preference.class);
124         when(preference.getKey()).thenReturn(key);
125 
126         mScreen.addPreference(preference);
127 
128         assertThat(mFragment.removePreference(mScreen, "not" + key)).isFalse();
129         assertThat(mScreen.getPreferenceCount()).isEqualTo(1);
130     }
131 
132     @Test
testUpdateEmptyView_containerInvisible_emptyViewVisible()133     public void testUpdateEmptyView_containerInvisible_emptyViewVisible() {
134         doReturn(View.INVISIBLE).when(mListContainer).getVisibility();
135         doReturn(mListContainer).when(mActivity).findViewById(android.R.id.list_container);
136         doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
137 
138         mFragment.updateEmptyView();
139 
140         assertThat(mEmptyView.getVisibility()).isEqualTo(View.VISIBLE);
141     }
142 
143     @Test
testUpdateEmptyView_containerNull_emptyViewGone()144     public void testUpdateEmptyView_containerNull_emptyViewGone() {
145         doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
146 
147         mFragment.updateEmptyView();
148 
149         assertThat(mEmptyView.getVisibility()).isEqualTo(View.GONE);
150     }
151 
152     @Test
153     @Config(shadows = ShadowFragment.class)
onCreate_hasExtraFragmentKey_shouldExpandPreferences()154     public void onCreate_hasExtraFragmentKey_shouldExpandPreferences() {
155         doReturn(mContext.getTheme()).when(mActivity).getTheme();
156         doReturn(mContext.getResources()).when(mFragment).getResources();
157         doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
158         final Bundle bundle = new Bundle();
159         bundle.putString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, "test_key");
160         when(mFragment.getArguments()).thenReturn(bundle);
161 
162         mFragment.onCreate(null /* icicle */);
163 
164         verify(mPreferenceScreen).setInitialExpandedChildrenCount(Integer.MAX_VALUE);
165     }
166 
167     @Test
168     @Config(shadows = ShadowFragment.class)
onCreate_noPreferenceScreen_shouldNotCrash()169     public void onCreate_noPreferenceScreen_shouldNotCrash() {
170         doReturn(mContext.getTheme()).when(mActivity).getTheme();
171         doReturn(mContext.getResources()).when(mFragment).getResources();
172         doReturn(null).when(mFragment).getPreferenceScreen();
173         final Bundle bundle = new Bundle();
174         bundle.putString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, "test_key");
175         when(mFragment.getArguments()).thenReturn(bundle);
176 
177         mFragment.onCreate(null /* icicle */);
178         // no crash
179     }
180 
181     @Test
checkAvailablePrefs_selfAvialbalePreferenceNotAvailable_shouldHidePreference()182     public void checkAvailablePrefs_selfAvialbalePreferenceNotAvailable_shouldHidePreference() {
183         doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
184         final WorkOnlyCategory workOnlyCategory = mock(WorkOnlyCategory.class);
185         when(mPreferenceScreen.getPreferenceCount()).thenReturn(1);
186         when(mPreferenceScreen.getPreference(0)).thenReturn(workOnlyCategory);
187         when(workOnlyCategory.isAvailable(any(Context.class))).thenReturn(false);
188 
189         mFragment.checkAvailablePrefs(mPreferenceScreen);
190 
191         verify(mPreferenceScreen, never()).removePreference(workOnlyCategory);
192         verify(workOnlyCategory).setVisible(false);
193     }
194 
195     @Test
showPinnedHeader_shouldBeVisible()196     public void showPinnedHeader_shouldBeVisible() {
197         mFragment.mPinnedHeaderFrameLayout = new FrameLayout(mContext);
198 
199         mFragment.showPinnedHeader(true);
200 
201         assertThat(mFragment.mPinnedHeaderFrameLayout.getVisibility()).isEqualTo(View.VISIBLE);
202     }
203 
204     @Test
hidePinnedHeader_shouldBeInvisible()205     public void hidePinnedHeader_shouldBeInvisible() {
206         mFragment.mPinnedHeaderFrameLayout = new FrameLayout(mContext);
207 
208         mFragment.showPinnedHeader(false);
209 
210         assertThat(mFragment.mPinnedHeaderFrameLayout.getVisibility()).isEqualTo(View.INVISIBLE);
211     }
212 
213     public static class TestFragment extends SettingsPreferenceFragment {
214 
215         @Override
getMetricsCategory()216         public int getMetricsCategory() {
217             return 0;
218         }
219     }
220 }
221