| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.widget.cts; |
| |
| import org.xmlpull.v1.XmlPullParser; |
| |
| import android.app.Activity; |
| import android.content.Context; |
| import android.os.Parcelable; |
| import android.test.ActivityInstrumentationTestCase2; |
| import android.util.AttributeSet; |
| import android.util.SparseArray; |
| import android.util.Xml; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.view.animation.AnimationSet; |
| import android.view.animation.LayoutAnimationController; |
| import android.widget.AdapterView; |
| import android.widget.ArrayAdapter; |
| import android.widget.ImageView; |
| import android.widget.ListAdapter; |
| import android.widget.ListView; |
| import android.widget.AdapterView.OnItemClickListener; |
| import android.widget.AdapterView.OnItemLongClickListener; |
| import android.widget.AdapterView.OnItemSelectedListener; |
| import android.provider.Settings; |
| |
| import com.android.cts.widget.R; |
| |
| |
| public class AdapterViewTest extends ActivityInstrumentationTestCase2<AdapterViewCtsActivity> { |
| |
| private final static int INVALID_ID = -1; |
| |
| private final static int LAYOUT_WIDTH = 200; |
| private final static int LAYOUT_HEIGHT = 200; |
| |
| final String[] FRUIT = { "1", "2", "3", "4", "5", "6", "7", "8" }; |
| |
| private Activity mActivity; |
| private AdapterView<ListAdapter> mAdapterView; |
| |
| public AdapterViewTest() { |
| super("com.android.cts.widget", AdapterViewCtsActivity.class); |
| } |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| mActivity = getActivity(); |
| mAdapterView = new ListView(mActivity); |
| } |
| |
| public void testConstructor() { |
| XmlPullParser parser = mActivity.getResources().getXml(R.layout.adapterview_layout); |
| AttributeSet attrs = Xml.asAttributeSet(parser); |
| |
| new MockAdapterView(mActivity); |
| |
| new MockAdapterView(mActivity, attrs); |
| |
| new MockAdapterView(mActivity, attrs, 0); |
| |
| try { |
| new MockAdapterView(null); |
| fail("Should throw NullPointerException"); |
| } catch (NullPointerException e) { |
| //expected |
| } |
| |
| new MockAdapterView(mActivity, null, INVALID_ID); |
| } |
| |
| /** |
| * test not supported methods, all should throw UnsupportedOperationException |
| */ |
| public void testUnsupportedMethods() { |
| ListView subView = new ListView(mActivity); |
| |
| try { |
| mAdapterView.addView(subView); |
| fail("addView(View) is not supported in AdapterView."); |
| } catch (UnsupportedOperationException e) { |
| //expected |
| } |
| |
| try { |
| mAdapterView.addView(subView, 0); |
| fail("addView(View, int) is not supported in AdapterView."); |
| } catch (UnsupportedOperationException e) { |
| //expected |
| } |
| |
| try { |
| mAdapterView.addView(subView, (ViewGroup.LayoutParams) null); |
| fail("addView(View, ViewGroup.LayoutParams) is not supported in AdapterView."); |
| } catch (UnsupportedOperationException e) { |
| //expected |
| } |
| |
| try { |
| mAdapterView.addView(subView, 0, (ViewGroup.LayoutParams) null); |
| fail("addView(View, int, ViewGroup.LayoutParams) is not supported in AdapterView."); |
| } catch (UnsupportedOperationException e) { |
| //expected |
| } |
| |
| try { |
| mAdapterView.removeViewAt(0); |
| fail("removeViewAt(int) is not supported in AdapterView"); |
| } catch (UnsupportedOperationException e) { |
| //expected |
| } |
| |
| try { |
| mAdapterView.removeAllViews(); |
| fail("removeAllViews() is not supported in AdapterView"); |
| } catch (UnsupportedOperationException e) { |
| //expected |
| } |
| |
| try { |
| mAdapterView.removeView(subView); |
| fail("removeView(View) is not supported in AdapterView"); |
| } catch (UnsupportedOperationException e) { |
| //expected |
| } |
| |
| try { |
| mAdapterView.setOnClickListener(new android.view.View.OnClickListener() { |
| public void onClick(View v) { |
| } |
| }); |
| fail("function setOnClickListener(android.view.View.OnClickListener) " |
| + "should throw out runtime exception"); |
| } catch (RuntimeException e) { |
| // expected |
| } |
| } |
| |
| public void testGetCount() { |
| // Before setAdapter, the count should be zero. |
| assertEquals(0, mAdapterView.getCount()); |
| |
| setArrayAdapter(mAdapterView); |
| |
| // After setAdapter, the count should be the value return by adapter. |
| assertEquals(FRUIT.length, mAdapterView.getCount()); |
| } |
| |
| public void testAccessEmptyView() { |
| ImageView emptyView = new ImageView(mActivity); |
| |
| // If there is no adapter has been set, emptyView hasn't been set, there will be no |
| // emptyView return by getEmptyView(). |
| assertEquals(null, mAdapterView.getEmptyView()); |
| |
| // If the adapter is 0 count, emptyView has been set, the emptyView should be returned by |
| // getEmptyView. EmptyView will be set to Visible. |
| mAdapterView.setAdapter(new ArrayAdapter<String>( |
| mActivity, R.layout.adapterview_layout, new String[]{})); |
| emptyView.setVisibility(View.INVISIBLE); |
| assertEquals(View.INVISIBLE, emptyView.getVisibility()); |
| |
| // set empty view, for no item added, empty set to visible |
| mAdapterView.setEmptyView(emptyView); |
| assertSame(emptyView, mAdapterView.getEmptyView()); |
| assertEquals(View.VISIBLE, emptyView.getVisibility()); |
| |
| // If the adapter is not empty, the emptyView should also be returned by |
| // getEmptyView. EmptyView will be set to Gone. |
| setArrayAdapter(mAdapterView); |
| emptyView = new ImageView(mActivity); |
| |
| assertEquals(View.VISIBLE, emptyView.getVisibility()); |
| mAdapterView.setEmptyView(emptyView); |
| // for item added, emptyview is set to gone |
| assertEquals(emptyView, mAdapterView.getEmptyView()); |
| assertEquals(View.GONE, emptyView.getVisibility()); |
| |
| // null adapter should also show empty view |
| mAdapterView.setAdapter(null); |
| emptyView = new ImageView(mActivity); |
| emptyView.setVisibility(View.INVISIBLE); |
| assertEquals(View.INVISIBLE, emptyView.getVisibility()); |
| // set empty view |
| mAdapterView.setEmptyView(emptyView); |
| assertEquals(emptyView, mAdapterView.getEmptyView()); |
| assertEquals(View.VISIBLE, emptyView.getVisibility()); |
| } |
| |
| public void testAccessVisiblePosition() { |
| |
| assertEquals(0, mAdapterView.getFirstVisiblePosition()); |
| // If no adapter has been set, the value should be -1; |
| assertEquals(-1, mAdapterView.getLastVisiblePosition()); |
| |
| setArrayAdapter(mAdapterView); |
| |
| // LastVisiblePosition should be adapter's getCount - 1,by mocking method |
| float fontScale = Settings.System.getFloat(mActivity.getContentResolver(), Settings.System.FONT_SCALE, 1); |
| if (fontScale < 1) { |
| fontScale = 1; |
| } |
| float density = mActivity.getResources().getDisplayMetrics().density; |
| int bottom = (int) (LAYOUT_HEIGHT * density * fontScale); |
| mAdapterView.layout(0, 0, LAYOUT_WIDTH, bottom); |
| assertEquals(FRUIT.length - 1, mAdapterView.getLastVisiblePosition()); |
| } |
| |
| public void testItemOrItemIdAtPosition() { |
| // no adapter set |
| assertNull(mAdapterView.getItemAtPosition(0)); |
| assertEquals(AdapterView.INVALID_ROW_ID, mAdapterView.getItemIdAtPosition(1)); |
| |
| // after adapter set |
| setArrayAdapter(mAdapterView); |
| int count = mAdapterView.getAdapter().getCount(); |
| |
| for (int i = 0; i < count; i++) { |
| assertEquals(FRUIT[i], mAdapterView.getItemAtPosition(i)); |
| } |
| assertNull(mAdapterView.getItemAtPosition(-1)); |
| try { |
| mAdapterView.getItemAtPosition(FRUIT.length); |
| fail("should throw IndexOutOfBoundsException"); |
| } catch (IndexOutOfBoundsException e) { |
| //expected |
| } |
| |
| for (int i = 0; i < count; i++) { |
| assertEquals(i, mAdapterView.getItemIdAtPosition(i)); |
| } |
| assertEquals(AdapterView.INVALID_ROW_ID, mAdapterView.getItemIdAtPosition(-1)); |
| assertEquals(FRUIT.length, mAdapterView.getItemIdAtPosition(FRUIT.length)); |
| } |
| |
| public void testAccessOnItemClickAndLongClickListener() { |
| MockOnItemClickListener clickListener = new MockOnItemClickListener(); |
| MockOnItemLongClickListener longClickListener = new MockOnItemLongClickListener(); |
| |
| assertFalse(mAdapterView.performItemClick(null, 0, 0)); |
| |
| mAdapterView.setOnItemClickListener(clickListener); |
| mAdapterView.setOnItemLongClickListener(longClickListener); |
| |
| assertFalse(clickListener.isClicked()); |
| assertTrue(mAdapterView.performItemClick(null, 0, 0)); |
| assertTrue(clickListener.isClicked()); |
| |
| setArrayAdapter(mAdapterView); |
| assertFalse(longClickListener.isClicked()); |
| mAdapterView.layout(0, 0, LAYOUT_WIDTH, LAYOUT_HEIGHT); |
| assertTrue(mAdapterView.showContextMenuForChild(mAdapterView.getChildAt(0))); |
| assertTrue(longClickListener.isClicked()); |
| } |
| |
| public void testAccessOnItemSelectedListener() { |
| // FIXME: we can not select the item in touch mode, how can we change the mode to test |
| setArrayAdapter(mAdapterView); |
| MockOnItemSelectedListener selectedListener = new MockOnItemSelectedListener(); |
| mAdapterView.setOnItemSelectedListener(selectedListener); |
| |
| // mAdapterView.layout(0, 0, LAYOUT_WIDTH, LAYOUT_HEIGHT); |
| // |
| // assertFalse(selectedListener.isItemSelected()); |
| // assertFalse(selectedListener.isNothingSelected()); |
| // |
| // mAdapterView.setSelection(1); |
| // assertTrue(selectedListener.isItemSelected()); |
| // assertFalse(selectedListener.isNothingSelected()); |
| // |
| // mAdapterView.setSelection(-1); |
| // assertTrue(selectedListener.isItemSelected()); |
| // assertTrue(selectedListener.isNothingSelected()); |
| // |
| // mAdapterView.setSelection(FRUIT.length); |
| // assertTrue(selectedListener.isItemSelected()); |
| // assertTrue(selectedListener.isNothingSelected()); |
| } |
| |
| /* |
| * Get the position within the adapter's data set for the view, where view is a an adapter item |
| * or a descendant of an adapter item. |
| * when scroll down the list, the item's position may be 5 or 6 be on the screen |
| * but to the layout parent ,it may still be the 1, 2 child for there always has 3,4 views there |
| * it's hard to scroll the list in unit test, so we just test without scrolling |
| * this means the position of item is same as position of the children in parent layout |
| */ |
| public void testGetPositionForView() { |
| setArrayAdapter(mAdapterView); |
| mAdapterView.layout(0, 0, LAYOUT_WIDTH, LAYOUT_HEIGHT); |
| |
| int count = mAdapterView.getChildCount(); |
| for (int i = 0; i < count; i++) { |
| assertEquals(i, mAdapterView.getPositionForView(mAdapterView.getChildAt(i))); |
| } |
| |
| try { |
| assertEquals(AdapterView.INVALID_POSITION, mAdapterView.getPositionForView(null)); |
| fail("Should throw NullPointerException"); |
| } catch (NullPointerException e) { |
| //expected |
| } |
| |
| assertEquals(AdapterView.INVALID_POSITION, |
| mAdapterView.getPositionForView(new ImageView(mActivity))); |
| } |
| |
| public void testChangeFocusable() { |
| assertFalse(mAdapterView.isFocusable()); |
| assertFalse(mAdapterView.isFocusableInTouchMode()); |
| |
| // no item added will never focusable |
| assertNull(mAdapterView.getAdapter()); |
| mAdapterView.setFocusable(true); |
| assertFalse(mAdapterView.isFocusable()); |
| assertFalse(mAdapterView.isFocusableInTouchMode()); |
| |
| // only focusable with children added |
| setArrayAdapter(mAdapterView); |
| assertTrue(mAdapterView.getAdapter().getCount() > 0); |
| mAdapterView.setFocusable(true); |
| assertTrue(mAdapterView.isFocusable()); |
| assertTrue(mAdapterView.isFocusableInTouchMode()); |
| |
| mAdapterView.setFocusable(false); |
| assertFalse(mAdapterView.isFocusable()); |
| assertFalse(mAdapterView.isFocusableInTouchMode()); |
| } |
| |
| /* |
| * skip this test, no need to test |
| */ |
| public void testOnLayout() { |
| // onLayout() is implementation details, do NOT test |
| } |
| |
| /* |
| * set and get the selected id, position and item. |
| * values will not change if invalid id given. |
| */ |
| public void testGetSelected() { |
| assertEquals(AdapterView.INVALID_ROW_ID, mAdapterView.getSelectedItemId()); |
| assertEquals(AdapterView.INVALID_POSITION, mAdapterView.getSelectedItemPosition()); |
| assertEquals(null, mAdapterView.getSelectedItem()); |
| |
| // set adapter, 0 selected by default |
| setArrayAdapter(mAdapterView); |
| assertEquals(0, mAdapterView.getSelectedItemId()); |
| assertEquals(0, mAdapterView.getSelectedItemPosition()); |
| assertEquals(FRUIT[0], mAdapterView.getSelectedItem()); |
| |
| int expectedId = 1; |
| mAdapterView.setSelection(expectedId); |
| assertEquals(expectedId, mAdapterView.getSelectedItemId()); |
| assertEquals(expectedId, mAdapterView.getSelectedItemPosition()); |
| assertEquals(FRUIT[expectedId], mAdapterView.getSelectedItem()); |
| |
| // invalid id will be ignored |
| expectedId = -1; |
| mAdapterView.setSelection(expectedId); |
| assertEquals(1, mAdapterView.getSelectedItemId()); |
| assertEquals(1, mAdapterView.getSelectedItemPosition()); |
| assertEquals(FRUIT[1], mAdapterView.getSelectedItem()); |
| |
| expectedId = mAdapterView.getCount(); |
| mAdapterView.setSelection(expectedId); |
| assertEquals(1, mAdapterView.getSelectedItemId()); |
| assertEquals(1, mAdapterView.getSelectedItemPosition()); |
| assertEquals(FRUIT[1], mAdapterView.getSelectedItem()); |
| } |
| |
| /* |
| * not update this test until the ViewGroup's test finish. |
| */ |
| public void testDispatchSaveInstanceState() { |
| MockAdapterView adapterView = new MockAdapterView(mActivity); |
| adapterView.setSaveEnabled(true); |
| adapterView.setId(1); |
| SparseArray<Parcelable> sa = new SparseArray<Parcelable>(); |
| adapterView.dispatchSaveInstanceState(sa); |
| assertTrue(sa.size() > 0); |
| } |
| |
| /* |
| * not update this test until the ViewGroup's test finish. |
| */ |
| public void testDispatchRestoreInstanceState() { |
| MockAdapterView adapterView = new MockAdapterView(mActivity); |
| adapterView.setSaveEnabled(true); |
| adapterView.setId(1); |
| SparseArray<Parcelable> sparseArray = new SparseArray<Parcelable>(); |
| adapterView.dispatchRestoreInstanceState(sparseArray); |
| } |
| |
| /* |
| * whether this view can has animation layout |
| * if no child added, it always return false |
| * this method is protected, so we involve the mock |
| */ |
| public void testCanAnimate() { |
| MockAdapterView adapterView = new MockAdapterView(mActivity); |
| LayoutAnimationController lAC = new LayoutAnimationController(new AnimationSet(true)); |
| |
| // no child added, always false |
| assertNull(adapterView.getAdapter()); |
| adapterView.setLayoutAnimation(lAC); |
| assertFalse(adapterView.canAnimate()); |
| |
| setArrayAdapter(adapterView); |
| |
| assertTrue(adapterView.getAdapter().getCount() > 0); |
| assertTrue(adapterView.canAnimate()); |
| } |
| |
| private static class MockAdapterView extends ListView{ |
| |
| public MockAdapterView(Context context) { |
| super(context); |
| } |
| |
| public MockAdapterView(Context context, AttributeSet attrs) { |
| super(context, attrs); |
| } |
| |
| public MockAdapterView(Context context, AttributeSet attrs, int defStyle) { |
| super(context, attrs, defStyle); |
| } |
| |
| @Override |
| protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { |
| super.dispatchRestoreInstanceState(container); |
| } |
| |
| @Override |
| protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) { |
| super.dispatchSaveInstanceState(container); |
| } |
| |
| @Override |
| protected boolean canAnimate() { |
| return super.canAnimate(); |
| } |
| } |
| |
| private void setArrayAdapter(AdapterView<ListAdapter> adapterView) { |
| ((ListView) adapterView).setAdapter(new ArrayAdapter<String>( |
| mActivity, R.layout.adapterview_layout, FRUIT)); |
| } |
| |
| /** |
| * this is a mock item click listener for check out call back |
| */ |
| private class MockOnItemClickListener implements OnItemClickListener { |
| private boolean mClicked; |
| |
| public void onItemClick(AdapterView<?> parent, View view, int position, long id) { |
| mClicked = true; |
| } |
| |
| protected boolean isClicked() { |
| return mClicked; |
| } |
| } |
| |
| /** |
| * this is a mock long item click listener for check out call back |
| */ |
| private class MockOnItemLongClickListener implements OnItemLongClickListener { |
| private boolean mClicked; |
| |
| public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { |
| mClicked = true; |
| return true; |
| } |
| |
| protected boolean isClicked() { |
| return mClicked; |
| } |
| } |
| |
| /** |
| * this is a mock item selected listener for check out call lback |
| */ |
| private class MockOnItemSelectedListener implements OnItemSelectedListener { |
| private boolean mIsItemSelected; |
| private boolean mIsNothingSelected; |
| |
| public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { |
| mIsItemSelected = true; |
| } |
| |
| public void onNothingSelected(AdapterView<?> parent) { |
| mIsNothingSelected = true; |
| } |
| |
| protected boolean isItemSelected() { |
| return mIsItemSelected; |
| } |
| |
| protected boolean isNothingSelected() { |
| return mIsNothingSelected; |
| } |
| } |
| } |