Home | History | Annotate | Download | only in cts
      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 org.xmlpull.v1.XmlPullParser;
     20 
     21 import android.app.Activity;
     22 import android.content.Context;
     23 import android.os.Parcelable;
     24 import android.test.ActivityInstrumentationTestCase2;
     25 import android.util.AttributeSet;
     26 import android.util.SparseArray;
     27 import android.util.Xml;
     28 import android.view.View;
     29 import android.view.ViewGroup;
     30 import android.view.animation.AnimationSet;
     31 import android.view.animation.LayoutAnimationController;
     32 import android.widget.AdapterView;
     33 import android.widget.ArrayAdapter;
     34 import android.widget.ImageView;
     35 import android.widget.ListAdapter;
     36 import android.widget.ListView;
     37 import android.widget.AdapterView.OnItemClickListener;
     38 import android.widget.AdapterView.OnItemLongClickListener;
     39 import android.widget.AdapterView.OnItemSelectedListener;
     40 import android.provider.Settings;
     41 
     42 import android.widget.cts.R;
     43 
     44 
     45 public class AdapterViewTest extends ActivityInstrumentationTestCase2<AdapterViewCtsActivity> {
     46 
     47     private final static int INVALID_ID = -1;
     48 
     49     private final static int LAYOUT_WIDTH = 200;
     50     private final static int LAYOUT_HEIGHT = 200;
     51 
     52     final String[] FRUIT = { "1", "2", "3", "4", "5", "6", "7", "8" };
     53 
     54     private Activity mActivity;
     55     private AdapterView<ListAdapter> mAdapterView;
     56 
     57     public AdapterViewTest() {
     58         super("android.widget.cts", AdapterViewCtsActivity.class);
     59     }
     60 
     61     @Override
     62     protected void setUp() throws Exception {
     63         super.setUp();
     64         mActivity = getActivity();
     65         mAdapterView = new ListView(mActivity);
     66     }
     67 
     68     public void testConstructor() {
     69         XmlPullParser parser = mActivity.getResources().getXml(R.layout.adapterview_layout);
     70         AttributeSet attrs = Xml.asAttributeSet(parser);
     71 
     72         new MockAdapterView(mActivity);
     73 
     74         new MockAdapterView(mActivity, attrs);
     75 
     76         new MockAdapterView(mActivity, attrs, 0);
     77 
     78         try {
     79             new MockAdapterView(null);
     80             fail("Should throw NullPointerException");
     81         } catch (NullPointerException e) {
     82             //expected
     83         }
     84 
     85         new MockAdapterView(mActivity, null, INVALID_ID);
     86     }
     87 
     88     /**
     89      * test not supported methods, all should throw UnsupportedOperationException
     90      */
     91     public void testUnsupportedMethods() {
     92         ListView subView = new ListView(mActivity);
     93 
     94         try {
     95             mAdapterView.addView(subView);
     96             fail("addView(View) is not supported in AdapterView.");
     97         } catch (UnsupportedOperationException e) {
     98             //expected
     99         }
    100 
    101         try {
    102             mAdapterView.addView(subView, 0);
    103             fail("addView(View, int) is not supported in AdapterView.");
    104         } catch (UnsupportedOperationException e) {
    105             //expected
    106         }
    107 
    108         try {
    109             mAdapterView.addView(subView, (ViewGroup.LayoutParams) null);
    110             fail("addView(View, ViewGroup.LayoutParams) is not supported in AdapterView.");
    111         } catch (UnsupportedOperationException e) {
    112             //expected
    113         }
    114 
    115         try {
    116             mAdapterView.addView(subView, 0, (ViewGroup.LayoutParams) null);
    117             fail("addView(View, int, ViewGroup.LayoutParams) is not supported in AdapterView.");
    118         } catch (UnsupportedOperationException e) {
    119             //expected
    120         }
    121 
    122         try {
    123             mAdapterView.removeViewAt(0);
    124             fail("removeViewAt(int) is not supported in AdapterView");
    125         } catch (UnsupportedOperationException e) {
    126             //expected
    127         }
    128 
    129         try {
    130             mAdapterView.removeAllViews();
    131             fail("removeAllViews() is not supported in AdapterView");
    132         } catch (UnsupportedOperationException e) {
    133             //expected
    134         }
    135 
    136         try {
    137             mAdapterView.removeView(subView);
    138             fail("removeView(View) is not supported in AdapterView");
    139         } catch (UnsupportedOperationException e) {
    140             //expected
    141         }
    142 
    143         try {
    144             mAdapterView.setOnClickListener(new android.view.View.OnClickListener() {
    145                 public void onClick(View v) {
    146                 }
    147             });
    148             fail("function setOnClickListener(android.view.View.OnClickListener) "
    149                     + "should throw out runtime exception");
    150         } catch (RuntimeException e) {
    151             // expected
    152         }
    153     }
    154 
    155     public void testGetCount() {
    156         // Before setAdapter, the count should be zero.
    157         assertEquals(0, mAdapterView.getCount());
    158 
    159         setArrayAdapter(mAdapterView);
    160 
    161         // After setAdapter, the count should be the value return by adapter.
    162         assertEquals(FRUIT.length, mAdapterView.getCount());
    163     }
    164 
    165     public void testAccessEmptyView() {
    166         ImageView emptyView = new ImageView(mActivity);
    167 
    168         // If there is no adapter has been set, emptyView hasn't been set, there will be no
    169         // emptyView return by getEmptyView().
    170         assertEquals(null, mAdapterView.getEmptyView());
    171 
    172         // If the adapter is 0 count, emptyView has been set, the emptyView should be returned by
    173         // getEmptyView. EmptyView will be set to Visible.
    174         mAdapterView.setAdapter(new ArrayAdapter<String>(
    175                 mActivity, R.layout.adapterview_layout, new String[]{}));
    176         emptyView.setVisibility(View.INVISIBLE);
    177         assertEquals(View.INVISIBLE, emptyView.getVisibility());
    178 
    179         // set empty view, for no item added, empty set to visible
    180         mAdapterView.setEmptyView(emptyView);
    181         assertSame(emptyView, mAdapterView.getEmptyView());
    182         assertEquals(View.VISIBLE, emptyView.getVisibility());
    183 
    184         // If the adapter is not empty, the emptyView should also be returned by
    185         // getEmptyView. EmptyView will be set to Gone.
    186         setArrayAdapter(mAdapterView);
    187         emptyView = new ImageView(mActivity);
    188 
    189         assertEquals(View.VISIBLE, emptyView.getVisibility());
    190         mAdapterView.setEmptyView(emptyView);
    191         // for item added, emptyview is set to gone
    192         assertEquals(emptyView, mAdapterView.getEmptyView());
    193         assertEquals(View.GONE, emptyView.getVisibility());
    194 
    195         // null adapter should also show empty view
    196         mAdapterView.setAdapter(null);
    197         emptyView = new ImageView(mActivity);
    198         emptyView.setVisibility(View.INVISIBLE);
    199         assertEquals(View.INVISIBLE, emptyView.getVisibility());
    200         // set empty view
    201         mAdapterView.setEmptyView(emptyView);
    202         assertEquals(emptyView, mAdapterView.getEmptyView());
    203         assertEquals(View.VISIBLE, emptyView.getVisibility());
    204     }
    205 
    206     public void testAccessVisiblePosition() {
    207 
    208         assertEquals(0, mAdapterView.getFirstVisiblePosition());
    209         // If no adapter has been set, the value should be -1;
    210         assertEquals(-1, mAdapterView.getLastVisiblePosition());
    211 
    212         setArrayAdapter(mAdapterView);
    213 
    214         // LastVisiblePosition should be adapter's getCount - 1,by mocking method
    215         float fontScale = Settings.System.getFloat(mActivity.getContentResolver(), Settings.System.FONT_SCALE, 1);
    216         if (fontScale < 1) {
    217             fontScale = 1;
    218         }
    219         float density = mActivity.getResources().getDisplayMetrics().density;
    220         int bottom = (int) (LAYOUT_HEIGHT * density * fontScale);
    221         mAdapterView.layout(0, 0, LAYOUT_WIDTH, bottom);
    222         assertEquals(FRUIT.length - 1, mAdapterView.getLastVisiblePosition());
    223     }
    224 
    225     public void testItemOrItemIdAtPosition() {
    226         // no adapter set
    227         assertNull(mAdapterView.getItemAtPosition(0));
    228         assertEquals(AdapterView.INVALID_ROW_ID, mAdapterView.getItemIdAtPosition(1));
    229 
    230         // after adapter set
    231         setArrayAdapter(mAdapterView);
    232         int count = mAdapterView.getAdapter().getCount();
    233 
    234         for (int i = 0; i < count; i++) {
    235             assertEquals(FRUIT[i], mAdapterView.getItemAtPosition(i));
    236         }
    237         assertNull(mAdapterView.getItemAtPosition(-1));
    238         try {
    239             mAdapterView.getItemAtPosition(FRUIT.length);
    240             fail("should throw IndexOutOfBoundsException");
    241         } catch (IndexOutOfBoundsException e) {
    242             //expected
    243         }
    244 
    245         for (int i = 0; i < count; i++) {
    246             assertEquals(i, mAdapterView.getItemIdAtPosition(i));
    247         }
    248         assertEquals(AdapterView.INVALID_ROW_ID, mAdapterView.getItemIdAtPosition(-1));
    249         assertEquals(FRUIT.length, mAdapterView.getItemIdAtPosition(FRUIT.length));
    250     }
    251 
    252     public void testAccessOnItemClickAndLongClickListener() {
    253         MockOnItemClickListener clickListener = new MockOnItemClickListener();
    254         MockOnItemLongClickListener longClickListener = new MockOnItemLongClickListener();
    255 
    256         assertFalse(mAdapterView.performItemClick(null, 0, 0));
    257 
    258         mAdapterView.setOnItemClickListener(clickListener);
    259         mAdapterView.setOnItemLongClickListener(longClickListener);
    260 
    261         assertFalse(clickListener.isClicked());
    262         assertTrue(mAdapterView.performItemClick(null, 0, 0));
    263         assertTrue(clickListener.isClicked());
    264 
    265         setArrayAdapter(mAdapterView);
    266         assertFalse(longClickListener.isClicked());
    267         mAdapterView.layout(0, 0, LAYOUT_WIDTH, LAYOUT_HEIGHT);
    268         assertTrue(mAdapterView.showContextMenuForChild(mAdapterView.getChildAt(0)));
    269         assertTrue(longClickListener.isClicked());
    270     }
    271 
    272     public void testAccessOnItemSelectedListener() {
    273         // FIXME: we can not select the item in touch mode, how can we change the mode to test
    274         setArrayAdapter(mAdapterView);
    275         MockOnItemSelectedListener selectedListener = new MockOnItemSelectedListener();
    276         mAdapterView.setOnItemSelectedListener(selectedListener);
    277 
    278 //        mAdapterView.layout(0, 0, LAYOUT_WIDTH, LAYOUT_HEIGHT);
    279 //
    280 //        assertFalse(selectedListener.isItemSelected());
    281 //        assertFalse(selectedListener.isNothingSelected());
    282 //
    283 //        mAdapterView.setSelection(1);
    284 //        assertTrue(selectedListener.isItemSelected());
    285 //        assertFalse(selectedListener.isNothingSelected());
    286 //
    287 //        mAdapterView.setSelection(-1);
    288 //        assertTrue(selectedListener.isItemSelected());
    289 //        assertTrue(selectedListener.isNothingSelected());
    290 //
    291 //        mAdapterView.setSelection(FRUIT.length);
    292 //        assertTrue(selectedListener.isItemSelected());
    293 //        assertTrue(selectedListener.isNothingSelected());
    294     }
    295 
    296     /*
    297      * Get the position within the adapter's data set for the view, where view is a an adapter item
    298      * or a descendant of an adapter item.
    299      * when scroll down the list, the item's position may be 5 or 6 be on the screen
    300      * but to the layout parent ,it may still be the 1, 2 child for there always has 3,4 views there
    301      * it's hard to scroll the list in unit test, so we just test without scrolling
    302      * this means the position of item is same as position of the children in parent layout
    303      */
    304     public void testGetPositionForView() {
    305         setArrayAdapter(mAdapterView);
    306         mAdapterView.layout(0, 0, LAYOUT_WIDTH, LAYOUT_HEIGHT);
    307 
    308         int count = mAdapterView.getChildCount();
    309         for (int i = 0; i < count; i++) {
    310             assertEquals(i, mAdapterView.getPositionForView(mAdapterView.getChildAt(i)));
    311         }
    312 
    313         try {
    314             assertEquals(AdapterView.INVALID_POSITION, mAdapterView.getPositionForView(null));
    315             fail("Should throw NullPointerException");
    316         } catch (NullPointerException e) {
    317             //expected
    318         }
    319 
    320         assertEquals(AdapterView.INVALID_POSITION,
    321                 mAdapterView.getPositionForView(new ImageView(mActivity)));
    322     }
    323 
    324     public void testChangeFocusable() {
    325         assertFalse(mAdapterView.isFocusable());
    326         assertFalse(mAdapterView.isFocusableInTouchMode());
    327 
    328         // no item added will never focusable
    329         assertNull(mAdapterView.getAdapter());
    330         mAdapterView.setFocusable(true);
    331         assertFalse(mAdapterView.isFocusable());
    332         assertFalse(mAdapterView.isFocusableInTouchMode());
    333 
    334         // only focusable with children added
    335         setArrayAdapter(mAdapterView);
    336         assertTrue(mAdapterView.getAdapter().getCount() > 0);
    337         mAdapterView.setFocusable(true);
    338         assertTrue(mAdapterView.isFocusable());
    339         assertTrue(mAdapterView.isFocusableInTouchMode());
    340 
    341         mAdapterView.setFocusable(false);
    342         assertFalse(mAdapterView.isFocusable());
    343         assertFalse(mAdapterView.isFocusableInTouchMode());
    344     }
    345 
    346     /*
    347      * skip this test, no need to test
    348      */
    349     public void testOnLayout() {
    350         // onLayout() is implementation details, do NOT test
    351     }
    352 
    353     /*
    354      * set and get the selected id, position and item.
    355      * values will not change if invalid id given.
    356      */
    357     public void testGetSelected() {
    358         assertEquals(AdapterView.INVALID_ROW_ID, mAdapterView.getSelectedItemId());
    359         assertEquals(AdapterView.INVALID_POSITION, mAdapterView.getSelectedItemPosition());
    360         assertEquals(null, mAdapterView.getSelectedItem());
    361 
    362         // set adapter, 0 selected by default
    363         setArrayAdapter(mAdapterView);
    364         assertEquals(0, mAdapterView.getSelectedItemId());
    365         assertEquals(0, mAdapterView.getSelectedItemPosition());
    366         assertEquals(FRUIT[0], mAdapterView.getSelectedItem());
    367 
    368         int expectedId = 1;
    369         mAdapterView.setSelection(expectedId);
    370         assertEquals(expectedId, mAdapterView.getSelectedItemId());
    371         assertEquals(expectedId, mAdapterView.getSelectedItemPosition());
    372         assertEquals(FRUIT[expectedId], mAdapterView.getSelectedItem());
    373 
    374         // invalid id will be ignored
    375         expectedId = -1;
    376         mAdapterView.setSelection(expectedId);
    377         assertEquals(1, mAdapterView.getSelectedItemId());
    378         assertEquals(1, mAdapterView.getSelectedItemPosition());
    379         assertEquals(FRUIT[1], mAdapterView.getSelectedItem());
    380 
    381         expectedId = mAdapterView.getCount();
    382         mAdapterView.setSelection(expectedId);
    383         assertEquals(1, mAdapterView.getSelectedItemId());
    384         assertEquals(1, mAdapterView.getSelectedItemPosition());
    385         assertEquals(FRUIT[1], mAdapterView.getSelectedItem());
    386     }
    387 
    388     /*
    389      * not update this test until the ViewGroup's test finish.
    390      */
    391     public void testDispatchSaveInstanceState() {
    392         MockAdapterView adapterView = new MockAdapterView(mActivity);
    393         adapterView.setSaveEnabled(true);
    394         adapterView.setId(1);
    395         SparseArray<Parcelable> sa = new SparseArray<Parcelable>();
    396         adapterView.dispatchSaveInstanceState(sa);
    397         assertTrue(sa.size() > 0);
    398     }
    399 
    400     /*
    401      * not update this test until the ViewGroup's test finish.
    402      */
    403     public void testDispatchRestoreInstanceState() {
    404         MockAdapterView adapterView = new MockAdapterView(mActivity);
    405         adapterView.setSaveEnabled(true);
    406         adapterView.setId(1);
    407         SparseArray<Parcelable> sparseArray = new SparseArray<Parcelable>();
    408         adapterView.dispatchRestoreInstanceState(sparseArray);
    409     }
    410 
    411     /*
    412      * whether this view can has animation layout
    413      * if no child added, it always return false
    414      * this method is protected, so we involve the mock
    415      */
    416     public void testCanAnimate() {
    417         MockAdapterView adapterView = new MockAdapterView(mActivity);
    418         LayoutAnimationController lAC = new LayoutAnimationController(new AnimationSet(true));
    419 
    420             // no child added, always false
    421         assertNull(adapterView.getAdapter());
    422         adapterView.setLayoutAnimation(lAC);
    423         assertFalse(adapterView.canAnimate());
    424 
    425         setArrayAdapter(adapterView);
    426 
    427         assertTrue(adapterView.getAdapter().getCount() > 0);
    428         assertTrue(adapterView.canAnimate());
    429     }
    430 
    431     private static class MockAdapterView extends ListView{
    432 
    433         public MockAdapterView(Context context) {
    434             super(context);
    435         }
    436 
    437         public MockAdapterView(Context context, AttributeSet attrs) {
    438             super(context, attrs);
    439         }
    440 
    441         public MockAdapterView(Context context, AttributeSet attrs, int defStyle) {
    442             super(context, attrs, defStyle);
    443         }
    444 
    445         @Override
    446         protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
    447             super.dispatchRestoreInstanceState(container);
    448         }
    449 
    450         @Override
    451         protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
    452             super.dispatchSaveInstanceState(container);
    453         }
    454 
    455         @Override
    456         protected boolean canAnimate() {
    457             return super.canAnimate();
    458         }
    459     }
    460 
    461     private void setArrayAdapter(AdapterView<ListAdapter> adapterView) {
    462         ((ListView) adapterView).setAdapter(new ArrayAdapter<String>(
    463                 mActivity, R.layout.adapterview_layout, FRUIT));
    464     }
    465 
    466     /**
    467      * this is a mock item click listener for check out call back
    468      */
    469     private class MockOnItemClickListener implements OnItemClickListener {
    470         private boolean mClicked;
    471 
    472         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    473             mClicked = true;
    474         }
    475 
    476         protected boolean isClicked() {
    477             return mClicked;
    478         }
    479     }
    480 
    481     /**
    482      * this is a mock long item click listener for check out call back
    483      */
    484     private class MockOnItemLongClickListener implements OnItemLongClickListener {
    485         private boolean mClicked;
    486 
    487         public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
    488             mClicked = true;
    489             return true;
    490         }
    491 
    492         protected boolean isClicked() {
    493             return mClicked;
    494         }
    495     }
    496 
    497     /**
    498      * this is a mock item selected listener for check out call lback
    499      */
    500     private class MockOnItemSelectedListener implements OnItemSelectedListener {
    501         private boolean mIsItemSelected;
    502         private boolean mIsNothingSelected;
    503 
    504         public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    505             mIsItemSelected = true;
    506         }
    507 
    508         public void onNothingSelected(AdapterView<?> parent) {
    509             mIsNothingSelected = true;
    510         }
    511 
    512         protected boolean isItemSelected() {
    513             return mIsItemSelected;
    514         }
    515 
    516         protected boolean isNothingSelected() {
    517             return mIsNothingSelected;
    518         }
    519     }
    520 }
    521