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