Loading src/com/android/settings/search2/SavedQueryViewHolder.java +1 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ public class SavedQueryViewHolder extends SearchViewHolder { public SavedQueryViewHolder(View view) { super(view); titleView = (TextView) view.findViewById(android.R.id.title); titleView = view.findViewById(android.R.id.title); } @Override Loading src/com/android/settings/search2/SearchFragment.java +24 −20 Original line number Diff line number Diff line Loading @@ -45,9 +45,8 @@ import com.android.settings.overlay.FeatureFactory; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; public class SearchFragment extends InstrumentedFragment implements SearchView.OnQueryTextListener, LoaderManager.LoaderCallbacks<List<? extends SearchResult>> { public class SearchFragment extends InstrumentedFragment implements SearchView.OnQueryTextListener, LoaderManager.LoaderCallbacks<List<? extends SearchResult>> { private static final String TAG = "SearchFragment"; @VisibleForTesting Loading @@ -66,7 +65,7 @@ public class SearchFragment extends InstrumentedFragment implements private static final int NUM_QUERY_LOADERS = 2; @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) AtomicInteger mUnfinishedLoadersCount = new AtomicInteger(NUM_QUERY_LOADERS);; AtomicInteger mUnfinishedLoadersCount = new AtomicInteger(NUM_QUERY_LOADERS); // Logging @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) Loading @@ -93,8 +92,7 @@ public class SearchFragment extends InstrumentedFragment implements private LinearLayout mNoResultsView; @VisibleForTesting final RecyclerView.OnScrollListener mScrollListener = new RecyclerView.OnScrollListener() { final RecyclerView.OnScrollListener mScrollListener = new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { if (dy != 0) { Loading Loading @@ -155,12 +153,12 @@ public class SearchFragment extends InstrumentedFragment implements public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View view = inflater.inflate(R.layout.search_panel_2, container, false); mResultsRecyclerView = (RecyclerView) view.findViewById(R.id.list_results); mResultsRecyclerView = view.findViewById(R.id.list_results); mResultsRecyclerView.setAdapter(mSearchAdapter); mResultsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); mResultsRecyclerView.addOnScrollListener(mScrollListener); mNoResultsView = (LinearLayout) view.findViewById(R.id.no_results_layout); mNoResultsView = view.findViewById(R.id.no_results_layout); return view; } Loading Loading @@ -245,16 +243,20 @@ public class SearchFragment extends InstrumentedFragment implements @Override public void onLoadFinished(Loader<List<? extends SearchResult>> loader, List<? extends SearchResult> data) { mSearchAdapter.addResultsToMap(data, loader.getClass().getName()); if (mUnfinishedLoadersCount.decrementAndGet() == 0) { final int resultCount = mSearchAdapter.mergeResults(); mSearchFeatureProvider.showFeedbackButton(this, getView()); if (resultCount == 0) { mNoResultsView.setVisibility(View.VISIBLE); final int resultCount; switch (loader.getId()) { case LOADER_ID_RECENTS: resultCount = mSearchAdapter.displaySavedQuery(data); break; default: mSearchAdapter.addSearchResults(data, loader.getClass().getName()); if (mUnfinishedLoadersCount.decrementAndGet() != 0) { return; } resultCount = mSearchAdapter.displaySearchResults(); } mNoResultsView.setVisibility(resultCount == 0 ? View.VISIBLE : View.GONE); mSearchFeatureProvider.showFeedbackButton(this, getView()); } @Override Loading @@ -267,6 +269,8 @@ public class SearchFragment extends InstrumentedFragment implements public void onSavedQueryClicked(CharSequence query) { final String queryString = query.toString(); mMetricsFeatureProvider.action(getContext(), MetricsProto.MetricsEvent.ACTION_CLICK_SETTINGS_SEARCH_SAVED_QUERY); mSearchView.setQuery(queryString, false /* submit */); onQueryTextChange(queryString); } Loading src/com/android/settings/search2/SearchResultsAdapter.java +22 −10 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ package com.android.settings.search2; import android.content.Context; import android.support.annotation.MainThread; import android.support.annotation.VisibleForTesting; import android.support.v7.widget.RecyclerView.Adapter; import android.support.v7.widget.RecyclerView; import android.util.ArrayMap; import android.view.LayoutInflater; import android.view.View; Loading @@ -32,10 +32,10 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import static com.android.settings.search2.SearchResult.TOP_RANK; import static com.android.settings.search2.SearchResult.BOTTOM_RANK; import static com.android.settings.search2.SearchResult.TOP_RANK; public class SearchResultsAdapter extends Adapter<SearchViewHolder> { public class SearchResultsAdapter extends RecyclerView.Adapter<SearchViewHolder> { private final List<SearchResult> mSearchResults; private final SearchFragment mFragment; Loading Loading @@ -91,16 +91,28 @@ public class SearchResultsAdapter extends Adapter<SearchViewHolder> { /** * Store the results from each of the loaders to be merged when all loaders are finished. * @param freshResults are the results from the loader. * * @param results the results from the loader. * @param loaderClassName class name of the loader. */ @MainThread public void addResultsToMap(List<? extends SearchResult> freshResults, String loaderClassName) { if (freshResults == null) { public void addSearchResults(List<? extends SearchResult> results, String loaderClassName) { if (results == null) { return; } mResultsMap.put(loaderClassName, freshResults); mResultsMap.put(loaderClassName, results); } /** * Displays recent searched queries. * * @return The number of saved queries to display */ public int displaySavedQuery(List<? extends SearchResult> data) { clearResults(); mSearchResults.addAll(data); notifyDataSetChanged(); return mSearchResults.size(); } /** Loading @@ -109,7 +121,7 @@ public class SearchResultsAdapter extends Adapter<SearchViewHolder> { * * @return Number of matched results */ public int mergeResults() { public int displaySearchResults() { final List<? extends SearchResult> databaseResults = mResultsMap .get(DatabaseResultLoader.class.getName()); final List<? extends SearchResult> installedAppResults = mResultsMap Loading tests/robotests/src/com/android/settings/search/SearchResultsAdapterTest.java +9 −14 Original line number Diff line number Diff line Loading @@ -21,9 +21,9 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.drawable.Drawable; import android.view.ViewGroup; import android.widget.FrameLayout; import com.android.settings.R; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; Loading @@ -34,13 +34,12 @@ import com.android.settings.search2.InstalledAppResultLoader; import com.android.settings.search2.IntentPayload; import com.android.settings.search2.IntentSearchViewHolder; import com.android.settings.search2.ResultPayload; import com.android.settings.search2.SearchActivity; import com.android.settings.search2.SearchFragment; import com.android.settings.search2.SearchResult; import com.android.settings.search2.SearchResult.Builder; import com.android.settings.search2.SearchResultsAdapter; import com.android.settings.search2.SearchViewHolder; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -48,15 +47,11 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.Robolectric; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowApplication; import org.robolectric.shadows.ShadowViewGroup; import org.robolectric.util.ActivityController; import java.util.ArrayList; import java.util.List; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doReturn; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) Loading Loading @@ -85,15 +80,15 @@ public class SearchResultsAdapterTest { @Test public void testSingleSourceMerge_ExactCopyReturned() { ArrayList<SearchResult> intentResults = getIntentSampleResults(); mAdapter.addResultsToMap(intentResults, mLoaderClassName); mAdapter.mergeResults(); mAdapter.addSearchResults(intentResults, mLoaderClassName); mAdapter.displaySearchResults(); List<SearchResult> updatedResults = mAdapter.getSearchResults(); assertThat(updatedResults).containsAllIn(intentResults); } @Test public void testCreatViewHolder_ReturnsIntentResult() { public void testCreateViewHolder_ReturnsIntentResult() { ViewGroup group = new FrameLayout(mContext); SearchViewHolder view = mAdapter.onCreateViewHolder(group, ResultPayload.PayloadType.INTENT); Loading @@ -101,7 +96,7 @@ public class SearchResultsAdapterTest { } @Test public void testCreatViewHolder_ReturnsInlineSwitchResult() { public void testCreateViewHolder_ReturnsInlineSwitchResult() { ViewGroup group = new FrameLayout(mContext); SearchViewHolder view = mAdapter.onCreateViewHolder(group, ResultPayload.PayloadType.INLINE_SWITCH); Loading @@ -110,11 +105,11 @@ public class SearchResultsAdapterTest { @Test public void testEndToEndSearch_ProperResultsMerged() { mAdapter.addResultsToMap(getDummyAppResults(), mAdapter.addSearchResults(getDummyAppResults(), InstalledAppResultLoader.class.getName()); mAdapter.addResultsToMap(getDummyDbResults(), mAdapter.addSearchResults(getDummyDbResults(), DatabaseResultLoader.class.getName()); int count = mAdapter.mergeResults(); int count = mAdapter.displaySearchResults(); List<SearchResult> results = mAdapter.getSearchResults(); assertThat(results.get(0).title).isEqualTo("alpha"); Loading tests/robotests/src/com/android/settings/search2/SavedQueryViewHolderTest.java 0 → 100644 +67 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.search2; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import com.android.settings.R; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class SavedQueryViewHolderTest { @Mock private SearchFragment mSearchFragment; private Context mContext; private SavedQueryViewHolder mHolder; private View mView; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; mView = LayoutInflater.from(mContext) .inflate(R.layout.search_saved_query_item, null); mHolder = new SavedQueryViewHolder(mView); } @Test public void onBind_shouldBindClickCallback() { final SearchResult result = mock(SearchResult.class); mHolder.onBind(mSearchFragment, result); mView.performClick(); verify(mSearchFragment).onSavedQueryClicked(any(CharSequence.class)); } } Loading
src/com/android/settings/search2/SavedQueryViewHolder.java +1 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ public class SavedQueryViewHolder extends SearchViewHolder { public SavedQueryViewHolder(View view) { super(view); titleView = (TextView) view.findViewById(android.R.id.title); titleView = view.findViewById(android.R.id.title); } @Override Loading
src/com/android/settings/search2/SearchFragment.java +24 −20 Original line number Diff line number Diff line Loading @@ -45,9 +45,8 @@ import com.android.settings.overlay.FeatureFactory; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; public class SearchFragment extends InstrumentedFragment implements SearchView.OnQueryTextListener, LoaderManager.LoaderCallbacks<List<? extends SearchResult>> { public class SearchFragment extends InstrumentedFragment implements SearchView.OnQueryTextListener, LoaderManager.LoaderCallbacks<List<? extends SearchResult>> { private static final String TAG = "SearchFragment"; @VisibleForTesting Loading @@ -66,7 +65,7 @@ public class SearchFragment extends InstrumentedFragment implements private static final int NUM_QUERY_LOADERS = 2; @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) AtomicInteger mUnfinishedLoadersCount = new AtomicInteger(NUM_QUERY_LOADERS);; AtomicInteger mUnfinishedLoadersCount = new AtomicInteger(NUM_QUERY_LOADERS); // Logging @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) Loading @@ -93,8 +92,7 @@ public class SearchFragment extends InstrumentedFragment implements private LinearLayout mNoResultsView; @VisibleForTesting final RecyclerView.OnScrollListener mScrollListener = new RecyclerView.OnScrollListener() { final RecyclerView.OnScrollListener mScrollListener = new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { if (dy != 0) { Loading Loading @@ -155,12 +153,12 @@ public class SearchFragment extends InstrumentedFragment implements public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View view = inflater.inflate(R.layout.search_panel_2, container, false); mResultsRecyclerView = (RecyclerView) view.findViewById(R.id.list_results); mResultsRecyclerView = view.findViewById(R.id.list_results); mResultsRecyclerView.setAdapter(mSearchAdapter); mResultsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); mResultsRecyclerView.addOnScrollListener(mScrollListener); mNoResultsView = (LinearLayout) view.findViewById(R.id.no_results_layout); mNoResultsView = view.findViewById(R.id.no_results_layout); return view; } Loading Loading @@ -245,16 +243,20 @@ public class SearchFragment extends InstrumentedFragment implements @Override public void onLoadFinished(Loader<List<? extends SearchResult>> loader, List<? extends SearchResult> data) { mSearchAdapter.addResultsToMap(data, loader.getClass().getName()); if (mUnfinishedLoadersCount.decrementAndGet() == 0) { final int resultCount = mSearchAdapter.mergeResults(); mSearchFeatureProvider.showFeedbackButton(this, getView()); if (resultCount == 0) { mNoResultsView.setVisibility(View.VISIBLE); final int resultCount; switch (loader.getId()) { case LOADER_ID_RECENTS: resultCount = mSearchAdapter.displaySavedQuery(data); break; default: mSearchAdapter.addSearchResults(data, loader.getClass().getName()); if (mUnfinishedLoadersCount.decrementAndGet() != 0) { return; } resultCount = mSearchAdapter.displaySearchResults(); } mNoResultsView.setVisibility(resultCount == 0 ? View.VISIBLE : View.GONE); mSearchFeatureProvider.showFeedbackButton(this, getView()); } @Override Loading @@ -267,6 +269,8 @@ public class SearchFragment extends InstrumentedFragment implements public void onSavedQueryClicked(CharSequence query) { final String queryString = query.toString(); mMetricsFeatureProvider.action(getContext(), MetricsProto.MetricsEvent.ACTION_CLICK_SETTINGS_SEARCH_SAVED_QUERY); mSearchView.setQuery(queryString, false /* submit */); onQueryTextChange(queryString); } Loading
src/com/android/settings/search2/SearchResultsAdapter.java +22 −10 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ package com.android.settings.search2; import android.content.Context; import android.support.annotation.MainThread; import android.support.annotation.VisibleForTesting; import android.support.v7.widget.RecyclerView.Adapter; import android.support.v7.widget.RecyclerView; import android.util.ArrayMap; import android.view.LayoutInflater; import android.view.View; Loading @@ -32,10 +32,10 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import static com.android.settings.search2.SearchResult.TOP_RANK; import static com.android.settings.search2.SearchResult.BOTTOM_RANK; import static com.android.settings.search2.SearchResult.TOP_RANK; public class SearchResultsAdapter extends Adapter<SearchViewHolder> { public class SearchResultsAdapter extends RecyclerView.Adapter<SearchViewHolder> { private final List<SearchResult> mSearchResults; private final SearchFragment mFragment; Loading Loading @@ -91,16 +91,28 @@ public class SearchResultsAdapter extends Adapter<SearchViewHolder> { /** * Store the results from each of the loaders to be merged when all loaders are finished. * @param freshResults are the results from the loader. * * @param results the results from the loader. * @param loaderClassName class name of the loader. */ @MainThread public void addResultsToMap(List<? extends SearchResult> freshResults, String loaderClassName) { if (freshResults == null) { public void addSearchResults(List<? extends SearchResult> results, String loaderClassName) { if (results == null) { return; } mResultsMap.put(loaderClassName, freshResults); mResultsMap.put(loaderClassName, results); } /** * Displays recent searched queries. * * @return The number of saved queries to display */ public int displaySavedQuery(List<? extends SearchResult> data) { clearResults(); mSearchResults.addAll(data); notifyDataSetChanged(); return mSearchResults.size(); } /** Loading @@ -109,7 +121,7 @@ public class SearchResultsAdapter extends Adapter<SearchViewHolder> { * * @return Number of matched results */ public int mergeResults() { public int displaySearchResults() { final List<? extends SearchResult> databaseResults = mResultsMap .get(DatabaseResultLoader.class.getName()); final List<? extends SearchResult> installedAppResults = mResultsMap Loading
tests/robotests/src/com/android/settings/search/SearchResultsAdapterTest.java +9 −14 Original line number Diff line number Diff line Loading @@ -21,9 +21,9 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.drawable.Drawable; import android.view.ViewGroup; import android.widget.FrameLayout; import com.android.settings.R; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; Loading @@ -34,13 +34,12 @@ import com.android.settings.search2.InstalledAppResultLoader; import com.android.settings.search2.IntentPayload; import com.android.settings.search2.IntentSearchViewHolder; import com.android.settings.search2.ResultPayload; import com.android.settings.search2.SearchActivity; import com.android.settings.search2.SearchFragment; import com.android.settings.search2.SearchResult; import com.android.settings.search2.SearchResult.Builder; import com.android.settings.search2.SearchResultsAdapter; import com.android.settings.search2.SearchViewHolder; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -48,15 +47,11 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.Robolectric; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowApplication; import org.robolectric.shadows.ShadowViewGroup; import org.robolectric.util.ActivityController; import java.util.ArrayList; import java.util.List; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doReturn; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) Loading Loading @@ -85,15 +80,15 @@ public class SearchResultsAdapterTest { @Test public void testSingleSourceMerge_ExactCopyReturned() { ArrayList<SearchResult> intentResults = getIntentSampleResults(); mAdapter.addResultsToMap(intentResults, mLoaderClassName); mAdapter.mergeResults(); mAdapter.addSearchResults(intentResults, mLoaderClassName); mAdapter.displaySearchResults(); List<SearchResult> updatedResults = mAdapter.getSearchResults(); assertThat(updatedResults).containsAllIn(intentResults); } @Test public void testCreatViewHolder_ReturnsIntentResult() { public void testCreateViewHolder_ReturnsIntentResult() { ViewGroup group = new FrameLayout(mContext); SearchViewHolder view = mAdapter.onCreateViewHolder(group, ResultPayload.PayloadType.INTENT); Loading @@ -101,7 +96,7 @@ public class SearchResultsAdapterTest { } @Test public void testCreatViewHolder_ReturnsInlineSwitchResult() { public void testCreateViewHolder_ReturnsInlineSwitchResult() { ViewGroup group = new FrameLayout(mContext); SearchViewHolder view = mAdapter.onCreateViewHolder(group, ResultPayload.PayloadType.INLINE_SWITCH); Loading @@ -110,11 +105,11 @@ public class SearchResultsAdapterTest { @Test public void testEndToEndSearch_ProperResultsMerged() { mAdapter.addResultsToMap(getDummyAppResults(), mAdapter.addSearchResults(getDummyAppResults(), InstalledAppResultLoader.class.getName()); mAdapter.addResultsToMap(getDummyDbResults(), mAdapter.addSearchResults(getDummyDbResults(), DatabaseResultLoader.class.getName()); int count = mAdapter.mergeResults(); int count = mAdapter.displaySearchResults(); List<SearchResult> results = mAdapter.getSearchResults(); assertThat(results.get(0).title).isEqualTo("alpha"); Loading
tests/robotests/src/com/android/settings/search2/SavedQueryViewHolderTest.java 0 → 100644 +67 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.search2; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import com.android.settings.R; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class SavedQueryViewHolderTest { @Mock private SearchFragment mSearchFragment; private Context mContext; private SavedQueryViewHolder mHolder; private View mView; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; mView = LayoutInflater.from(mContext) .inflate(R.layout.search_saved_query_item, null); mHolder = new SavedQueryViewHolder(mView); } @Test public void onBind_shouldBindClickCallback() { final SearchResult result = mock(SearchResult.class); mHolder.onBind(mSearchFragment, result); mView.performClick(); verify(mSearchFragment).onSavedQueryClicked(any(CharSequence.class)); } }