• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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