• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.launcher3.ui;
18 
19 import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
20 
21 import static com.android.launcher3.BubbleTextView.DISPLAY_ALL_APPS;
22 import static com.android.launcher3.BubbleTextView.DISPLAY_PREDICTION_ROW;
23 import static com.android.launcher3.config.FeatureFlags.ENABLE_TWOLINE_ALLAPPS;
24 
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertNotEquals;
27 
28 import android.content.Context;
29 import android.graphics.Typeface;
30 import android.view.ViewGroup;
31 
32 import com.android.launcher3.BubbleTextView;
33 import com.android.launcher3.Utilities;
34 import com.android.launcher3.model.data.ItemInfoWithIcon;
35 import com.android.launcher3.search.StringMatcherUtility;
36 import com.android.launcher3.util.ActivityContextWrapper;
37 import com.android.launcher3.util.IntArray;
38 import com.android.launcher3.util.TestUtil;
39 import com.android.launcher3.views.BaseDragLayer;
40 
41 import org.junit.Before;
42 import org.junit.Test;
43 
44 /**
45  * Unit tests for testing modifyTitleToSupportMultiLine() in BubbleTextView.java
46  * This class tests a couple of strings and uses the getMaxLines() to determine if the test passes.
47  * Verifying with getMaxLines() is sufficient since BubbleTextView can only be in one line or
48  * two lines, and this is enough to ensure whether the string should be specifically wrapped onto
49  * the second line and to ensure truncation.
50  */
51 public class BubbleTextViewTest {
52 
53     private static final StringMatcherUtility.StringMatcher
54             MATCHER = StringMatcherUtility.StringMatcher.getInstance();
55     private static final int ONE_LINE = 1;
56     private static final int TWO_LINE = 2;
57     private static final String TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT = "Battery Stats";
58     private static final String TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT_RESULT =
59             "Battery\nStats";
60     private static final String TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT =
61             "flutterappflorafy";
62     private static final String TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT =
63             "System UWB Field Test";
64     private static final String TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT_RESULT =
65             "System\nUWB Field Test";
66     private static final String TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT =
67             "LEGO®Builder";
68     private static final String TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT_RESULT =
69             "LEGO®\nBuilder";
70     private static final String EMPTY_STRING = "";
71     private static final int CHAR_CNT = 7;
72 
73     private BubbleTextView mBubbleTextView;
74     private ItemInfoWithIcon mItemInfoWithIcon;
75     private Context mContext;
76     private int mLimitedWidth;
77 
78     @Before
setUp()79     public void setUp() throws Exception {
80         Utilities.enableRunningInTestHarnessForTests();
81         mContext = new ActivityContextWrapper(getApplicationContext());
82         mBubbleTextView = new BubbleTextView(mContext);
83         mBubbleTextView.reset();
84 
85         BubbleTextView testView = new BubbleTextView(mContext);
86         testView.setTypeface(Typeface.MONOSPACE);
87         testView.setText("B");
88         // calculate the maxWidth of the textView by calculating the width of one monospace
89         // character * CHAR_CNT
90         mLimitedWidth =
91                 (int) (testView.getPaint().measureText(testView.getText().toString()) * CHAR_CNT);
92         // needed otherwise there is a NPE during setText() on checkForRelayout()
93         mBubbleTextView.setLayoutParams(
94                 new ViewGroup.LayoutParams(mLimitedWidth,
95                 BaseDragLayer.LayoutParams.WRAP_CONTENT));
96         mItemInfoWithIcon = new ItemInfoWithIcon() {
97             @Override
98             public ItemInfoWithIcon clone() {
99                 return null;
100             }
101         };
102     }
103 
104     @Test
testEmptyString_flagOn()105     public void testEmptyString_flagOn() {
106         try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
107             mItemInfoWithIcon.title = EMPTY_STRING;
108             mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
109             mBubbleTextView.applyLabel(mItemInfoWithIcon);
110             mBubbleTextView.setTypeface(Typeface.MONOSPACE);
111             mBubbleTextView.measure(mLimitedWidth, 0);
112             mBubbleTextView.onPreDraw();
113             assertNotEquals(TWO_LINE, mBubbleTextView.getMaxLines());
114         } catch (Exception e) {
115             throw new RuntimeException(e);
116         }
117     }
118 
119     @Test
testEmptyString_flagOff()120     public void testEmptyString_flagOff() {
121         try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) {
122             mItemInfoWithIcon.title = EMPTY_STRING;
123             mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
124             mBubbleTextView.applyLabel(mItemInfoWithIcon);
125             mBubbleTextView.setTypeface(Typeface.MONOSPACE);
126             mBubbleTextView.measure(mLimitedWidth, 0);
127             mBubbleTextView.onPreDraw();
128             assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
129         } catch (Exception e) {
130             throw new RuntimeException(e);
131         }
132     }
133 
134     @Test
testStringWithSpaceLongerThanCharLimit_flagOn()135     public void testStringWithSpaceLongerThanCharLimit_flagOn() {
136         try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
137             // test string: "Battery Stats"
138             mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
139             mBubbleTextView.applyLabel(mItemInfoWithIcon);
140             mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
141             mBubbleTextView.setTypeface(Typeface.MONOSPACE);
142             mBubbleTextView.measure(mLimitedWidth, 0);
143             mBubbleTextView.onPreDraw();
144             assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
145         } catch (Exception e) {
146             throw new RuntimeException(e);
147         }
148     }
149 
150     @Test
testStringWithSpaceLongerThanCharLimit_flagOff()151     public void testStringWithSpaceLongerThanCharLimit_flagOff() {
152         try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) {
153             // test string: "Battery Stats"
154             mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
155             mBubbleTextView.applyLabel(mItemInfoWithIcon);
156             mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
157             mBubbleTextView.setTypeface(Typeface.MONOSPACE);
158             mBubbleTextView.measure(mLimitedWidth, 0);
159             mBubbleTextView.onPreDraw();
160             assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
161         } catch (Exception e) {
162             throw new RuntimeException(e);
163         }
164     }
165 
166     @Test
testLongStringNoSpaceLongerThanCharLimit_flagOn()167     public void testLongStringNoSpaceLongerThanCharLimit_flagOn() {
168         try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
169             // test string: "flutterappflorafy"
170             mItemInfoWithIcon.title = TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT;
171             mBubbleTextView.applyLabel(mItemInfoWithIcon);
172             mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
173             mBubbleTextView.setTypeface(Typeface.MONOSPACE);
174             mBubbleTextView.measure(mLimitedWidth, 0);
175             mBubbleTextView.onPreDraw();
176             assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
177         } catch (Exception e) {
178             throw new RuntimeException(e);
179         }
180     }
181 
182     @Test
testLongStringNoSpaceLongerThanCharLimit_flagOff()183     public void testLongStringNoSpaceLongerThanCharLimit_flagOff() {
184         try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) {
185             // test string: "flutterappflorafy"
186             mItemInfoWithIcon.title = TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT;
187             mBubbleTextView.applyLabel(mItemInfoWithIcon);
188             mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
189             mBubbleTextView.setTypeface(Typeface.MONOSPACE);
190             mBubbleTextView.measure(mLimitedWidth, 0);
191             mBubbleTextView.onPreDraw();
192             assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
193         } catch (Exception e) {
194             throw  new RuntimeException(e);
195         }
196     }
197 
198     @Test
testLongStringWithSpaceLongerThanCharLimit_flagOn()199     public void testLongStringWithSpaceLongerThanCharLimit_flagOn() {
200         try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
201             // test string: "System UWB Field Test"
202             mItemInfoWithIcon.title = TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
203             mBubbleTextView.applyLabel(mItemInfoWithIcon);
204             mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
205             mBubbleTextView.setTypeface(Typeface.MONOSPACE);
206             mBubbleTextView.measure(mLimitedWidth, 0);
207             mBubbleTextView.onPreDraw();
208             assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
209         } catch (Exception e) {
210             throw  new RuntimeException(e);
211         }
212     }
213 
214     @Test
testLongStringWithSpaceLongerThanCharLimit_flagOff()215     public void testLongStringWithSpaceLongerThanCharLimit_flagOff() {
216         try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) {
217             // test string: "System UWB Field Test"
218             mItemInfoWithIcon.title = TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
219             mBubbleTextView.applyLabel(mItemInfoWithIcon);
220             mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
221             mBubbleTextView.setTypeface(Typeface.MONOSPACE);
222             mBubbleTextView.measure(mLimitedWidth, 0);
223             mBubbleTextView.onPreDraw();
224             assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
225         } catch (Exception e) {
226             throw  new RuntimeException(e);
227         }
228     }
229 
230     @Test
testLongStringSymbolLongerThanCharLimit_flagOn()231     public void testLongStringSymbolLongerThanCharLimit_flagOn() {
232         try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
233             // test string: "LEGO®Builder"
234             mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT;
235             mBubbleTextView.applyLabel(mItemInfoWithIcon);
236             mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
237             mBubbleTextView.setTypeface(Typeface.MONOSPACE);
238             mBubbleTextView.measure(mLimitedWidth, 0);
239             mBubbleTextView.onPreDraw();
240             assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
241         } catch (Exception e) {
242             throw  new RuntimeException(e);
243         }
244     }
245 
246     @Test
testLongStringSymbolLongerThanCharLimit_flagOff()247     public void testLongStringSymbolLongerThanCharLimit_flagOff() {
248         try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) {
249             // test string: "LEGO®Builder"
250             mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT;
251             mBubbleTextView.applyLabel(mItemInfoWithIcon);
252             mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
253             mBubbleTextView.setTypeface(Typeface.MONOSPACE);
254             mBubbleTextView.measure(mLimitedWidth, 0);
255             mBubbleTextView.onPreDraw();
256             assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
257         } catch (Exception e) {
258             throw  new RuntimeException(e);
259         }
260     }
261 
262     @Test
modifyTitleToSupportMultiLine_TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT()263     public void modifyTitleToSupportMultiLine_TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT() {
264         // test string: "Battery Stats"
265         IntArray breakPoints = StringMatcherUtility.getListOfBreakpoints(
266                 TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT, MATCHER);
267         CharSequence newString = BubbleTextView.modifyTitleToSupportMultiLine(mLimitedWidth,
268                 TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT, mBubbleTextView.getPaint(),
269                 breakPoints);
270         assertEquals(TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT_RESULT, newString);
271     }
272 
273     @Test
modifyTitleToSupportMultiLine_TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT()274     public void modifyTitleToSupportMultiLine_TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT() {
275         // test string: "flutterappflorafy"
276         IntArray breakPoints = StringMatcherUtility.getListOfBreakpoints(
277                 TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT, MATCHER);
278         CharSequence newString = BubbleTextView.modifyTitleToSupportMultiLine(mLimitedWidth,
279                 TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT, mBubbleTextView.getPaint(),
280                 breakPoints);
281         assertEquals(TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT, newString);
282     }
283 
284     @Test
modifyTitleToSupportMultiLine_TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT()285     public void modifyTitleToSupportMultiLine_TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT() {
286         // test string: "System UWB Field Test"
287         IntArray breakPoints = StringMatcherUtility.getListOfBreakpoints(
288                 TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT, MATCHER);
289         CharSequence newString = BubbleTextView.modifyTitleToSupportMultiLine(mLimitedWidth,
290                 TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT, mBubbleTextView.getPaint(),
291                 breakPoints);
292         assertEquals(TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT_RESULT, newString);
293     }
294 
295     @Test
modifyTitleToSupportMultiLine_TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT()296     public void modifyTitleToSupportMultiLine_TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT() {
297         // test string: "LEGO®Builder"
298         IntArray breakPoints = StringMatcherUtility.getListOfBreakpoints(
299                 TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT, MATCHER);
300         CharSequence newString = BubbleTextView.modifyTitleToSupportMultiLine(mLimitedWidth,
301                 TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT, mBubbleTextView.getPaint(),
302                 breakPoints);
303         assertEquals(TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT_RESULT, newString);
304     }
305 
306     @Test
testEnsurePredictionRowIsOneLine()307     public void testEnsurePredictionRowIsOneLine() {
308         try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
309             // test string: "Battery Stats"
310             mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
311             mBubbleTextView.setDisplay(DISPLAY_PREDICTION_ROW);
312             mBubbleTextView.applyLabel(mItemInfoWithIcon);
313             mBubbleTextView.setTypeface(Typeface.MONOSPACE);
314             mBubbleTextView.measure(mLimitedWidth, 0);
315             mBubbleTextView.onPreDraw();
316             assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
317         } catch (Exception e) {
318             throw new RuntimeException(e);
319         }
320     }
321 }
322