• 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.search2;
18 
19 import android.app.LoaderManager;
20 import android.content.Context;
21 import android.content.Loader;
22 import android.os.Bundle;
23 import android.view.View;
24 
25 import com.android.internal.logging.nano.MetricsProto;
26 import com.android.settings.R;
27 import com.android.settings.SettingsRobolectricTestRunner;
28 import com.android.settings.TestConfig;
29 import com.android.settings.search.IndexingCallback;
30 import com.android.settings.testutils.FakeFeatureFactory;
31 
32 import org.junit.Before;
33 import org.junit.Test;
34 import org.junit.runner.RunWith;
35 import org.mockito.Answers;
36 import org.mockito.Mock;
37 import org.mockito.MockitoAnnotations;
38 import org.robolectric.Robolectric;
39 import org.robolectric.RuntimeEnvironment;
40 import org.robolectric.annotation.Config;
41 import org.robolectric.util.ActivityController;
42 import org.robolectric.util.ReflectionHelpers;
43 
44 import java.util.List;
45 
46 import static com.google.common.truth.Truth.assertThat;
47 import static org.mockito.Matchers.any;
48 import static org.mockito.Matchers.anyString;
49 import static org.mockito.Matchers.eq;
50 import static org.mockito.Mockito.mock;
51 import static org.mockito.Mockito.never;
52 import static org.mockito.Mockito.spy;
53 import static org.mockito.Mockito.times;
54 import static org.mockito.Mockito.verify;
55 import static org.mockito.Mockito.when;
56 
57 @RunWith(SettingsRobolectricTestRunner.class)
58 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
59 public class SearchFragmentTest {
60 
61     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
62     private Context mContext;
63     @Mock
64     private DatabaseResultLoader mDatabaseResultLoader;
65     @Mock
66     private InstalledAppResultLoader mInstalledAppResultLoader;
67 
68     @Mock
69     private SavedQueryLoader mSavedQueryLoader;
70     @Mock
71     private SavedQueryController mSavedQueryController;
72     private FakeFeatureFactory mFeatureFactory;
73 
74     @Before
setUp()75     public void setUp() {
76         MockitoAnnotations.initMocks(this);
77 
78         FakeFeatureFactory.setupForTest(mContext);
79         mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
80     }
81 
82     @Test
screenRotate_shouldPersistQuery()83     public void screenRotate_shouldPersistQuery() {
84         when(mFeatureFactory.searchFeatureProvider
85                 .getDatabaseSearchLoader(any(Context.class), anyString()))
86                 .thenReturn(mDatabaseResultLoader);
87         when(mFeatureFactory.searchFeatureProvider
88                 .getInstalledAppSearchLoader(any(Context.class), anyString()))
89                 .thenReturn(mInstalledAppResultLoader);
90         when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
91                 .thenReturn(mSavedQueryLoader);
92 
93         final Bundle bundle = new Bundle();
94         final String testQuery = "test";
95         ActivityController<SearchActivity> activityController =
96                 Robolectric.buildActivity(SearchActivity.class);
97         activityController.setup();
98         SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager()
99                 .findFragmentById(R.id.main_content);
100 
101         ReflectionHelpers.setField(fragment, "mShowingSavedQuery", false);
102         fragment.mQuery = testQuery;
103 
104         activityController.saveInstanceState(bundle).pause().stop().destroy();
105 
106         activityController = Robolectric.buildActivity(SearchActivity.class);
107         activityController.setup(bundle);
108 
109         assertThat(fragment.mQuery).isEqualTo(testQuery);
110     }
111 
112     @Test
screenRotateEmptyString_ShouldNotCrash()113     public void screenRotateEmptyString_ShouldNotCrash() {
114         when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
115                 .thenReturn(mSavedQueryLoader);
116 
117         final Bundle bundle = new Bundle();
118         ActivityController<SearchActivity> activityController =
119                 Robolectric.buildActivity(SearchActivity.class);
120         activityController.setup();
121         SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager()
122                 .findFragmentById(R.id.main_content);
123         when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
124                 .thenReturn(true);
125 
126         fragment.mQuery = "";
127 
128         activityController.saveInstanceState(bundle).pause().stop().destroy();
129 
130         activityController = Robolectric.buildActivity(SearchActivity.class);
131         activityController.setup(bundle);
132 
133         verify(mFeatureFactory.searchFeatureProvider, never())
134                 .getDatabaseSearchLoader(any(Context.class), anyString());
135         verify(mFeatureFactory.searchFeatureProvider, never())
136                 .getInstalledAppSearchLoader(any(Context.class), anyString());
137     }
138 
139     @Test
queryTextChange_shouldTriggerLoader()140     public void queryTextChange_shouldTriggerLoader() {
141         when(mFeatureFactory.searchFeatureProvider
142                 .getDatabaseSearchLoader(any(Context.class), anyString()))
143                 .thenReturn(mDatabaseResultLoader);
144         when(mFeatureFactory.searchFeatureProvider
145                 .getInstalledAppSearchLoader(any(Context.class), anyString()))
146                 .thenReturn(mInstalledAppResultLoader);
147         when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
148                 .thenReturn(mSavedQueryLoader);
149 
150         final String testQuery = "test";
151         ActivityController<SearchActivity> activityController =
152                 Robolectric.buildActivity(SearchActivity.class);
153         activityController.setup();
154         SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager()
155                 .findFragmentById(R.id.main_content);
156         when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
157                 .thenReturn(true);
158 
159         fragment.onQueryTextChange(testQuery);
160         activityController.get().onBackPressed();
161 
162         activityController.pause().stop().destroy();
163 
164         verify(mFeatureFactory.metricsFeatureProvider, never()).action(
165                 any(Context.class),
166                 eq(MetricsProto.MetricsEvent.ACTION_LEAVE_SEARCH_RESULT_WITHOUT_QUERY));
167         verify(mFeatureFactory.metricsFeatureProvider).histogram(
168                 any(Context.class), eq(SearchFragment.RESULT_CLICK_COUNT), eq(0));
169         verify(mFeatureFactory.searchFeatureProvider)
170                 .getDatabaseSearchLoader(any(Context.class), anyString());
171         verify(mFeatureFactory.searchFeatureProvider)
172                 .getInstalledAppSearchLoader(any(Context.class), anyString());
173     }
174 
175     @Test
queryTextChangeToEmpty_shouldLoadSavedQuery()176     public void queryTextChangeToEmpty_shouldLoadSavedQuery() {
177         when(mFeatureFactory.searchFeatureProvider
178                 .getDatabaseSearchLoader(any(Context.class), anyString()))
179                 .thenReturn(mDatabaseResultLoader);
180         when(mFeatureFactory.searchFeatureProvider
181                 .getInstalledAppSearchLoader(any(Context.class), anyString()))
182                 .thenReturn(mInstalledAppResultLoader);
183         when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
184                 .thenReturn(mSavedQueryLoader);
185         ActivityController<SearchActivity> activityController =
186                 Robolectric.buildActivity(SearchActivity.class);
187         activityController.setup();
188         SearchFragment fragment = spy((SearchFragment) activityController.get().getFragmentManager()
189                 .findFragmentById(R.id.main_content));
190         when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
191                 .thenReturn(true);
192         ReflectionHelpers.setField(fragment, "mSavedQueryController", mSavedQueryController);
193         fragment.mQuery = "123";
194 
195         fragment.onQueryTextChange("");
196 
197         verify(mFeatureFactory.searchFeatureProvider, never())
198                 .getDatabaseSearchLoader(any(Context.class), anyString());
199         verify(mFeatureFactory.searchFeatureProvider, never())
200                 .getInstalledAppSearchLoader(any(Context.class), anyString());
201         verify(mSavedQueryController).loadSavedQueries();
202     }
203 
204     @Test
updateIndex_TriggerOnCreate()205     public void updateIndex_TriggerOnCreate() {
206         when(mFeatureFactory.searchFeatureProvider
207                 .getDatabaseSearchLoader(any(Context.class), anyString()))
208                 .thenReturn(mDatabaseResultLoader);
209         when(mFeatureFactory.searchFeatureProvider
210                 .getInstalledAppSearchLoader(any(Context.class), anyString()))
211                 .thenReturn(mInstalledAppResultLoader);
212         when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
213                 .thenReturn(mSavedQueryLoader);
214 
215         ActivityController<SearchActivity> activityController =
216                 Robolectric.buildActivity(SearchActivity.class);
217         activityController.setup();
218         SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager()
219                 .findFragmentById(R.id.main_content);
220         when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
221                 .thenReturn(true);
222 
223         fragment.onAttach(null);
224         verify(mFeatureFactory.searchFeatureProvider).updateIndex(any(Context.class),
225                 any(IndexingCallback.class));
226     }
227 
228     @Test
syncLoaders_MergeWhenAllLoadersDone()229     public void syncLoaders_MergeWhenAllLoadersDone() {
230         when(mFeatureFactory.searchFeatureProvider
231                 .getDatabaseSearchLoader(any(Context.class), anyString()))
232                 .thenReturn(new MockDBLoader(RuntimeEnvironment.application));
233         when(mFeatureFactory.searchFeatureProvider
234                 .getInstalledAppSearchLoader(any(Context.class), anyString()))
235                 .thenReturn(new MockAppLoader(RuntimeEnvironment.application));
236         when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
237                 .thenReturn(mSavedQueryLoader);
238 
239         ActivityController<SearchActivity> activityController =
240                 Robolectric.buildActivity(SearchActivity.class);
241         activityController.setup();
242 
243         SearchFragment fragment = (SearchFragment) spy(activityController.get().getFragmentManager()
244                 .findFragmentById(R.id.main_content));
245         when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
246                 .thenReturn(true);
247 
248         fragment.onQueryTextChange("non-empty");
249 
250         Robolectric.flushForegroundThreadScheduler();
251 
252         verify(fragment, times(2)).onLoadFinished(any(Loader.class), any(List.class));
253     }
254 
255     @Test
whenNoQuery_HideFeedbackIsCalled()256     public void whenNoQuery_HideFeedbackIsCalled() {
257         when(mFeatureFactory.searchFeatureProvider
258                 .getDatabaseSearchLoader(any(Context.class), anyString()))
259                 .thenReturn(new MockDBLoader(RuntimeEnvironment.application));
260         when(mFeatureFactory.searchFeatureProvider
261                 .getInstalledAppSearchLoader(any(Context.class), anyString()))
262                 .thenReturn(new MockAppLoader(RuntimeEnvironment.application));
263         when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
264                 .thenReturn(mSavedQueryLoader);
265 
266         ActivityController<SearchActivity> activityController =
267                 Robolectric.buildActivity(SearchActivity.class);
268         activityController.setup();
269         SearchFragment fragment = (SearchFragment) spy(activityController.get().getFragmentManager()
270                 .findFragmentById(R.id.main_content));
271         when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
272                 .thenReturn(true);
273         when(fragment.getLoaderManager()).thenReturn(mock(LoaderManager.class));
274 
275         fragment.onQueryTextChange("");
276         Robolectric.flushForegroundThreadScheduler();
277 
278         verify(mFeatureFactory.searchFeatureProvider).hideFeedbackButton();
279     }
280 
281     @Test
onLoadFinished_ShowsFeedback()282     public void onLoadFinished_ShowsFeedback() {
283         when(mFeatureFactory.searchFeatureProvider
284                 .getDatabaseSearchLoader(any(Context.class), anyString()))
285                 .thenReturn(new MockDBLoader(RuntimeEnvironment.application));
286         when(mFeatureFactory.searchFeatureProvider
287                 .getInstalledAppSearchLoader(any(Context.class), anyString()))
288                 .thenReturn(new MockAppLoader(RuntimeEnvironment.application));
289         when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
290                 .thenReturn(mSavedQueryLoader);
291         ActivityController<SearchActivity> activityController =
292                 Robolectric.buildActivity(SearchActivity.class);
293         activityController.setup();
294         SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager()
295                 .findFragmentById(R.id.main_content);
296         when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
297                 .thenReturn(true);
298 
299         fragment.onQueryTextChange("non-empty");
300         Robolectric.flushForegroundThreadScheduler();
301 
302         verify(mFeatureFactory.searchFeatureProvider).showFeedbackButton(any(SearchFragment.class),
303                 any(View.class));
304     }
305 
306     @Test
preIndexingFinished_isIndexingFinishedFlag_isFalse()307     public void preIndexingFinished_isIndexingFinishedFlag_isFalse() {
308         ActivityController<SearchActivity> activityController =
309                 Robolectric.buildActivity(SearchActivity.class);
310         activityController.setup();
311         SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager()
312                 .findFragmentById(R.id.main_content);
313 
314         when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
315                 .thenReturn(false);
316     }
317 
318     @Test
onIndexingFinished_notShowingSavedQuery_initLoaders()319     public void onIndexingFinished_notShowingSavedQuery_initLoaders() {
320         ActivityController<SearchActivity> activityController =
321                 Robolectric.buildActivity(SearchActivity.class);
322         activityController.setup();
323         SearchFragment fragment = (SearchFragment) spy(activityController.get().getFragmentManager()
324                 .findFragmentById(R.id.main_content));
325         final LoaderManager loaderManager = mock(LoaderManager.class);
326         when(fragment.getLoaderManager()).thenReturn(loaderManager);
327         fragment.mShowingSavedQuery = false;
328         fragment.mQuery = null;
329 
330         fragment.onIndexingFinished();
331 
332         verify(loaderManager).initLoader(eq(SearchFragment.LOADER_ID_DATABASE),
333                 eq(null), any(LoaderManager.LoaderCallbacks.class));
334         verify(loaderManager).initLoader(eq(SearchFragment.LOADER_ID_INSTALLED_APPS),
335                 eq(null), any(LoaderManager.LoaderCallbacks.class));
336     }
337 
338     @Test
onIndexingFinished_showingSavedQuery_loadsSavedQueries()339     public void onIndexingFinished_showingSavedQuery_loadsSavedQueries() {
340         ActivityController<SearchActivity> activityController =
341                 Robolectric.buildActivity(SearchActivity.class);
342         activityController.setup();
343         SearchFragment fragment = (SearchFragment) spy(activityController.get().getFragmentManager()
344                 .findFragmentById(R.id.main_content));
345         fragment.mShowingSavedQuery = true;
346         ReflectionHelpers.setField(fragment, "mSavedQueryController", mSavedQueryController);
347 
348         fragment.onIndexingFinished();
349 
350         verify(fragment.mSavedQueryController).loadSavedQueries();
351     }
352 
353     @Test
onIndexingFinished_noActivity_shouldNotCrash()354     public void onIndexingFinished_noActivity_shouldNotCrash() {
355         ActivityController<SearchActivity> activityController =
356             Robolectric.buildActivity(SearchActivity.class);
357         activityController.setup();
358         SearchFragment fragment = (SearchFragment) spy(activityController.get().getFragmentManager()
359             .findFragmentById(R.id.main_content));
360         when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
361             .thenReturn(true);
362         fragment.mQuery = "bright";
363         ReflectionHelpers.setField(fragment, "mLoaderManager", null);
364         ReflectionHelpers.setField(fragment, "mHost", null);
365 
366         fragment.onIndexingFinished();
367         // no crash
368     }
369 }
370