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