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 java.util.List; 20 21 import junit.framework.Assert; 22 23 import org.xmlpull.v1.XmlPullParser; 24 25 import android.app.Activity; 26 import android.app.Instrumentation; 27 import android.content.Context; 28 import android.graphics.Canvas; 29 import android.graphics.Rect; 30 import android.graphics.drawable.Drawable; 31 import android.test.ActivityInstrumentationTestCase2; 32 import android.test.UiThreadTest; 33 import android.test.suitebuilder.annotation.MediumTest; 34 import android.util.AttributeSet; 35 import android.util.SparseBooleanArray; 36 import android.util.Xml; 37 import android.view.KeyEvent; 38 import android.view.View; 39 import android.view.ViewGroup; 40 import android.view.animation.LayoutAnimationController; 41 import android.widget.AdapterView; 42 import android.widget.ArrayAdapter; 43 import android.widget.ListView; 44 import android.widget.TextView; 45 import android.widget.AdapterView.OnItemClickListener; 46 47 import com.android.cts.stub.R; 48 import com.google.android.collect.Lists; 49 50 import dalvik.annotation.TestLevel; 51 import dalvik.annotation.TestTargetClass; 52 import dalvik.annotation.TestTargetNew; 53 import dalvik.annotation.TestTargets; 54 import dalvik.annotation.ToBeFixed; 55 56 @TestTargetClass(ListView.class) 57 public class ListViewTest extends ActivityInstrumentationTestCase2<ListViewStubActivity> { 58 private final String[] mCountryList = new String[] { 59 "Argentina", "Australia", "China", "France", "Germany", "Italy", "Japan", "United States" 60 }; 61 private final String[] mNameList = new String[] { 62 "Jacky", "David", "Kevin", "Michael", "Andy" 63 }; 64 65 private ListView mListView; 66 private Activity mActivity; 67 private Instrumentation mInstrumentation; 68 private AttributeSet mAttributeSet; 69 private ArrayAdapter<String> mAdapter_countries; 70 private ArrayAdapter<String> mAdapter_names; 71 ListViewTest()72 public ListViewTest() { 73 super("com.android.cts.stub", ListViewStubActivity.class); 74 } 75 setUp()76 protected void setUp() throws Exception { 77 super.setUp(); 78 79 mActivity = getActivity(); 80 mInstrumentation = getInstrumentation(); 81 XmlPullParser parser = mActivity.getResources().getXml(R.layout.listview_layout); 82 mAttributeSet = Xml.asAttributeSet(parser); 83 84 mAdapter_countries = new ArrayAdapter<String>(mActivity, 85 android.R.layout.simple_list_item_1, mCountryList); 86 mAdapter_names = new ArrayAdapter<String>(mActivity, android.R.layout.simple_list_item_1, 87 mNameList); 88 89 mListView = (ListView) mActivity.findViewById(R.id.listview_default); 90 } 91 92 @TestTargets({ 93 @TestTargetNew( 94 level = TestLevel.COMPLETE, 95 method = "ListView", 96 args = {android.content.Context.class} 97 ), 98 @TestTargetNew( 99 level = TestLevel.COMPLETE, 100 method = "ListView", 101 args = {android.content.Context.class, android.util.AttributeSet.class} 102 ), 103 @TestTargetNew( 104 level = TestLevel.COMPLETE, 105 method = "ListView", 106 args = {android.content.Context.class, android.util.AttributeSet.class, int.class} 107 ) 108 }) 109 @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete") testConstructor()110 public void testConstructor() { 111 new ListView(mActivity); 112 new ListView(mActivity, mAttributeSet); 113 new ListView(mActivity, mAttributeSet, 0); 114 115 try { 116 new ListView(null); 117 fail("There should be a NullPointerException thrown out. "); 118 } catch (NullPointerException e) { 119 // expected, test success. 120 } 121 122 try { 123 new ListView(null, null); 124 fail("There should be a NullPointerException thrown out. "); 125 } catch (NullPointerException e) { 126 // expected, test success. 127 } 128 129 try { 130 new ListView(null, null, -1); 131 fail("There should be a NullPointerException thrown out. "); 132 } catch (NullPointerException e) { 133 // expected, test success. 134 } 135 } 136 137 @TestTargets({ 138 @TestTargetNew( 139 level = TestLevel.COMPLETE, 140 method = "setAdapter", 141 args = {android.widget.ListAdapter.class} 142 ), 143 @TestTargetNew( 144 level = TestLevel.COMPLETE, 145 method = "getMaxScrollAmount", 146 args = {} 147 ) 148 }) testGetMaxScrollAmount()149 public void testGetMaxScrollAmount() { 150 mInstrumentation.runOnMainSync(new Runnable() { 151 public void run() { 152 mListView.setAdapter(mAdapter_countries); 153 } 154 }); 155 mInstrumentation.waitForIdleSync(); 156 157 int amount1 = mListView.getMaxScrollAmount(); 158 assertTrue(amount1 > 0); 159 160 mInstrumentation.runOnMainSync(new Runnable() { 161 public void run() { 162 mListView.setAdapter(mAdapter_names); 163 } 164 }); 165 mInstrumentation.waitForIdleSync(); 166 167 int amount2 = mListView.getMaxScrollAmount(); 168 assertTrue(amount2 > 0); 169 assertTrue(amount2 < amount1); // because NAMES list is shorter than COUNTRIES list 170 } 171 172 @TestTargets({ 173 @TestTargetNew( 174 level = TestLevel.COMPLETE, 175 method = "setDividerHeight", 176 args = {int.class} 177 ), 178 @TestTargetNew( 179 level = TestLevel.COMPLETE, 180 method = "getDividerHeight", 181 args = {} 182 ), 183 @TestTargetNew( 184 level = TestLevel.COMPLETE, 185 method = "getDivider", 186 args = {} 187 ) 188 }) 189 public void testAccessDividerHeight() { 190 mInstrumentation.runOnMainSync(new Runnable() { 191 public void run() { 192 mListView.setAdapter(mAdapter_countries); 193 } 194 }); 195 mInstrumentation.waitForIdleSync(); 196 197 Drawable d = mListView.getDivider(); 198 Rect r = d.getBounds(); 199 assertTrue(r.bottom - r.top > 0); 200 201 mInstrumentation.runOnMainSync(new Runnable() { 202 public void run() { 203 mListView.setDividerHeight(20); 204 } 205 }); 206 mInstrumentation.waitForIdleSync(); 207 assertEquals(20, mListView.getDividerHeight()); 208 assertEquals(20, r.bottom - r.top); 209 210 mInstrumentation.runOnMainSync(new Runnable() { 211 public void run() { 212 mListView.setDividerHeight(10); 213 } 214 }); 215 mInstrumentation.waitForIdleSync(); 216 assertEquals(10, mListView.getDividerHeight()); 217 assertEquals(10, r.bottom - r.top); 218 } 219 220 @TestTargets({ 221 @TestTargetNew( 222 level = TestLevel.PARTIAL, 223 method = "setItemsCanFocus", 224 args = {boolean.class} 225 ), 226 @TestTargetNew( 227 level = TestLevel.PARTIAL, 228 method = "getItemsCanFocus", 229 args = {} 230 ) 231 }) testAccessItemsCanFocus()232 public void testAccessItemsCanFocus() { 233 mListView.setItemsCanFocus(true); 234 assertTrue(mListView.getItemsCanFocus()); 235 236 mListView.setItemsCanFocus(false); 237 assertFalse(mListView.getItemsCanFocus()); 238 239 // TODO: how to check? 240 } 241 242 @TestTargets({ 243 @TestTargetNew( 244 level = TestLevel.COMPLETE, 245 method = "setAdapter", 246 args = {android.widget.ListAdapter.class} 247 ), 248 @TestTargetNew( 249 level = TestLevel.COMPLETE, 250 method = "getAdapter", 251 args = {} 252 ) 253 }) testAccessAdapter()254 public void testAccessAdapter() { 255 mInstrumentation.runOnMainSync(new Runnable() { 256 public void run() { 257 mListView.setAdapter(mAdapter_countries); 258 } 259 }); 260 mInstrumentation.waitForIdleSync(); 261 262 assertSame(mAdapter_countries, mListView.getAdapter()); 263 assertEquals(mCountryList.length, mListView.getCount()); 264 265 mInstrumentation.runOnMainSync(new Runnable() { 266 public void run() { 267 mListView.setAdapter(mAdapter_names); 268 } 269 }); 270 mInstrumentation.waitForIdleSync(); 271 272 assertSame(mAdapter_names, mListView.getAdapter()); 273 assertEquals(mNameList.length, mListView.getCount()); 274 } 275 276 @TestTargets({ 277 @TestTargetNew( 278 level = TestLevel.COMPLETE, 279 method = "setItemChecked", 280 args = {int.class, boolean.class} 281 ), 282 @TestTargetNew( 283 level = TestLevel.COMPLETE, 284 method = "setChoiceMode", 285 args = {int.class} 286 ), 287 @TestTargetNew( 288 level = TestLevel.COMPLETE, 289 method = "getChoiceMode", 290 args = {} 291 ), 292 @TestTargetNew( 293 level = TestLevel.COMPLETE, 294 method = "getCheckedItemPosition", 295 args = {} 296 ), 297 @TestTargetNew( 298 level = TestLevel.COMPLETE, 299 method = "isItemChecked", 300 args = {int.class} 301 ), 302 @TestTargetNew( 303 level = TestLevel.COMPLETE, 304 method = "getCheckedItemPositions", 305 args = {} 306 ), 307 @TestTargetNew( 308 level = TestLevel.COMPLETE, 309 method = "clearChoices", 310 args = {} 311 ) 312 }) 313 @UiThreadTest 314 @ToBeFixed(bug="2031502", explanation="setItemChecked(i,false) always unchecks all items") testAccessItemChecked()315 public void testAccessItemChecked() { 316 // NONE mode 317 mListView.setChoiceMode(ListView.CHOICE_MODE_NONE); 318 assertEquals(ListView.CHOICE_MODE_NONE, mListView.getChoiceMode()); 319 320 mListView.setItemChecked(1, true); 321 assertEquals(ListView.INVALID_POSITION, mListView.getCheckedItemPosition()); 322 assertFalse(mListView.isItemChecked(1)); 323 324 // SINGLE mode 325 mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); 326 assertEquals(ListView.CHOICE_MODE_SINGLE, mListView.getChoiceMode()); 327 328 mListView.setItemChecked(2, true); 329 assertEquals(2, mListView.getCheckedItemPosition()); 330 assertTrue(mListView.isItemChecked(2)); 331 332 mListView.setItemChecked(3, true); 333 assertEquals(3, mListView.getCheckedItemPosition()); 334 assertTrue(mListView.isItemChecked(3)); 335 assertFalse(mListView.isItemChecked(2)); 336 337 // test attempt to uncheck a item that wasn't checked to begin with 338 mListView.setItemChecked(4, false); 339 // item three should still be checked, but current ListView behavior unchecks all items 340 assertEquals(ListView.INVALID_POSITION, mListView.getCheckedItemPosition()); 341 assertFalse(mListView.isItemChecked(4)); 342 // should be assertTrue 343 assertFalse(mListView.isItemChecked(3)); 344 assertFalse(mListView.isItemChecked(2)); 345 346 mListView.setItemChecked(4, true); 347 assertTrue(mListView.isItemChecked(4)); 348 mListView.clearChoices(); 349 assertEquals(ListView.INVALID_POSITION, mListView.getCheckedItemPosition()); 350 assertFalse(mListView.isItemChecked(4)); 351 352 // MULTIPLE mode 353 mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); 354 assertEquals(ListView.CHOICE_MODE_MULTIPLE, mListView.getChoiceMode()); 355 356 mListView.setItemChecked(1, true); 357 assertEquals(ListView.INVALID_POSITION, mListView.getCheckedItemPosition()); 358 SparseBooleanArray array = mListView.getCheckedItemPositions(); 359 assertTrue(array.get(1)); 360 assertFalse(array.get(2)); 361 assertTrue(mListView.isItemChecked(1)); 362 assertFalse(mListView.isItemChecked(2)); 363 364 mListView.setItemChecked(2, true); 365 mListView.setItemChecked(3, false); 366 mListView.setItemChecked(4, true); 367 368 assertTrue(array.get(1)); 369 assertTrue(array.get(2)); 370 assertFalse(array.get(3)); 371 assertTrue(array.get(4)); 372 assertTrue(mListView.isItemChecked(1)); 373 assertTrue(mListView.isItemChecked(2)); 374 assertFalse(mListView.isItemChecked(3)); 375 assertTrue(mListView.isItemChecked(4)); 376 377 mListView.clearChoices(); 378 assertFalse(array.get(1)); 379 assertFalse(array.get(2)); 380 assertFalse(array.get(3)); 381 assertFalse(array.get(4)); 382 assertFalse(mListView.isItemChecked(1)); 383 assertFalse(mListView.isItemChecked(2)); 384 assertFalse(mListView.isItemChecked(3)); 385 assertFalse(mListView.isItemChecked(4)); 386 } 387 388 @TestTargets({ 389 @TestTargetNew( 390 level = TestLevel.COMPLETE, 391 method = "setFooterDividersEnabled", 392 args = {boolean.class} 393 ), 394 @TestTargetNew( 395 level = TestLevel.COMPLETE, 396 method = "addFooterView", 397 args = {android.view.View.class, java.lang.Object.class, boolean.class} 398 ), 399 @TestTargetNew( 400 level = TestLevel.COMPLETE, 401 method = "addFooterView", 402 args = {android.view.View.class} 403 ), 404 @TestTargetNew( 405 level = TestLevel.COMPLETE, 406 method = "getFooterViewsCount", 407 args = {} 408 ), 409 @TestTargetNew( 410 level = TestLevel.COMPLETE, 411 method = "removeFooterView", 412 args = {android.view.View.class} 413 ) 414 }) testAccessFooterView()415 public void testAccessFooterView() { 416 final TextView footerView1 = new TextView(mActivity); 417 footerView1.setText("footerview1"); 418 final TextView footerView2 = new TextView(mActivity); 419 footerView2.setText("footerview2"); 420 421 mInstrumentation.runOnMainSync(new Runnable() { 422 public void run() { 423 mListView.setFooterDividersEnabled(true); 424 } 425 }); 426 mInstrumentation.waitForIdleSync(); 427 assertEquals(0, mListView.getFooterViewsCount()); 428 429 mInstrumentation.runOnMainSync(new Runnable() { 430 public void run() { 431 mListView.addFooterView(footerView1, null, true); 432 } 433 }); 434 mInstrumentation.waitForIdleSync(); 435 assertEquals(1, mListView.getFooterViewsCount()); 436 437 mInstrumentation.runOnMainSync(new Runnable() { 438 public void run() { 439 mListView.addFooterView(footerView2); 440 } 441 }); 442 443 mInstrumentation.waitForIdleSync(); 444 assertEquals(2, mListView.getFooterViewsCount()); 445 446 mInstrumentation.runOnMainSync(new Runnable() { 447 public void run() { 448 mListView.setAdapter(mAdapter_countries); 449 } 450 }); 451 mInstrumentation.waitForIdleSync(); 452 453 mInstrumentation.runOnMainSync(new Runnable() { 454 public void run() { 455 mListView.removeFooterView(footerView1); 456 } 457 }); 458 mInstrumentation.waitForIdleSync(); 459 assertEquals(1, mListView.getFooterViewsCount()); 460 461 mInstrumentation.runOnMainSync(new Runnable() { 462 public void run() { 463 mListView.removeFooterView(footerView2); 464 } 465 }); 466 mInstrumentation.waitForIdleSync(); 467 assertEquals(0, mListView.getFooterViewsCount()); 468 } 469 470 @TestTargets({ 471 @TestTargetNew( 472 level = TestLevel.COMPLETE, 473 method = "setHeaderDividersEnabled", 474 args = {boolean.class} 475 ), 476 @TestTargetNew( 477 level = TestLevel.COMPLETE, 478 method = "addHeaderView", 479 args = {android.view.View.class, java.lang.Object.class, boolean.class} 480 ), 481 @TestTargetNew( 482 level = TestLevel.COMPLETE, 483 method = "addHeaderView", 484 args = {android.view.View.class} 485 ), 486 @TestTargetNew( 487 level = TestLevel.COMPLETE, 488 method = "getHeaderViewsCount", 489 args = {} 490 ), 491 @TestTargetNew( 492 level = TestLevel.COMPLETE, 493 method = "removeHeaderView", 494 args = {android.view.View.class} 495 ) 496 }) 497 @ToBeFixed(bug = "", explanation = "After add two header views, the setAdapter will fail, " + 498 "and throws out an java.lang.ClassCastException.") testAccessHeaderView()499 public void testAccessHeaderView() { 500 final TextView headerView1 = (TextView) mActivity.findViewById(R.id.headerview1); 501 final TextView headerView2 = (TextView) mActivity.findViewById(R.id.headerview2); 502 503 mInstrumentation.runOnMainSync(new Runnable() { 504 public void run() { 505 mListView.setHeaderDividersEnabled(true); 506 } 507 }); 508 mInstrumentation.waitForIdleSync(); 509 assertEquals(0, mListView.getHeaderViewsCount()); 510 511 mInstrumentation.runOnMainSync(new Runnable() { 512 public void run() { 513 mListView.addHeaderView(headerView2, null, true); 514 } 515 }); 516 mInstrumentation.waitForIdleSync(); 517 assertEquals(1, mListView.getHeaderViewsCount()); 518 519 mInstrumentation.runOnMainSync(new Runnable() { 520 public void run() { 521 mListView.addHeaderView(headerView1); 522 } 523 }); 524 mInstrumentation.waitForIdleSync(); 525 assertEquals(2, mListView.getHeaderViewsCount()); 526 } 527 528 @TestTargets({ 529 @TestTargetNew( 530 level = TestLevel.COMPLETE, 531 method = "setDivider", 532 args = {android.graphics.drawable.Drawable.class} 533 ), 534 @TestTargetNew( 535 level = TestLevel.COMPLETE, 536 method = "getDivider", 537 args = {} 538 ) 539 }) testAccessDivider()540 public void testAccessDivider() { 541 mInstrumentation.runOnMainSync(new Runnable() { 542 public void run() { 543 mListView.setAdapter(mAdapter_countries); 544 } 545 }); 546 mInstrumentation.waitForIdleSync(); 547 548 Drawable defaultDrawable = mListView.getDivider(); 549 Rect r = defaultDrawable.getBounds(); 550 assertTrue(r.bottom - r.top > 0); 551 552 final Drawable d = mActivity.getResources().getDrawable(R.drawable.scenery); 553 r = d.getBounds(); 554 mInstrumentation.runOnMainSync(new Runnable() { 555 public void run() { 556 mListView.setDivider(d); 557 } 558 }); 559 mInstrumentation.waitForIdleSync(); 560 assertSame(d, mListView.getDivider()); 561 assertEquals(r.bottom - r.top, mListView.getDividerHeight()); 562 563 mInstrumentation.runOnMainSync(new Runnable() { 564 public void run() { 565 mListView.setDividerHeight(10); 566 } 567 }); 568 mInstrumentation.waitForIdleSync(); 569 assertEquals(10, mListView.getDividerHeight()); 570 assertEquals(10, r.bottom - r.top); 571 } 572 573 @TestTargets({ 574 @TestTargetNew( 575 level = TestLevel.COMPLETE, 576 method = "setSelection", 577 args = {int.class} 578 ), 579 @TestTargetNew( 580 level = TestLevel.COMPLETE, 581 method = "setSelectionFromTop", 582 args = {int.class, int.class} 583 ), 584 @TestTargetNew( 585 level = TestLevel.COMPLETE, 586 method = "setSelectionAfterHeaderView", 587 args = {} 588 ) 589 }) testSetSelection()590 public void testSetSelection() { 591 mInstrumentation.runOnMainSync(new Runnable() { 592 public void run() { 593 mListView.setAdapter(mAdapter_countries); 594 } 595 }); 596 mInstrumentation.waitForIdleSync(); 597 598 mInstrumentation.runOnMainSync(new Runnable() { 599 public void run() { 600 mListView.setSelection(1); 601 } 602 }); 603 mInstrumentation.waitForIdleSync(); 604 String item = (String) mListView.getSelectedItem(); 605 assertEquals(mCountryList[1], item); 606 607 mInstrumentation.runOnMainSync(new Runnable() { 608 public void run() { 609 mListView.setSelectionFromTop(5, 0); 610 } 611 }); 612 mInstrumentation.waitForIdleSync(); 613 item = (String) mListView.getSelectedItem(); 614 assertEquals(mCountryList[5], item); 615 616 mInstrumentation.runOnMainSync(new Runnable() { 617 public void run() { 618 mListView.setSelectionAfterHeaderView(); 619 } 620 }); 621 mInstrumentation.waitForIdleSync(); 622 item = (String) mListView.getSelectedItem(); 623 assertEquals(mCountryList[0], item); 624 } 625 626 @TestTargets({ 627 @TestTargetNew( 628 level = TestLevel.NOT_NECESSARY, 629 method = "onKeyDown", 630 args = {int.class, android.view.KeyEvent.class} 631 ), 632 @TestTargetNew( 633 level = TestLevel.NOT_NECESSARY, 634 method = "onKeyUp", 635 args = {int.class, android.view.KeyEvent.class} 636 ), 637 @TestTargetNew( 638 level = TestLevel.NOT_NECESSARY, 639 method = "onKeyMultiple", 640 args = {int.class, int.class, android.view.KeyEvent.class} 641 ) 642 }) testOnKeyUpDown()643 public void testOnKeyUpDown() { 644 // implementation details, do NOT test 645 } 646 647 @TestTargetNew( 648 level = TestLevel.COMPLETE, 649 method = "performItemClick", 650 args = {android.view.View.class, int.class, long.class} 651 ) testPerformItemClick()652 public void testPerformItemClick() { 653 mInstrumentation.runOnMainSync(new Runnable() { 654 public void run() { 655 mListView.setAdapter(mAdapter_countries); 656 } 657 }); 658 mInstrumentation.waitForIdleSync(); 659 660 mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); 661 mInstrumentation.runOnMainSync(new Runnable() { 662 public void run() { 663 mListView.setSelection(2); 664 } 665 }); 666 mInstrumentation.waitForIdleSync(); 667 668 final TextView child = (TextView) mAdapter_countries.getView(2, null, mListView); 669 assertNotNull(child); 670 assertEquals(mCountryList[2], child.getText().toString()); 671 final long itemID = mAdapter_countries.getItemId(2); 672 assertEquals(2, itemID); 673 674 mInstrumentation.runOnMainSync(new Runnable() { 675 public void run() { 676 mListView.performItemClick(child, 2, itemID); 677 } 678 }); 679 mInstrumentation.waitForIdleSync(); 680 681 MockOnItemClickListener onClickListener = new MockOnItemClickListener(); 682 mListView.setOnItemClickListener(onClickListener); 683 684 assertNull(onClickListener.getView()); 685 assertEquals(0, onClickListener.getPosition()); 686 assertEquals(0, onClickListener.getID()); 687 688 mInstrumentation.runOnMainSync(new Runnable() { 689 public void run() { 690 mListView.performItemClick(child, 2, itemID); 691 } 692 }); 693 mInstrumentation.waitForIdleSync(); 694 695 assertSame(child, onClickListener.getView()); 696 assertEquals(2, onClickListener.getPosition()); 697 assertEquals(2, onClickListener.getID()); 698 } 699 700 @TestTargets({ 701 @TestTargetNew( 702 level = TestLevel.NOT_NECESSARY, 703 method = "onRestoreInstanceState", 704 args = {android.os.Parcelable.class} 705 ), 706 @TestTargetNew( 707 level = TestLevel.NOT_NECESSARY, 708 method = "onSaveInstanceState", 709 args = {} 710 ) 711 }) testSaveAndRestoreInstanceState()712 public void testSaveAndRestoreInstanceState() { 713 // implementation details, do NOT test 714 } 715 716 @TestTargetNew( 717 level = TestLevel.COMPLETE, 718 method = "dispatchKeyEvent", 719 args = {android.view.KeyEvent.class} 720 ) testDispatchKeyEvent()721 public void testDispatchKeyEvent() { 722 mInstrumentation.runOnMainSync(new Runnable() { 723 public void run() { 724 mListView.setAdapter(mAdapter_countries); 725 } 726 }); 727 mInstrumentation.waitForIdleSync(); 728 729 mInstrumentation.runOnMainSync(new Runnable() { 730 public void run() { 731 mListView.setSelection(1); 732 } 733 }); 734 mInstrumentation.waitForIdleSync(); 735 String item = (String) mListView.getSelectedItem(); 736 assertEquals(mCountryList[1], item); 737 738 mInstrumentation.runOnMainSync(new Runnable() { 739 public void run() { 740 KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A); 741 mListView.dispatchKeyEvent(keyEvent); 742 } 743 }); 744 mInstrumentation.waitForIdleSync(); 745 746 mInstrumentation.runOnMainSync(new Runnable() { 747 public void run() { 748 KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN); 749 mListView.dispatchKeyEvent(keyEvent); 750 mListView.dispatchKeyEvent(keyEvent); 751 mListView.dispatchKeyEvent(keyEvent); 752 } 753 }); 754 mInstrumentation.waitForIdleSync(); 755 item = (String)mListView.getSelectedItem(); 756 assertEquals(mCountryList[4], item); 757 } 758 759 @TestTargetNew( 760 level = TestLevel.PARTIAL, 761 method = "requestChildRectangleOnScreen", 762 args = {android.view.View.class, android.graphics.Rect.class, boolean.class} 763 ) testRequestChildRectangleOnScreen()764 public void testRequestChildRectangleOnScreen() { 765 mInstrumentation.runOnMainSync(new Runnable() { 766 public void run() { 767 mListView.setAdapter(mAdapter_countries); 768 } 769 }); 770 mInstrumentation.waitForIdleSync(); 771 772 TextView child = (TextView) mAdapter_countries.getView(0, null, mListView); 773 assertNotNull(child); 774 assertEquals(mCountryList[0], child.getText().toString()); 775 776 Rect rect = new Rect(0, 0, 10, 10); 777 assertFalse(mListView.requestChildRectangleOnScreen(child, rect, false)); 778 779 // TODO: how to check? 780 } 781 782 @TestTargetNew( 783 level = TestLevel.NOT_NECESSARY, 784 method = "onTouchEvent", 785 args = {android.view.MotionEvent.class} 786 ) testOnTouchEvent()787 public void testOnTouchEvent() { 788 // implementation details, do NOT test 789 } 790 791 @TestTargets({ 792 @TestTargetNew( 793 level = TestLevel.COMPLETE, 794 method = "canAnimate", 795 args = {} 796 ), 797 @TestTargetNew( 798 level = TestLevel.COMPLETE, 799 method = "setAdapter", 800 args = {android.widget.ListAdapter.class} 801 ) 802 }) 803 @UiThreadTest testCanAnimate()804 public void testCanAnimate() { 805 MyListView listView = new MyListView(mActivity, mAttributeSet); 806 807 assertFalse(listView.canAnimate()); 808 listView.setAdapter(mAdapter_countries); 809 assertFalse(listView.canAnimate()); 810 811 LayoutAnimationController controller = new LayoutAnimationController( 812 mActivity, mAttributeSet); 813 listView.setLayoutAnimation(controller); 814 815 assertTrue(listView.canAnimate()); 816 } 817 818 @TestTargetNew( 819 level = TestLevel.NOT_NECESSARY, 820 method = "dispatchDraw", 821 args = {android.graphics.Canvas.class} 822 ) 823 @UiThreadTest testDispatchDraw()824 public void testDispatchDraw() { 825 // implementation details, do NOT test 826 } 827 828 @TestTargets({ 829 @TestTargetNew( 830 level = TestLevel.COMPLETE, 831 method = "findViewTraversal", 832 args = {int.class} 833 ), 834 @TestTargetNew( 835 level = TestLevel.COMPLETE, 836 method = "addHeaderView", 837 args = {android.view.View.class} 838 ) 839 }) 840 @UiThreadTest testFindViewTraversal()841 public void testFindViewTraversal() { 842 MyListView listView = new MyListView(mActivity, mAttributeSet); 843 TextView headerView = (TextView) mActivity.findViewById(R.id.headerview1); 844 845 assertNull(listView.findViewTraversal(R.id.headerview1)); 846 847 listView.addHeaderView(headerView); 848 assertNotNull(listView.findViewTraversal(R.id.headerview1)); 849 assertSame(headerView, listView.findViewTraversal(R.id.headerview1)); 850 } 851 852 @TestTargets({ 853 @TestTargetNew( 854 level = TestLevel.COMPLETE, 855 method = "findViewWithTagTraversal", 856 args = {java.lang.Object.class} 857 ), 858 @TestTargetNew( 859 level = TestLevel.COMPLETE, 860 method = "addHeaderView", 861 args = {android.view.View.class} 862 ) 863 }) 864 @UiThreadTest testFindViewWithTagTraversal()865 public void testFindViewWithTagTraversal() { 866 MyListView listView = new MyListView(mActivity, mAttributeSet); 867 TextView headerView = (TextView) mActivity.findViewById(R.id.headerview1); 868 869 assertNull(listView.findViewWithTagTraversal("header")); 870 871 headerView.setTag("header"); 872 listView.addHeaderView(headerView); 873 assertNotNull(listView.findViewWithTagTraversal("header")); 874 assertSame(headerView, listView.findViewWithTagTraversal("header")); 875 } 876 877 @TestTargetNew( 878 level = TestLevel.TODO, 879 method = "layoutChildren", 880 args = {} 881 ) 882 @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete") testLayoutChildren()883 public void testLayoutChildren() { 884 // TODO: how to test? 885 } 886 887 @TestTargetNew( 888 level = TestLevel.NOT_NECESSARY, 889 method = "onFinishInflate", 890 args = {} 891 ) testOnFinishInflate()892 public void testOnFinishInflate() { 893 // implementation details, do NOT test 894 } 895 896 @TestTargetNew( 897 level = TestLevel.NOT_NECESSARY, 898 method = "onFocusChanged", 899 args = {boolean.class, int.class, android.graphics.Rect.class} 900 ) testOnFocusChanged()901 public void testOnFocusChanged() { 902 // implementation details, do NOT test 903 } 904 905 @TestTargetNew( 906 level = TestLevel.NOT_NECESSARY, 907 method = "onMeasure", 908 args = {int.class, int.class} 909 ) testOnMeasure()910 public void testOnMeasure() { 911 // implementation details, do NOT test 912 } 913 914 /** 915 * MyListView for test 916 */ 917 private static class MyListView extends ListView { MyListView(Context context, AttributeSet attrs)918 public MyListView(Context context, AttributeSet attrs) { 919 super(context, attrs); 920 } 921 922 @Override canAnimate()923 protected boolean canAnimate() { 924 return super.canAnimate(); 925 } 926 927 @Override dispatchDraw(Canvas canvas)928 protected void dispatchDraw(Canvas canvas) { 929 super.dispatchDraw(canvas); 930 } 931 932 @Override findViewTraversal(int id)933 protected View findViewTraversal(int id) { 934 return super.findViewTraversal(id); 935 } 936 937 @Override findViewWithTagTraversal(Object tag)938 protected View findViewWithTagTraversal(Object tag) { 939 return super.findViewWithTagTraversal(tag); 940 } 941 942 @Override layoutChildren()943 protected void layoutChildren() { 944 super.layoutChildren(); 945 } 946 } 947 948 private static class MockOnItemClickListener implements OnItemClickListener { 949 private View mView; 950 private int mPosition; 951 private long mID; 952 onItemClick(AdapterView<?> parent, View view, int position, long id)953 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 954 mView = view; 955 mPosition = position; 956 mID = id; 957 } 958 getView()959 public View getView() { 960 return mView; 961 } 962 getPosition()963 public int getPosition() { 964 return mPosition; 965 } 966 getID()967 public long getID() { 968 return mID; 969 } 970 } 971 972 /** 973 * The following functions are merged from frameworktest. 974 */ 975 @TestTargets({ 976 @TestTargetNew( 977 level = TestLevel.COMPLETE, 978 method = "layoutChildren", 979 args = {} 980 ), 981 @TestTargetNew( 982 level = TestLevel.COMPLETE, 983 method = "setAdapter", 984 args = {android.widget.ListAdapter.class} 985 ) 986 }) 987 @MediumTest testRequestLayout()988 public void testRequestLayout() throws Exception { 989 ListView listView = new ListView(mActivity); 990 List<String> items = Lists.newArrayList("hello"); 991 Adapter<String> adapter = new Adapter<String>(mActivity, 0, items); 992 listView.setAdapter(adapter); 993 994 int measureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY); 995 996 adapter.notifyDataSetChanged(); 997 listView.measure(measureSpec, measureSpec); 998 listView.layout(0, 0, 100, 100); 999 1000 MockView childView = (MockView) listView.getChildAt(0); 1001 1002 childView.requestLayout(); 1003 childView.onMeasureCalled = false; 1004 listView.measure(measureSpec, measureSpec); 1005 listView.layout(0, 0, 100, 100); 1006 Assert.assertTrue(childView.onMeasureCalled); 1007 } 1008 1009 @TestTargets({ 1010 @TestTargetNew( 1011 level = TestLevel.COMPLETE, 1012 method = "setSelection", 1013 args = {int.class} 1014 ), 1015 @TestTargetNew( 1016 level = TestLevel.COMPLETE, 1017 method = "setAdapter", 1018 args = {android.widget.ListAdapter.class} 1019 ) 1020 }) 1021 @MediumTest testNoSelectableItems()1022 public void testNoSelectableItems() throws Exception { 1023 ListView listView = new ListView(mActivity); 1024 // We use a header as the unselectable item to remain after the selectable one is removed. 1025 listView.addHeaderView(new View(mActivity), null, false); 1026 List<String> items = Lists.newArrayList("hello"); 1027 Adapter<String> adapter = new Adapter<String>(mActivity, 0, items); 1028 listView.setAdapter(adapter); 1029 1030 listView.setSelection(1); 1031 1032 int measureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY); 1033 1034 adapter.notifyDataSetChanged(); 1035 listView.measure(measureSpec, measureSpec); 1036 listView.layout(0, 0, 100, 100); 1037 1038 items.remove(0); 1039 1040 adapter.notifyDataSetChanged(); 1041 listView.measure(measureSpec, measureSpec); 1042 listView.layout(0, 0, 100, 100); 1043 } 1044 1045 private class MockView extends View { 1046 1047 public boolean onMeasureCalled = false; 1048 MockView(Context context)1049 public MockView(Context context) { 1050 super(context); 1051 } 1052 1053 @Override onMeasure(int widthMeasureSpec, int heightMeasureSpec)1054 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 1055 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 1056 onMeasureCalled = true; 1057 } 1058 } 1059 1060 private class Adapter<T> extends ArrayAdapter<T> { 1061 Adapter(Context context, int resource, List<T> objects)1062 public Adapter(Context context, int resource, List<T> objects) { 1063 super(context, resource, objects); 1064 } 1065 1066 @Override getView(int position, View convertView, ViewGroup parent)1067 public View getView(int position, View convertView, ViewGroup parent) { 1068 return new MockView(getContext()); 1069 } 1070 } 1071 } 1072