blob: 36b6f01dc03359ad68e58c14e729e3cccc93ceb5 [file] [log] [blame]
Alina Zaidic6fe0dd2021-03-03 18:40:01 +00001/*
2 * Copyright (C) 2021 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
17package com.android.launcher3.widget.picker.search;
18
19import static android.os.Looper.getMainLooper;
20
Sunny Goyalce6cc7e2021-03-30 16:51:08 -070021import static org.junit.Assert.assertEquals;
Alina Zaidic6fe0dd2021-03-03 18:40:01 +000022import static org.mockito.ArgumentMatchers.any;
Sunny Goyalce6cc7e2021-03-30 16:51:08 -070023import static org.mockito.ArgumentMatchers.argThat;
Alina Zaidic6fe0dd2021-03-03 18:40:01 +000024import static org.mockito.ArgumentMatchers.matches;
Sunny Goyalce6cc7e2021-03-30 16:51:08 -070025import static org.mockito.Mockito.doAnswer;
26import static org.mockito.Mockito.doReturn;
Alina Zaidic6fe0dd2021-03-03 18:40:01 +000027import static org.mockito.Mockito.verify;
28import static org.robolectric.Shadows.shadowOf;
29
Sunny Goyalce6cc7e2021-03-30 16:51:08 -070030import android.appwidget.AppWidgetProviderInfo;
31import android.content.ComponentName;
32import android.content.Context;
33import android.graphics.Bitmap;
34import android.os.UserHandle;
35
36import com.android.launcher3.InvariantDeviceProfile;
37import com.android.launcher3.icons.BitmapInfo;
38import com.android.launcher3.icons.ComponentWithLabel;
39import com.android.launcher3.icons.IconCache;
40import com.android.launcher3.model.WidgetItem;
41import com.android.launcher3.model.data.PackageItemInfo;
42import com.android.launcher3.popup.PopupDataProvider;
Alina Zaidic6fe0dd2021-03-03 18:40:01 +000043import com.android.launcher3.search.SearchCallback;
Sunny Goyalce6cc7e2021-03-30 16:51:08 -070044import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
Alina Zaidic6fe0dd2021-03-03 18:40:01 +000045import com.android.launcher3.widget.model.WidgetsListBaseEntry;
Sunny Goyalce6cc7e2021-03-30 16:51:08 -070046import com.android.launcher3.widget.model.WidgetsListContentEntry;
47import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
48import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry;
Alina Zaidic6fe0dd2021-03-03 18:40:01 +000049
50import org.junit.Before;
51import org.junit.Test;
52import org.junit.runner.RunWith;
Alina Zaidic6fe0dd2021-03-03 18:40:01 +000053import org.mockito.Mock;
54import org.mockito.MockitoAnnotations;
55import org.robolectric.RobolectricTestRunner;
Sunny Goyalce6cc7e2021-03-30 16:51:08 -070056import org.robolectric.RuntimeEnvironment;
57import org.robolectric.shadows.ShadowPackageManager;
58import org.robolectric.util.ReflectionHelpers;
Alina Zaidic6fe0dd2021-03-03 18:40:01 +000059
60import java.util.ArrayList;
Sunny Goyalce6cc7e2021-03-30 16:51:08 -070061import java.util.Collections;
Alina Zaidic6fe0dd2021-03-03 18:40:01 +000062import java.util.List;
Alina Zaidic6fe0dd2021-03-03 18:40:01 +000063
64@RunWith(RobolectricTestRunner.class)
65public class SimpleWidgetsSearchAlgorithmTest {
66
Sunny Goyalce6cc7e2021-03-30 16:51:08 -070067 @Mock private IconCache mIconCache;
68
69 private InvariantDeviceProfile mTestProfile;
70 private WidgetsListHeaderEntry mCalendarHeaderEntry;
71 private WidgetsListContentEntry mCalendarContentEntry;
72 private WidgetsListHeaderEntry mCameraHeaderEntry;
73 private WidgetsListContentEntry mCameraContentEntry;
74 private WidgetsListHeaderEntry mClockHeaderEntry;
75 private WidgetsListContentEntry mClockContentEntry;
76 private Context mContext;
77
Alina Zaidic6fe0dd2021-03-03 18:40:01 +000078 private SimpleWidgetsSearchAlgorithm mSimpleWidgetsSearchAlgorithm;
79 @Mock
Sunny Goyalce6cc7e2021-03-30 16:51:08 -070080 private PopupDataProvider mDataProvider;
Alina Zaidic6fe0dd2021-03-03 18:40:01 +000081 @Mock
82 private SearchCallback<WidgetsListBaseEntry> mSearchCallback;
Alina Zaidic6fe0dd2021-03-03 18:40:01 +000083
84 @Before
85 public void setUp() {
86 MockitoAnnotations.initMocks(this);
Sunny Goyalce6cc7e2021-03-30 16:51:08 -070087 doAnswer(invocation -> {
88 ComponentWithLabel componentWithLabel = (ComponentWithLabel) invocation.getArgument(0);
89 return componentWithLabel.getComponent().getShortClassName();
90 }).when(mIconCache).getTitleNoCache(any());
91 mTestProfile = new InvariantDeviceProfile();
92 mTestProfile.numRows = 5;
93 mTestProfile.numColumns = 5;
94 mContext = RuntimeEnvironment.application;
95
96 mCalendarHeaderEntry =
97 createWidgetsHeaderEntry("com.example.android.Calendar", "Calendar", 2);
98 mCalendarContentEntry =
99 createWidgetsContentEntry("com.example.android.Calendar", "Calendar", 2);
100 mCameraHeaderEntry = createWidgetsHeaderEntry("com.example.android.Camera", "Camera", 11);
101 mCameraContentEntry = createWidgetsContentEntry("com.example.android.Camera", "Camera", 11);
102 mClockHeaderEntry = createWidgetsHeaderEntry("com.example.android.Clock", "Clock", 3);
103 mClockContentEntry = createWidgetsContentEntry("com.example.android.Clock", "Clock", 3);
104
105
106 mSimpleWidgetsSearchAlgorithm = new SimpleWidgetsSearchAlgorithm(mDataProvider);
107 doReturn(Collections.EMPTY_LIST).when(mDataProvider).getAllWidgets();
Alina Zaidic6fe0dd2021-03-03 18:40:01 +0000108 }
109
110 @Test
Sunny Goyalce6cc7e2021-03-30 16:51:08 -0700111 public void filter_shouldMatchOnAppName() {
112 doReturn(List.of(mCalendarHeaderEntry, mCalendarContentEntry, mCameraHeaderEntry,
113 mCameraContentEntry, mClockHeaderEntry, mClockContentEntry))
114 .when(mDataProvider)
115 .getAllWidgets();
Alina Zaidic6fe0dd2021-03-03 18:40:01 +0000116
Sunny Goyalce6cc7e2021-03-30 16:51:08 -0700117 assertEquals(List.of(
118 new WidgetsListSearchHeaderEntry(
119 mCalendarHeaderEntry.mPkgItem,
120 mCalendarHeaderEntry.mTitleSectionName,
121 mCalendarHeaderEntry.mWidgets),
122 mCalendarContentEntry,
123 new WidgetsListSearchHeaderEntry(
124 mCameraHeaderEntry.mPkgItem,
125 mCameraHeaderEntry.mTitleSectionName,
126 mCameraHeaderEntry.mWidgets),
127 mCameraContentEntry),
128 SimpleWidgetsSearchAlgorithm.getFilteredWidgets(mDataProvider, "Ca"));
Alina Zaidic6fe0dd2021-03-03 18:40:01 +0000129 }
130
131 @Test
Sunny Goyalce6cc7e2021-03-30 16:51:08 -0700132 public void filter_shouldMatchOnWidgetLabel() {
133 doReturn(List.of(mCalendarHeaderEntry, mCalendarContentEntry, mCameraHeaderEntry,
134 mCameraContentEntry))
135 .when(mDataProvider)
136 .getAllWidgets();
Alina Zaidic6fe0dd2021-03-03 18:40:01 +0000137
Sunny Goyalce6cc7e2021-03-30 16:51:08 -0700138 assertEquals(List.of(
139 new WidgetsListSearchHeaderEntry(
140 mCalendarHeaderEntry.mPkgItem,
141 mCalendarHeaderEntry.mTitleSectionName,
142 mCalendarHeaderEntry.mWidgets.subList(1, 2)),
143 new WidgetsListContentEntry(
144 mCalendarHeaderEntry.mPkgItem,
145 mCalendarHeaderEntry.mTitleSectionName,
146 mCalendarHeaderEntry.mWidgets.subList(1, 2)),
147 new WidgetsListSearchHeaderEntry(
148 mCameraHeaderEntry.mPkgItem,
149 mCameraHeaderEntry.mTitleSectionName,
150 mCameraHeaderEntry.mWidgets.subList(1, 3)),
151 new WidgetsListContentEntry(
152 mCameraHeaderEntry.mPkgItem,
153 mCameraHeaderEntry.mTitleSectionName,
154 mCameraHeaderEntry.mWidgets.subList(1, 3))),
155 SimpleWidgetsSearchAlgorithm.getFilteredWidgets(mDataProvider, "Widget1"));
156 }
Alina Zaidic6fe0dd2021-03-03 18:40:01 +0000157
Sunny Goyalce6cc7e2021-03-30 16:51:08 -0700158 @Test
159 public void doSearch_shouldInformCallback() {
160 doReturn(List.of(mCalendarHeaderEntry, mCalendarContentEntry, mCameraHeaderEntry,
161 mCameraContentEntry, mClockHeaderEntry, mClockContentEntry))
162 .when(mDataProvider)
163 .getAllWidgets();
164 mSimpleWidgetsSearchAlgorithm.doSearch("Ca", mSearchCallback);
Alina Zaidic6fe0dd2021-03-03 18:40:01 +0000165 shadowOf(getMainLooper()).idle();
Sunny Goyalce6cc7e2021-03-30 16:51:08 -0700166 verify(mSearchCallback).onSearchResult(
167 matches("Ca"), argThat(a -> a != null && !a.isEmpty()));
168 }
169
170 private WidgetsListHeaderEntry createWidgetsHeaderEntry(String packageName, String appName,
171 int numOfWidgets) {
172 List<WidgetItem> widgetItems = generateWidgetItems(packageName, numOfWidgets);
173 PackageItemInfo pInfo = createPackageItemInfo(packageName, appName,
174 widgetItems.get(0).user);
175
176 return new WidgetsListHeaderEntry(pInfo, /* titleSectionName= */ "", widgetItems);
177 }
178
179 private WidgetsListContentEntry createWidgetsContentEntry(String packageName, String appName,
180 int numOfWidgets) {
181 List<WidgetItem> widgetItems = generateWidgetItems(packageName, numOfWidgets);
182 PackageItemInfo pInfo = createPackageItemInfo(packageName, appName,
183 widgetItems.get(0).user);
184
185 return new WidgetsListContentEntry(pInfo, /* titleSectionName= */ "", widgetItems);
186 }
187
188 private PackageItemInfo createPackageItemInfo(String packageName, String appName,
189 UserHandle userHandle) {
190 PackageItemInfo pInfo = new PackageItemInfo(packageName);
191 pInfo.title = appName;
192 pInfo.user = userHandle;
193 pInfo.bitmap = BitmapInfo.of(Bitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8), 0);
194 return pInfo;
195 }
196
197 private List<WidgetItem> generateWidgetItems(String packageName, int numOfWidgets) {
198 ShadowPackageManager packageManager = shadowOf(mContext.getPackageManager());
199 ArrayList<WidgetItem> widgetItems = new ArrayList<>();
200 for (int i = 0; i < numOfWidgets; i++) {
201 ComponentName cn = ComponentName.createRelative(packageName, ".SampleWidget" + i);
202 AppWidgetProviderInfo widgetInfo = new AppWidgetProviderInfo();
203 widgetInfo.provider = cn;
204 ReflectionHelpers.setField(widgetInfo, "providerInfo",
205 packageManager.addReceiverIfNotPresent(cn));
206
207 WidgetItem widgetItem = new WidgetItem(
208 LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, widgetInfo),
209 mTestProfile, mIconCache);
210 widgetItems.add(widgetItem);
211 }
212 return widgetItems;
Alina Zaidic6fe0dd2021-03-03 18:40:01 +0000213 }
214}