1 /* 2 * Copyright (C) 2008 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 android.widget.cts; 18 19 import static android.widget.ListPopupWindow.INPUT_METHOD_FROM_FOCUSABLE; 20 import static android.widget.ListPopupWindow.INPUT_METHOD_NEEDED; 21 import static android.widget.ListPopupWindow.INPUT_METHOD_NOT_NEEDED; 22 23 import static com.android.compatibility.common.util.WidgetTestUtils.sameCharSequence; 24 25 import static com.google.common.truth.Truth.assertThat; 26 27 import static org.junit.Assert.assertEquals; 28 import static org.junit.Assert.assertFalse; 29 import static org.junit.Assert.assertNotNull; 30 import static org.junit.Assert.assertNotSame; 31 import static org.junit.Assert.assertNull; 32 import static org.junit.Assert.assertSame; 33 import static org.junit.Assert.assertTrue; 34 import static org.mockito.Mockito.any; 35 import static org.mockito.Mockito.anyInt; 36 import static org.mockito.Mockito.atLeastOnce; 37 import static org.mockito.Mockito.eq; 38 import static org.mockito.Mockito.mock; 39 import static org.mockito.Mockito.never; 40 import static org.mockito.Mockito.spy; 41 import static org.mockito.Mockito.times; 42 import static org.mockito.Mockito.verify; 43 import static org.mockito.Mockito.verifyNoMoreInteractions; 44 import static org.mockito.Mockito.verifyZeroInteractions; 45 46 import android.app.Activity; 47 import android.app.Instrumentation; 48 import android.app.UiModeManager; 49 import android.content.Context; 50 import android.content.res.Configuration; 51 import android.content.res.Resources; 52 import android.graphics.Color; 53 import android.graphics.Rect; 54 import android.graphics.drawable.Drawable; 55 import android.os.SystemClock; 56 import android.text.Editable; 57 import android.text.TextWatcher; 58 import android.util.AttributeSet; 59 import android.util.Xml; 60 import android.view.KeyCharacterMap; 61 import android.view.KeyEvent; 62 import android.view.View; 63 import android.view.ViewGroup; 64 import android.widget.AdapterView; 65 import android.widget.ArrayAdapter; 66 import android.widget.AutoCompleteTextView; 67 import android.widget.AutoCompleteTextView.Validator; 68 import android.widget.Filter; 69 import android.widget.Filterable; 70 import android.widget.cts.util.TestUtils; 71 72 import androidx.test.InstrumentationRegistry; 73 import androidx.test.annotation.UiThreadTest; 74 import androidx.test.filters.MediumTest; 75 import androidx.test.rule.ActivityTestRule; 76 import androidx.test.runner.AndroidJUnit4; 77 78 import com.android.compatibility.common.util.PollingCheck; 79 import com.android.compatibility.common.util.WidgetTestUtils; 80 import com.android.compatibility.common.util.WindowUtil; 81 82 import com.google.common.collect.ImmutableList; 83 84 import org.junit.Before; 85 import org.junit.Rule; 86 import org.junit.Test; 87 import org.junit.runner.RunWith; 88 import org.xmlpull.v1.XmlPullParser; 89 90 import java.util.ArrayList; 91 import java.util.List; 92 93 @MediumTest 94 @RunWith(AndroidJUnit4.class) 95 public class AutoCompleteTextViewTest { 96 private final static String[] WORDS = 97 new String[] { "testOne", "testTwo", "testThree", "testFour" }; 98 private final static String STRING_TEST = "To be tested"; 99 private final static String STRING_VALIDATED = "String Validated"; 100 private final static String STRING_CHECK = "To be checked"; 101 102 private Activity mActivity; 103 private Instrumentation mInstrumentation; 104 private AutoCompleteTextView mAutoCompleteTextView; 105 private MockAutoCompleteTextView mMockAutoCompleteTextView; 106 private boolean mNumeric = false; 107 private ArrayAdapter<String> mAdapter; 108 109 @Rule 110 public ActivityTestRule<AutoCompleteCtsActivity> mActivityRule = 111 new ActivityTestRule<>(AutoCompleteCtsActivity.class); 112 113 private final Validator mValidator = new Validator() { 114 public CharSequence fixText(CharSequence invalidText) { 115 return STRING_VALIDATED; 116 } 117 118 public boolean isValid(CharSequence text) { 119 return false; 120 } 121 }; 122 123 protected class MyTextWatcher implements TextWatcher { 124 private CharSequence mExpectedAfter; 125 MyTextWatcher(CharSequence expectedAfter)126 public MyTextWatcher(CharSequence expectedAfter) { 127 mExpectedAfter = expectedAfter; 128 } 129 130 @Override onTextChanged(CharSequence s, int start, int before, int count)131 public void onTextChanged(CharSequence s, int start, int before, int count) { 132 assertEquals(mExpectedAfter.toString(), s.toString()); 133 // This watcher is expected to be notified in the middle of completion 134 assertTrue(mAutoCompleteTextView.isPerformingCompletion()); 135 } 136 137 @Override beforeTextChanged(CharSequence s, int start, int count, int after)138 public void beforeTextChanged(CharSequence s, int start, int count, int after) { 139 } 140 141 @Override afterTextChanged(Editable s)142 public void afterTextChanged(Editable s) { 143 } 144 } 145 146 @Before setup()147 public void setup() { 148 mActivity = mActivityRule.getActivity(); 149 WindowUtil.waitForFocus(mActivity); 150 mInstrumentation = InstrumentationRegistry.getInstrumentation(); 151 mAutoCompleteTextView = mActivity.findViewById(R.id.autocompletetv_edit); 152 mAutoCompleteTextView.setFocusableInTouchMode(true); 153 mMockAutoCompleteTextView = mActivity.findViewById(R.id.autocompletetv_custom); 154 mAdapter = new ArrayAdapter<>(mActivity, 155 android.R.layout.simple_dropdown_item_1line, WORDS); 156 KeyCharacterMap keymap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); 157 if (keymap.getKeyboardType() == KeyCharacterMap.NUMERIC) { 158 mNumeric = true; 159 } 160 } 161 isTvMode()162 boolean isTvMode() { 163 UiModeManager uiModeManager = (UiModeManager) mActivity.getSystemService( 164 Context.UI_MODE_SERVICE); 165 return uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION; 166 } 167 168 @Test testConstructor()169 public void testConstructor() { 170 XmlPullParser parser; 171 172 new AutoCompleteTextView(mActivity); 173 new AutoCompleteTextView(mActivity, null); 174 new AutoCompleteTextView(mActivity, null, android.R.attr.autoCompleteTextViewStyle); 175 new AutoCompleteTextView(mActivity, null, 0, 176 android.R.style.Widget_DeviceDefault_AutoCompleteTextView); 177 new AutoCompleteTextView(mActivity, null, 0, 178 android.R.style.Widget_DeviceDefault_Light_AutoCompleteTextView); 179 new AutoCompleteTextView(mActivity, null, 0, 180 android.R.style.Widget_Material_AutoCompleteTextView); 181 new AutoCompleteTextView(mActivity, null, 0, 182 android.R.style.Widget_Material_Light_AutoCompleteTextView); 183 184 final Resources.Theme popupTheme = mActivity.getResources().newTheme(); 185 popupTheme.applyStyle(android.R.style.Theme_Material, true); 186 new AutoCompleteTextView(mActivity, null, 0, 187 android.R.style.Widget_Material_Light_AutoCompleteTextView, popupTheme); 188 189 // new the AutoCompleteTextView instance 190 parser = mActivity.getResources().getXml(R.layout.simple_dropdown_item_1line); 191 AttributeSet attributeSet = Xml.asAttributeSet(parser); 192 new AutoCompleteTextView(mActivity, attributeSet); 193 194 // new the AutoCompleteTextView instance 195 parser = mActivity.getResources().getXml(R.layout.framelayout_layout); 196 attributeSet = Xml.asAttributeSet(parser); 197 new AutoCompleteTextView(mActivity, attributeSet, 0); 198 199 // Test for negative style resource ID 200 new AutoCompleteTextView(mActivity, attributeSet, -1); 201 // Test null AttributeSet 202 new AutoCompleteTextView(mActivity, null, -1); 203 } 204 205 @Test(expected=NullPointerException.class) testConstructorWithNullContext()206 public void testConstructorWithNullContext() { 207 XmlPullParser parser = mActivity.getResources().getXml(R.layout.simple_dropdown_item_1line); 208 AttributeSet attributeSet = Xml.asAttributeSet(parser); 209 new AutoCompleteTextView(null, attributeSet, 0); 210 } 211 212 @Test testEnoughToFilter()213 public void testEnoughToFilter() throws Throwable { 214 mAutoCompleteTextView.setThreshold(3); 215 assertEquals(3, mAutoCompleteTextView.getThreshold()); 216 217 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, 218 () -> mAutoCompleteTextView.setText("TryToTest")); 219 assertTrue(mAutoCompleteTextView.enoughToFilter()); 220 221 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, 222 () -> mAutoCompleteTextView.setText("No")); 223 assertFalse(mAutoCompleteTextView.enoughToFilter()); 224 } 225 226 @UiThreadTest 227 @Test testAccessAdapter()228 public void testAccessAdapter() { 229 mAutoCompleteTextView.setAdapter(null); 230 assertNull(mAutoCompleteTextView.getAdapter()); 231 232 mAutoCompleteTextView.setAdapter(mAdapter); 233 assertSame(mAdapter, mAutoCompleteTextView.getAdapter()); 234 235 // Re-set adapter to null 236 mAutoCompleteTextView.setAdapter(null); 237 assertNull(mAutoCompleteTextView.getAdapter()); 238 } 239 240 @UiThreadTest 241 @Test testAccessFilter()242 public void testAccessFilter() { 243 MockAutoCompleteTextView autoCompleteTextView = new MockAutoCompleteTextView(mActivity); 244 245 // Set Threshold to 4 characters 246 autoCompleteTextView.setThreshold(4); 247 248 autoCompleteTextView.setAdapter(null); 249 assertNull(autoCompleteTextView.getAdapter()); 250 assertNull(autoCompleteTextView.getFilter()); 251 252 Filter filter = mAdapter.getFilter(); 253 assertNotNull(filter); 254 autoCompleteTextView.setAdapter(mAdapter); 255 assertSame(mAdapter, autoCompleteTextView.getAdapter()); 256 assertSame(filter, autoCompleteTextView.getFilter()); 257 258 // Re-set adapter to null 259 autoCompleteTextView.setAdapter(null); 260 assertNull(autoCompleteTextView.getAdapter()); 261 assertNull(autoCompleteTextView.getFilter()); 262 } 263 264 @UiThreadTest 265 @Test testAccessItemClickListener()266 public void testAccessItemClickListener() { 267 final AdapterView.OnItemClickListener mockItemClickListener = 268 mock(AdapterView.OnItemClickListener.class); 269 270 // To ensure null listener 271 mAutoCompleteTextView.setOnItemClickListener(null); 272 assertNull(mAutoCompleteTextView.getItemClickListener()); 273 assertNull(mAutoCompleteTextView.getOnItemClickListener()); 274 275 mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener); 276 assertSame(mockItemClickListener, mAutoCompleteTextView.getItemClickListener()); 277 assertSame(mockItemClickListener, mAutoCompleteTextView.getOnItemClickListener()); 278 verifyZeroInteractions(mockItemClickListener); 279 280 // re-clear listener by setOnItemClickListener 281 mAutoCompleteTextView.setOnItemClickListener(null); 282 assertNull(mAutoCompleteTextView.getItemClickListener()); 283 assertNull(mAutoCompleteTextView.getOnItemClickListener()); 284 verifyZeroInteractions(mockItemClickListener); 285 } 286 287 @UiThreadTest 288 @Test testAccessItemSelectedListener()289 public void testAccessItemSelectedListener() { 290 final AdapterView.OnItemSelectedListener mockItemSelectedListener = 291 mock(AdapterView.OnItemSelectedListener.class); 292 293 // To ensure null listener 294 mAutoCompleteTextView.setOnItemSelectedListener(null); 295 assertNull(mAutoCompleteTextView.getItemSelectedListener()); 296 assertNull(mAutoCompleteTextView.getOnItemSelectedListener()); 297 298 mAutoCompleteTextView.setOnItemSelectedListener(mockItemSelectedListener); 299 assertSame(mockItemSelectedListener, mAutoCompleteTextView.getItemSelectedListener()); 300 assertSame(mockItemSelectedListener, mAutoCompleteTextView.getOnItemSelectedListener()); 301 verifyZeroInteractions(mockItemSelectedListener); 302 303 //re-clear listener by setOnItemClickListener 304 mAutoCompleteTextView.setOnItemSelectedListener(null); 305 assertNull(mAutoCompleteTextView.getItemSelectedListener()); 306 assertNull(mAutoCompleteTextView.getOnItemSelectedListener()); 307 verifyZeroInteractions(mockItemSelectedListener); 308 } 309 310 @UiThreadTest 311 @Test testConvertSelectionToString()312 public void testConvertSelectionToString() { 313 MockAutoCompleteTextView autoCompleteTextView = new MockAutoCompleteTextView(mActivity); 314 315 // Set Threshold to 4 characters 316 autoCompleteTextView.setThreshold(4); 317 autoCompleteTextView.setAdapter(mAdapter); 318 assertNotNull(autoCompleteTextView.getAdapter()); 319 320 assertEquals("", autoCompleteTextView.convertSelectionToString(null)); 321 assertEquals(STRING_TEST, autoCompleteTextView.convertSelectionToString(STRING_TEST)); 322 } 323 324 @UiThreadTest 325 @Test testOnTextChanged()326 public void testOnTextChanged() { 327 final TextWatcher mockTextWatcher = mock(TextWatcher.class); 328 mAutoCompleteTextView.addTextChangedListener(mockTextWatcher); 329 verify(mockTextWatcher, never()).onTextChanged(any(CharSequence.class), 330 anyInt(), anyInt(), anyInt()); 331 332 mAutoCompleteTextView.setText(STRING_TEST); 333 verify(mockTextWatcher, times(1)).onTextChanged(sameCharSequence(STRING_TEST), 334 eq(0), eq(0), eq(STRING_TEST.length())); 335 336 // Test replacing text. 337 mAutoCompleteTextView.setText(STRING_CHECK); 338 verify(mockTextWatcher, times(1)).onTextChanged(sameCharSequence(STRING_CHECK), 339 eq(0), eq(STRING_TEST.length()), eq(STRING_CHECK.length())); 340 } 341 342 @UiThreadTest 343 @Test testPopupWindow()344 public void testPopupWindow() { 345 final AutoCompleteTextView.OnDismissListener mockDismissListener = 346 mock(AutoCompleteTextView.OnDismissListener.class); 347 mAutoCompleteTextView.setOnDismissListener(mockDismissListener); 348 349 assertFalse(mAutoCompleteTextView.isPopupShowing()); 350 mAutoCompleteTextView.showDropDown(); 351 assertTrue(mAutoCompleteTextView.isPopupShowing()); 352 verifyZeroInteractions(mockDismissListener); 353 354 mAutoCompleteTextView.dismissDropDown(); 355 assertFalse(mAutoCompleteTextView.isPopupShowing()); 356 verify(mockDismissListener, times(1)).onDismiss(); 357 358 mAutoCompleteTextView.showDropDown(); 359 assertTrue(mAutoCompleteTextView.isPopupShowing()); 360 verify(mockDismissListener, times(1)).onDismiss(); 361 362 final MockValidator validator = new MockValidator(); 363 mAutoCompleteTextView.setValidator(validator); 364 mAutoCompleteTextView.requestFocus(); 365 mAutoCompleteTextView.showDropDown(); 366 mAutoCompleteTextView.setText(STRING_TEST); 367 assertEquals(STRING_TEST, mAutoCompleteTextView.getText().toString()); 368 369 // clearFocus will trigger onFocusChanged, and onFocusChanged will validate the text. 370 mAutoCompleteTextView.clearFocus(); 371 assertFalse(mAutoCompleteTextView.isPopupShowing()); 372 assertEquals(STRING_VALIDATED, mAutoCompleteTextView.getText().toString()); 373 verify(mockDismissListener, times(2)).onDismiss(); 374 375 verifyNoMoreInteractions(mockDismissListener); 376 } 377 378 @UiThreadTest 379 @Test testDropDownMetrics()380 public void testDropDownMetrics() { 381 mAutoCompleteTextView.setAdapter(mAdapter); 382 383 final Resources res = mActivity.getResources(); 384 final int dropDownWidth = 385 res.getDimensionPixelSize(R.dimen.autocomplete_textview_dropdown_width); 386 final int dropDownHeight = 387 res.getDimensionPixelSize(R.dimen.autocomplete_textview_dropdown_height); 388 final int dropDownOffsetHorizontal = 389 res.getDimensionPixelSize(R.dimen.autocomplete_textview_dropdown_offset_h); 390 final int dropDownOffsetVertical = 391 res.getDimensionPixelSize(R.dimen.autocomplete_textview_dropdown_offset_v); 392 393 mAutoCompleteTextView.setDropDownWidth(dropDownWidth); 394 mAutoCompleteTextView.setDropDownHeight(dropDownHeight); 395 mAutoCompleteTextView.setDropDownHorizontalOffset(dropDownOffsetHorizontal); 396 mAutoCompleteTextView.setDropDownVerticalOffset(dropDownOffsetVertical); 397 398 mAutoCompleteTextView.showDropDown(); 399 400 assertEquals(dropDownWidth, mAutoCompleteTextView.getDropDownWidth()); 401 assertEquals(dropDownHeight, mAutoCompleteTextView.getDropDownHeight()); 402 assertEquals(dropDownOffsetHorizontal, mAutoCompleteTextView.getDropDownHorizontalOffset()); 403 assertEquals(dropDownOffsetVertical, mAutoCompleteTextView.getDropDownVerticalOffset()); 404 } 405 406 @Test testDropDownBackground()407 public void testDropDownBackground() throws Throwable { 408 mActivityRule.runOnUiThread(() -> mAutoCompleteTextView.setAdapter(mAdapter)); 409 410 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 411 mAutoCompleteTextView.setDropDownBackgroundResource(R.drawable.blue_fill); 412 mAutoCompleteTextView.showDropDown(); 413 }); 414 415 Drawable dropDownBackground = mAutoCompleteTextView.getDropDownBackground(); 416 TestUtils.assertAllPixelsOfColor("Drop down should be blue", dropDownBackground, 417 dropDownBackground.getBounds().width(), dropDownBackground.getBounds().height(), 418 false, Color.BLUE, 1, true); 419 420 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 421 mAutoCompleteTextView.dismissDropDown(); 422 mAutoCompleteTextView.setDropDownBackgroundDrawable( 423 mActivity.getDrawable(R.drawable.yellow_fill)); 424 mAutoCompleteTextView.showDropDown(); 425 }); 426 427 dropDownBackground = mAutoCompleteTextView.getDropDownBackground(); 428 TestUtils.assertAllPixelsOfColor("Drop down should be yellow", dropDownBackground, 429 dropDownBackground.getBounds().width(), dropDownBackground.getBounds().height(), 430 false, Color.YELLOW, 1, true); 431 } 432 433 @Test refreshAutoCompleteResults_addItem()434 public void refreshAutoCompleteResults_addItem() throws Throwable { 435 List<String> suggestions = new ArrayList<>(ImmutableList.of("testOne", "testTwo")); 436 mAdapter = new ArrayAdapter<String>( 437 mActivity, android.R.layout.simple_dropdown_item_1line, suggestions); 438 439 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 440 mAutoCompleteTextView.setAdapter(mAdapter); 441 mAutoCompleteTextView.setText("testT"); 442 mAutoCompleteTextView.refreshAutoCompleteResults(); 443 }); 444 445 PollingCheck.waitFor(() -> { 446 List<Object> autoCompleteSuggestions = getAutoCompleteSuggestions(); 447 return (autoCompleteSuggestions.size() == 1) 448 && autoCompleteSuggestions.contains("testTwo"); 449 }); 450 451 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 452 mAdapter.add("testThree"); 453 mAutoCompleteTextView.refreshAutoCompleteResults(); 454 }); 455 456 PollingCheck.waitFor(() -> { 457 List<Object> autoCompleteSuggestions = getAutoCompleteSuggestions(); 458 return (autoCompleteSuggestions.size() == 2) 459 && autoCompleteSuggestions.contains("testTwo") 460 && autoCompleteSuggestions.contains("testThree"); 461 }); 462 } 463 464 @Test refreshAutoCompleteResults_removeItem()465 public void refreshAutoCompleteResults_removeItem() throws Throwable { 466 List<String> suggestions = new ArrayList<>( 467 ImmutableList.of("testOne", "testTwo", "testThree")); 468 mAdapter = new ArrayAdapter<>( 469 mActivity, android.R.layout.simple_dropdown_item_1line, suggestions); 470 471 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 472 mAutoCompleteTextView.setAdapter(mAdapter); 473 mAutoCompleteTextView.setText("testT"); 474 mAutoCompleteTextView.refreshAutoCompleteResults(); 475 }); 476 PollingCheck.waitFor(() -> { 477 List<Object> autoCompleteSuggestions = getAutoCompleteSuggestions(); 478 return (autoCompleteSuggestions.size() == 2) 479 && autoCompleteSuggestions.contains("testTwo") 480 && autoCompleteSuggestions.contains("testThree"); 481 }); 482 483 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 484 mAdapter.remove("testThree"); 485 mAutoCompleteTextView.refreshAutoCompleteResults(); 486 }); 487 PollingCheck.waitFor(() -> { 488 List<Object> autoCompleteSuggestions = getAutoCompleteSuggestions(); 489 return (autoCompleteSuggestions.size() == 1) 490 && autoCompleteSuggestions.contains("testTwo"); 491 }); 492 } 493 494 @Test refreshAutoCompleteResults_threshold_changeText()495 public void refreshAutoCompleteResults_threshold_changeText() throws Throwable { 496 List<String> suggestions = new ArrayList<>( 497 ImmutableList.of("testOne", "testTwo", "testThree")); 498 mAdapter = new ArrayAdapter<String>( 499 mActivity, android.R.layout.simple_dropdown_item_1line, suggestions); 500 501 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 502 mAutoCompleteTextView.setThreshold(3); 503 mAutoCompleteTextView.setAdapter(mAdapter); 504 mAutoCompleteTextView.setText("tes"); 505 }); 506 507 // Above Threshold. 508 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 509 mAutoCompleteTextView.setText("test"); 510 mAutoCompleteTextView.refreshAutoCompleteResults(); 511 }); 512 assertThat(mAutoCompleteTextView.isPopupShowing()).isTrue(); 513 assertThat(getAutoCompleteSuggestions()).containsExactly("testOne", "testTwo", "testThree"); 514 515 // At Threshold. 516 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 517 mAutoCompleteTextView.setText("tes"); 518 mAutoCompleteTextView.refreshAutoCompleteResults(); 519 }); 520 assertThat(mAutoCompleteTextView.isPopupShowing()).isTrue(); 521 assertThat(getAutoCompleteSuggestions()).containsExactly("testOne", "testTwo", "testThree"); 522 523 // Below Threshold. 524 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 525 mAutoCompleteTextView.setText("te"); 526 mAutoCompleteTextView.refreshAutoCompleteResults(); 527 }); 528 assertThat(mAutoCompleteTextView.isPopupShowing()).isFalse(); 529 } 530 531 @Test refreshAutoCompleteResults_changeThreshold()532 public void refreshAutoCompleteResults_changeThreshold() throws Throwable { 533 List<String> suggestions = new ArrayList<>( 534 ImmutableList.of("testOne", "testTwo", "testThree")); 535 mAdapter = new ArrayAdapter<String>(mActivity, android.R.layout.simple_dropdown_item_1line, 536 suggestions); 537 538 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 539 mAutoCompleteTextView.setAdapter(mAdapter); 540 mAutoCompleteTextView.setText("test"); 541 }); 542 543 // Above Threshold. 544 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 545 mAutoCompleteTextView.setThreshold(3); 546 mAutoCompleteTextView.refreshAutoCompleteResults(); 547 }); 548 assertThat(mAutoCompleteTextView.isPopupShowing()).isTrue(); 549 assertThat(getAutoCompleteSuggestions()).containsExactly("testOne", "testTwo", "testThree"); 550 551 // At Threshold. 552 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 553 mAutoCompleteTextView.setThreshold(4); 554 mAutoCompleteTextView.refreshAutoCompleteResults(); 555 }); 556 assertThat(mAutoCompleteTextView.isPopupShowing()).isTrue(); 557 assertThat(getAutoCompleteSuggestions()).containsExactly("testOne", "testTwo", "testThree"); 558 559 // Below Threshold. 560 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 561 mAutoCompleteTextView.setThreshold(5); 562 mAutoCompleteTextView.refreshAutoCompleteResults(); 563 }); 564 assertThat(mAutoCompleteTextView.isPopupShowing()).isFalse(); 565 } 566 567 @Test refreshAutoCompleteResults_dropDownAlwaysVisible()568 public void refreshAutoCompleteResults_dropDownAlwaysVisible() throws Throwable { 569 List<String> suggestions = new ArrayList<>( 570 ImmutableList.of("testOne", "testTwo", "testThree")); 571 mAdapter = new ArrayAdapter<String>(mActivity, android.R.layout.simple_dropdown_item_1line, 572 suggestions); 573 574 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 575 mAutoCompleteTextView.setAdapter(mAdapter); 576 mAutoCompleteTextView.setDropDownAlwaysVisible(true); 577 mAutoCompleteTextView.setText("test"); 578 }); 579 580 // Below Threshold. 581 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 582 mAutoCompleteTextView.setThreshold(5); 583 mAutoCompleteTextView.refreshAutoCompleteResults(); 584 }); 585 PollingCheck.waitFor(() -> mAutoCompleteTextView.isPopupShowing()); 586 } 587 588 @Test refreshAutoCompleteResults_dropDownNotAlwaysVisible()589 public void refreshAutoCompleteResults_dropDownNotAlwaysVisible() throws Throwable { 590 List<String> suggestions = new ArrayList<>( 591 ImmutableList.of("testOne", "testTwo", "testThree")); 592 mAdapter = new ArrayAdapter<String>(mActivity, android.R.layout.simple_dropdown_item_1line, 593 suggestions); 594 595 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 596 mAutoCompleteTextView.setAdapter(mAdapter); 597 mAutoCompleteTextView.setDropDownAlwaysVisible(false); 598 mAutoCompleteTextView.setText("test"); 599 }); 600 601 // Below Threshold. 602 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 603 mAutoCompleteTextView.setThreshold(5); 604 mAutoCompleteTextView.refreshAutoCompleteResults(); 605 }); 606 assertThat(mAutoCompleteTextView.isPopupShowing()).isFalse(); 607 } 608 609 @Test refreshAutoCompleteResults_popupCanBeUpdated()610 public void refreshAutoCompleteResults_popupCanBeUpdated() throws Throwable { 611 List<String> suggestions = new ArrayList<>( 612 ImmutableList.of("testOne", "testTwo", "testThree")); 613 mAdapter = new ArrayAdapter<String>(mActivity, android.R.layout.simple_dropdown_item_1line, 614 suggestions); 615 616 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 617 mAutoCompleteTextView.setAdapter(mAdapter); 618 mAutoCompleteTextView.setDropDownAlwaysVisible(false); 619 mAutoCompleteTextView.setText("test"); 620 }); 621 622 // Below Threshold. 623 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 624 mAutoCompleteTextView.setThreshold(5); 625 mAutoCompleteTextView.refreshAutoCompleteResults(); 626 }); 627 assertThat(mAutoCompleteTextView.isPopupShowing()).isFalse(); 628 } 629 630 @Test refreshAutoCompleteResults()631 public void refreshAutoCompleteResults() throws Throwable { 632 List<String> suggestions = new ArrayList<>(ImmutableList.of("testOne", "testTwo")); 633 mAdapter = new ArrayAdapter<>(mActivity, android.R.layout.simple_dropdown_item_1line, 634 suggestions); 635 636 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 637 mAutoCompleteTextView.setAdapter(mAdapter); 638 mAutoCompleteTextView.setText("testT"); 639 mAutoCompleteTextView.refreshAutoCompleteResults(); 640 }); 641 PollingCheck.waitFor(() -> { 642 List<Object> autoCompleteSuggestions = getAutoCompleteSuggestions(); 643 return (autoCompleteSuggestions.size() == 1) 644 && autoCompleteSuggestions.contains("testTwo"); 645 }); 646 647 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 648 mAdapter.add("testThree"); 649 mAutoCompleteTextView.refreshAutoCompleteResults(); 650 }); 651 PollingCheck.waitFor(() -> { 652 List<Object> autoCompleteSuggestions = getAutoCompleteSuggestions(); 653 return (autoCompleteSuggestions.size() == 2) 654 && autoCompleteSuggestions.contains("testTwo") 655 && autoCompleteSuggestions.contains("testThree"); 656 }); 657 } 658 659 @UiThreadTest 660 @Test setInputMethodMode_fromFocussable()661 public void setInputMethodMode_fromFocussable() { 662 mAutoCompleteTextView.setInputMethodMode(INPUT_METHOD_FROM_FOCUSABLE); 663 assertThat(mAutoCompleteTextView.getInputMethodMode()) 664 .isEqualTo(INPUT_METHOD_FROM_FOCUSABLE); 665 } 666 667 @UiThreadTest 668 @Test setInputMethodMode_Needed()669 public void setInputMethodMode_Needed() { 670 mAutoCompleteTextView.setInputMethodMode(INPUT_METHOD_NEEDED); 671 assertThat(mAutoCompleteTextView.getInputMethodMode()).isEqualTo(INPUT_METHOD_NEEDED); 672 } 673 674 @UiThreadTest 675 @Test setInputMethodMode_NotNeeded()676 public void setInputMethodMode_NotNeeded() { 677 mAutoCompleteTextView.setInputMethodMode(INPUT_METHOD_NOT_NEEDED); 678 assertThat(mAutoCompleteTextView.getInputMethodMode()).isEqualTo(INPUT_METHOD_NOT_NEEDED); 679 } 680 681 @UiThreadTest 682 @Test testReplaceText()683 public void testReplaceText() { 684 final TextWatcher mockTextWatcher = mock(TextWatcher.class); 685 mMockAutoCompleteTextView.addTextChangedListener(mockTextWatcher); 686 verify(mockTextWatcher, never()).onTextChanged(any(CharSequence.class), 687 anyInt(), anyInt(), anyInt()); 688 689 mMockAutoCompleteTextView.replaceText("Text"); 690 assertEquals("Text", mMockAutoCompleteTextView.getText().toString()); 691 verify(mockTextWatcher, times(1)).onTextChanged(sameCharSequence("Text"), 692 eq(0), eq(0), eq("Text".length())); 693 694 mMockAutoCompleteTextView.replaceText("Another"); 695 assertEquals("Another", mMockAutoCompleteTextView.getText().toString()); 696 verify(mockTextWatcher, times(1)).onTextChanged(sameCharSequence("Another"), 697 eq(0), eq("Text".length()), eq("Another".length())); 698 } 699 700 @UiThreadTest 701 @Test testSetFrame()702 public void testSetFrame() { 703 assertTrue(mMockAutoCompleteTextView.setFrame(0, 1, 2, 3)); 704 assertEquals(0, mMockAutoCompleteTextView.getLeft()); 705 assertEquals(1, mMockAutoCompleteTextView.getTop()); 706 assertEquals(2, mMockAutoCompleteTextView.getRight()); 707 assertEquals(3, mMockAutoCompleteTextView.getBottom()); 708 709 // If the values are the same as old ones, function will return false 710 assertFalse(mMockAutoCompleteTextView.setFrame(0, 1, 2, 3)); 711 assertEquals(0, mMockAutoCompleteTextView.getLeft()); 712 assertEquals(1, mMockAutoCompleteTextView.getTop()); 713 assertEquals(2, mMockAutoCompleteTextView.getRight()); 714 assertEquals(3, mMockAutoCompleteTextView.getBottom()); 715 716 // If the values are not the same as old ones, function will return true 717 assertTrue(mMockAutoCompleteTextView.setFrame(2, 3, 4, 5)); 718 assertEquals(2, mMockAutoCompleteTextView.getLeft()); 719 assertEquals(3, mMockAutoCompleteTextView.getTop()); 720 assertEquals(4, mMockAutoCompleteTextView.getRight()); 721 assertEquals(5, mMockAutoCompleteTextView.getBottom()); 722 } 723 724 @UiThreadTest 725 @Test testGetThreshold()726 public void testGetThreshold() { 727 assertEquals(1, mAutoCompleteTextView.getThreshold()); 728 mAutoCompleteTextView.setThreshold(3); 729 assertEquals(3, mAutoCompleteTextView.getThreshold()); 730 731 // Test negative value input 732 mAutoCompleteTextView.setThreshold(-5); 733 assertEquals(1, mAutoCompleteTextView.getThreshold()); 734 735 // Test zero 736 mAutoCompleteTextView.setThreshold(0); 737 assertEquals(1, mAutoCompleteTextView.getThreshold()); 738 } 739 740 @UiThreadTest 741 @Test testAccessValidater()742 public void testAccessValidater() { 743 final MockValidator validator = new MockValidator(); 744 745 assertNull(mAutoCompleteTextView.getValidator()); 746 mAutoCompleteTextView.setValidator(validator); 747 assertSame(validator, mAutoCompleteTextView.getValidator()); 748 749 // Set to null 750 mAutoCompleteTextView.setValidator(null); 751 assertNull(mAutoCompleteTextView.getValidator()); 752 } 753 754 @Test testOnFilterComplete()755 public void testOnFilterComplete() throws Throwable { 756 // Set Threshold to 4 characters 757 mAutoCompleteTextView.setThreshold(4); 758 759 String testString = ""; 760 if (mNumeric) { 761 // "tes" in case of 12-key(NUMERIC) keyboard 762 testString = "8337777"; 763 } else { 764 testString = "tes"; 765 } 766 767 // Test the filter if the input string is not long enough to threshold 768 mActivityRule.runOnUiThread(() -> { 769 mAutoCompleteTextView.setAdapter(mAdapter); 770 mAutoCompleteTextView.setText(""); 771 mAutoCompleteTextView.requestFocus(); 772 }); 773 mInstrumentation.sendStringSync(testString); 774 775 // onFilterComplete will close the popup. 776 PollingCheck.waitFor(() -> !mAutoCompleteTextView.isPopupShowing()); 777 778 if (mNumeric) { 779 // "that" in case of 12-key(NUMERIC) keyboard 780 testString = "84428"; 781 } else { 782 testString = "that"; 783 } 784 mInstrumentation.sendStringSync(testString); 785 PollingCheck.waitFor(() -> !mAutoCompleteTextView.isPopupShowing()); 786 787 // Test the expected filter matching scene 788 mActivityRule.runOnUiThread(() -> { 789 mAutoCompleteTextView.setFocusable(true); 790 mAutoCompleteTextView.requestFocus(); 791 mAutoCompleteTextView.setText(""); 792 }); 793 if (mNumeric) { 794 // "test" in case of 12-key(NUMERIC) keyboard 795 mInstrumentation.sendStringSync("83377778"); 796 } else { 797 mInstrumentation.sendStringSync("test"); 798 } 799 assertTrue(mAutoCompleteTextView.hasFocus()); 800 assertTrue(mAutoCompleteTextView.hasWindowFocus()); 801 PollingCheck.waitFor(() -> mAutoCompleteTextView.isPopupShowing()); 802 } 803 804 @Test testPerformFiltering()805 public void testPerformFiltering() throws Throwable { 806 if (isTvMode()) { 807 return; 808 } 809 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 810 mAutoCompleteTextView.setAdapter(mAdapter); 811 mAutoCompleteTextView.setValidator(mValidator); 812 813 mAutoCompleteTextView.setText("test"); 814 mAutoCompleteTextView.setFocusable(true); 815 mAutoCompleteTextView.requestFocus(); 816 mAutoCompleteTextView.showDropDown(); 817 }); 818 assertTrue(mAutoCompleteTextView.isPopupShowing()); 819 820 mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK); 821 // KeyBack will close the popup. 822 assertFalse(mAutoCompleteTextView.isPopupShowing()); 823 824 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 825 mAutoCompleteTextView.showDropDown(); 826 }); 827 assertTrue(mAutoCompleteTextView.isPopupShowing()); 828 829 mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_ESCAPE); 830 // KeyEscape will also close the popup. 831 assertFalse(mAutoCompleteTextView.isPopupShowing()); 832 833 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 834 mAutoCompleteTextView.dismissDropDown(); 835 mAutoCompleteTextView.setText(STRING_TEST); 836 }); 837 838 assertEquals(STRING_TEST, mAutoCompleteTextView.getText().toString()); 839 mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN); 840 // If the popup is closed, onKeyDown will invoke performValidation. 841 assertEquals(STRING_VALIDATED, mAutoCompleteTextView.getText().toString()); 842 843 final MockAdapter<String> adapter = new MockAdapter<String>(mActivity, 844 android.R.layout.simple_dropdown_item_1line, WORDS); 845 846 // Set Threshold to 4 characters onKeyDown 847 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 848 mAutoCompleteTextView.setAdapter(adapter); 849 mAutoCompleteTextView.requestFocus(); 850 mAutoCompleteTextView.setText(""); 851 }); 852 // Create and get the filter. 853 final MockFilter filter = (MockFilter) adapter.getFilter(); 854 855 // performFiltering will be indirectly invoked by onKeyDown 856 assertNull(filter.getResult()); 857 // 12-key support 858 if (mNumeric) { 859 // "numeric" in case of 12-key(NUMERIC) keyboard 860 mInstrumentation.sendStringSync("6688633777444222"); 861 PollingCheck.waitFor(() -> "numeric".equals(filter.getResult())); 862 } else { 863 SystemClock.sleep(200); 864 mInstrumentation.sendStringSync(STRING_TEST); 865 PollingCheck.waitFor(() -> STRING_TEST.equals(filter.getResult())); 866 } 867 } 868 869 @Test testPerformCompletionWithDPad()870 public void testPerformCompletionWithDPad() throws Throwable { 871 if (isTvMode()) { 872 return; 873 } 874 final AdapterView.OnItemClickListener mockItemClickListener = 875 mock(AdapterView.OnItemClickListener.class); 876 assertFalse(mAutoCompleteTextView.isPerformingCompletion()); 877 878 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 879 mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener); 880 mAutoCompleteTextView.setAdapter(mAdapter); 881 mAutoCompleteTextView.requestFocus(); 882 mAutoCompleteTextView.showDropDown(); 883 }); 884 assertFalse(mAutoCompleteTextView.isPerformingCompletion()); 885 886 // Key is ENTER, will invoke completion 887 mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN); 888 mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER); 889 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, null); 890 verify(mockItemClickListener, times(1)).onItemClick(any(AdapterView.class), any(View.class), 891 eq(0), eq(0L)); 892 assertEquals(WORDS[0], mAutoCompleteTextView.getText().toString()); 893 894 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, 895 mAutoCompleteTextView::showDropDown); 896 // Key is NUMPAD_ENTER, will invoke completion 897 mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN); 898 mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_NUMPAD_ENTER); 899 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, null); 900 verify(mockItemClickListener, times(2)).onItemClick(any(AdapterView.class), any(View.class), 901 eq(0), eq(0L)); 902 assertEquals(WORDS[0], mAutoCompleteTextView.getText().toString()); 903 904 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, 905 mAutoCompleteTextView::showDropDown); 906 mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN); 907 mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER); 908 verify(mockItemClickListener, times(3)).onItemClick(any(AdapterView.class), any(View.class), 909 eq(0), eq(0L)); 910 assertEquals(WORDS[0], mAutoCompleteTextView.getText().toString()); 911 assertFalse(mAutoCompleteTextView.isPerformingCompletion()); 912 913 mActivityRule.runOnUiThread(mAutoCompleteTextView::showDropDown); 914 mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN); 915 // Test normal key code. 916 mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_0); 917 verifyNoMoreInteractions(mockItemClickListener); 918 assertNotSame("", mAutoCompleteTextView.getText().toString()); 919 assertFalse(mAutoCompleteTextView.isPerformingCompletion()); 920 921 // Test the method on the scene of popup is closed. 922 mActivityRule.runOnUiThread(mAutoCompleteTextView::dismissDropDown); 923 924 mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN); 925 mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER); 926 verifyNoMoreInteractions(mockItemClickListener); 927 assertNotSame("", mAutoCompleteTextView.getText().toString()); 928 assertFalse(mAutoCompleteTextView.isPerformingCompletion()); 929 } 930 931 @Test testPerformCompletionExplicit()932 public void testPerformCompletionExplicit() throws Throwable { 933 final AdapterView.OnItemClickListener mockItemClickListener = 934 mock(AdapterView.OnItemClickListener.class); 935 assertFalse(mAutoCompleteTextView.isPerformingCompletion()); 936 937 // Create a custom watcher that checks isPerformingCompletion to return true 938 // in the "middle" of the performCompletion processing. We also spy on this watcher 939 // to make sure that its onTextChanged is invoked. 940 final TextWatcher myTextWatcher = new MyTextWatcher(WORDS[1]); 941 final TextWatcher spyTextWatcher = spy(myTextWatcher); 942 mAutoCompleteTextView.addTextChangedListener(spyTextWatcher); 943 944 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 945 mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener); 946 mAutoCompleteTextView.setAdapter(mAdapter); 947 mAutoCompleteTextView.requestFocus(); 948 mAutoCompleteTextView.showDropDown(); 949 }); 950 951 assertTrue(mAutoCompleteTextView.isPopupShowing()); 952 assertFalse(mAutoCompleteTextView.isPerformingCompletion()); 953 954 mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN); 955 mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN); 956 mActivityRule.runOnUiThread(mAutoCompleteTextView::performCompletion); 957 verify(mockItemClickListener, times(1)).onItemClick(any(AdapterView.class), any(View.class), 958 eq(1), eq(1L)); 959 assertEquals(WORDS[1], mAutoCompleteTextView.getText().toString()); 960 assertFalse(mAutoCompleteTextView.isPerformingCompletion()); 961 assertFalse(mAutoCompleteTextView.isPopupShowing()); 962 963 verify(spyTextWatcher, atLeastOnce()).onTextChanged(sameCharSequence(WORDS[1]), 964 eq(0), eq(0), eq(WORDS[1].length())); 965 verifyNoMoreInteractions(mockItemClickListener); 966 } 967 968 @Test testSetTextWithCompletion()969 public void testSetTextWithCompletion() throws Throwable { 970 final AdapterView.OnItemClickListener mockItemClickListener = 971 mock(AdapterView.OnItemClickListener.class); 972 973 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 974 mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener); 975 mAutoCompleteTextView.setAdapter(mAdapter); 976 }); 977 PollingCheck.waitFor(() -> !mAutoCompleteTextView.isPopupShowing()); 978 979 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, 980 () -> mAutoCompleteTextView.setText("testO", true)); 981 PollingCheck.waitFor(() -> mAutoCompleteTextView.isPopupShowing()); 982 983 verifyZeroInteractions(mockItemClickListener); 984 } 985 986 @Test testSetTextWithNoCompletion()987 public void testSetTextWithNoCompletion() throws Throwable { 988 final AdapterView.OnItemClickListener mockItemClickListener = 989 mock(AdapterView.OnItemClickListener.class); 990 991 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 992 mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener); 993 mAutoCompleteTextView.setAdapter(mAdapter); 994 }); 995 996 assertFalse(mAutoCompleteTextView.isPopupShowing()); 997 998 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, 999 () -> mAutoCompleteTextView.setText("testO", false)); 1000 1001 assertFalse(mAutoCompleteTextView.isPopupShowing()); 1002 verifyZeroInteractions(mockItemClickListener); 1003 } 1004 1005 @UiThreadTest 1006 @Test testPerformValidation()1007 public void testPerformValidation() { 1008 final CharSequence text = "this"; 1009 1010 mAutoCompleteTextView.setValidator(mValidator); 1011 mAutoCompleteTextView.setAdapter((ArrayAdapter<String>) null); 1012 mAutoCompleteTextView.setText(text); 1013 mAutoCompleteTextView.performValidation(); 1014 1015 assertEquals(STRING_VALIDATED, mAutoCompleteTextView.getText().toString()); 1016 mAutoCompleteTextView.setValidator(null); 1017 } 1018 1019 @UiThreadTest 1020 @Test testAccessCompletionHint()1021 public void testAccessCompletionHint() { 1022 mAutoCompleteTextView.setCompletionHint("TEST HINT"); 1023 assertEquals("TEST HINT", mAutoCompleteTextView.getCompletionHint()); 1024 1025 mAutoCompleteTextView.setCompletionHint(null); 1026 assertNull(mAutoCompleteTextView.getCompletionHint()); 1027 } 1028 1029 @Test testAccessListSelection()1030 public void testAccessListSelection() throws Throwable { 1031 final AdapterView.OnItemClickListener mockItemClickListener = 1032 mock(AdapterView.OnItemClickListener.class); 1033 1034 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 1035 mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener); 1036 mAutoCompleteTextView.setAdapter(mAdapter); 1037 mAutoCompleteTextView.requestFocus(); 1038 mAutoCompleteTextView.showDropDown(); 1039 }); 1040 1041 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> { 1042 mAutoCompleteTextView.setListSelection(1); 1043 assertEquals(1, mAutoCompleteTextView.getListSelection()); 1044 1045 mAutoCompleteTextView.setListSelection(2); 1046 assertEquals(2, mAutoCompleteTextView.getListSelection()); 1047 1048 mAutoCompleteTextView.clearListSelection(); 1049 assertEquals(2, mAutoCompleteTextView.getListSelection()); 1050 }); 1051 } 1052 1053 @UiThreadTest 1054 @Test testAccessDropDownAnchor()1055 public void testAccessDropDownAnchor() { 1056 mAutoCompleteTextView.setDropDownAnchor(View.NO_ID); 1057 assertEquals(View.NO_ID, mAutoCompleteTextView.getDropDownAnchor()); 1058 1059 mAutoCompleteTextView.setDropDownAnchor(0x5555); 1060 assertEquals(0x5555, mAutoCompleteTextView.getDropDownAnchor()); 1061 } 1062 1063 @UiThreadTest 1064 @Test testAccessDropDownWidth()1065 public void testAccessDropDownWidth() { 1066 mAutoCompleteTextView.setDropDownWidth(ViewGroup.LayoutParams.WRAP_CONTENT); 1067 assertEquals(ViewGroup.LayoutParams.WRAP_CONTENT, mAutoCompleteTextView.getDropDownWidth()); 1068 1069 mAutoCompleteTextView.setDropDownWidth(ViewGroup.LayoutParams.MATCH_PARENT); 1070 assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, mAutoCompleteTextView.getDropDownWidth()); 1071 } 1072 getAutoCompleteSuggestions()1073 private List<Object> getAutoCompleteSuggestions() { 1074 int count = mAutoCompleteTextView.getAdapter().getCount(); 1075 List<Object> autoCompleteSuggestions = new ArrayList<>(count); 1076 for (int index = 0; index < count; index++) { 1077 autoCompleteSuggestions.add(mAutoCompleteTextView.getAdapter().getItem(index)); 1078 } 1079 return autoCompleteSuggestions; 1080 } 1081 1082 private class MockValidator implements AutoCompleteTextView.Validator { fixText(CharSequence invalidText)1083 public CharSequence fixText(CharSequence invalidText) { 1084 return STRING_VALIDATED; 1085 } 1086 isValid(CharSequence text)1087 public boolean isValid(CharSequence text) { 1088 return (text == STRING_TEST); 1089 } 1090 } 1091 1092 public static class MockAutoCompleteTextView extends AutoCompleteTextView { MockAutoCompleteTextView(Context context)1093 public MockAutoCompleteTextView(Context context) { 1094 super(context); 1095 } 1096 MockAutoCompleteTextView(Context context, AttributeSet attrs)1097 public MockAutoCompleteTextView(Context context, AttributeSet attrs) { 1098 super(context, attrs); 1099 } 1100 1101 @Override convertSelectionToString(Object selectedItem)1102 protected CharSequence convertSelectionToString(Object selectedItem) { 1103 return super.convertSelectionToString(selectedItem); 1104 } 1105 1106 @Override getFilter()1107 protected Filter getFilter() { 1108 return super.getFilter(); 1109 } 1110 1111 @Override onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect)1112 protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { 1113 super.onFocusChanged(focused, direction, previouslyFocusedRect); 1114 } 1115 1116 @Override performFiltering(CharSequence text, int keyCode)1117 protected void performFiltering(CharSequence text, int keyCode) { 1118 super.performFiltering(text, keyCode); 1119 } 1120 1121 @Override replaceText(CharSequence text)1122 protected void replaceText(CharSequence text) { 1123 super.replaceText(text); 1124 } 1125 1126 @Override setFrame(int l, int t, int r, int b)1127 protected boolean setFrame(int l, int t, int r, int b) { 1128 return super.setFrame(l, t, r, b); 1129 } 1130 } 1131 1132 private static class MockFilter extends Filter { 1133 private String mFilterResult; 1134 1135 @Override performFiltering(CharSequence constraint)1136 protected FilterResults performFiltering(CharSequence constraint) { 1137 if (constraint != null) { 1138 mFilterResult = constraint.toString(); 1139 } 1140 return null; 1141 } 1142 1143 @Override publishResults(CharSequence constraint, FilterResults results)1144 protected void publishResults(CharSequence constraint, FilterResults results) { 1145 } 1146 getResult()1147 public String getResult() { 1148 return mFilterResult; 1149 } 1150 } 1151 1152 private static class MockAdapter<T> extends ArrayAdapter<T> implements Filterable { 1153 private MockFilter mFilter; 1154 MockAdapter(Context context, int textViewResourceId, T[] objects)1155 public MockAdapter(Context context, int textViewResourceId, T[] objects) { 1156 super(context, textViewResourceId, objects); 1157 } 1158 1159 @Override getFilter()1160 public Filter getFilter() { 1161 if (mFilter == null) { 1162 mFilter = new MockFilter(); 1163 } 1164 return mFilter; 1165 } 1166 } 1167 } 1168