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 static org.junit.Assert.assertEquals;
     20 import static org.junit.Assert.assertFalse;
     21 import static org.junit.Assert.assertNotNull;
     22 import static org.junit.Assert.assertNull;
     23 import static org.junit.Assert.assertSame;
     24 import static org.junit.Assert.assertTrue;
     25 import static org.mockito.Matchers.any;
     26 import static org.mockito.Mockito.mock;
     27 import static org.mockito.Mockito.never;
     28 import static org.mockito.Mockito.reset;
     29 import static org.mockito.Mockito.spy;
     30 import static org.mockito.Mockito.times;
     31 import static org.mockito.Mockito.verify;
     32 import static org.mockito.Mockito.verifyZeroInteractions;
     33 
     34 import android.app.Activity;
     35 import android.app.Instrumentation;
     36 import android.content.Context;
     37 import android.content.res.ColorStateList;
     38 import android.graphics.Canvas;
     39 import android.graphics.Color;
     40 import android.graphics.PorterDuff;
     41 import android.graphics.Rect;
     42 import android.graphics.drawable.ColorDrawable;
     43 import android.graphics.drawable.Drawable;
     44 import android.os.Parcelable;
     45 import android.support.test.InstrumentationRegistry;
     46 import android.support.test.annotation.UiThreadTest;
     47 import android.support.test.filters.SmallTest;
     48 import android.support.test.rule.ActivityTestRule;
     49 import android.support.test.runner.AndroidJUnit4;
     50 import android.util.AttributeSet;
     51 import android.util.StateSet;
     52 import android.util.Xml;
     53 import android.view.Gravity;
     54 import android.view.View;
     55 import android.widget.CompoundButton;
     56 import android.widget.cts.util.TestUtils;
     57 
     58 import org.junit.Before;
     59 import org.junit.Rule;
     60 import org.junit.Test;
     61 import org.junit.runner.RunWith;
     62 import org.xmlpull.v1.XmlPullParser;
     63 
     64 /**
     65  * Test {@link CompoundButton}.
     66  */
     67 @SmallTest
     68 @RunWith(AndroidJUnit4.class)
     69 public class CompoundButtonTest  {
     70     private Instrumentation mInstrumentation;
     71     private Activity mActivity;
     72     private CompoundButton mCompoundButton;
     73 
     74     @Rule
     75     public ActivityTestRule<CompoundButtonCtsActivity> mActivityRule =
     76             new ActivityTestRule<>(CompoundButtonCtsActivity.class);
     77 
     78     @Before
     79     public void setup() {
     80         mInstrumentation = InstrumentationRegistry.getInstrumentation();
     81         mActivity = mActivityRule.getActivity();
     82         mCompoundButton = (CompoundButton) mActivity.findViewById(R.id.compound_button);
     83     }
     84 
     85     @Test
     86     public void testConstructor() {
     87         XmlPullParser parser = mActivity.getResources().getXml(R.layout.compoundbutton_layout);
     88         AttributeSet mAttrSet = Xml.asAttributeSet(parser);
     89 
     90         new MockCompoundButton(mActivity, mAttrSet, 0);
     91         new MockCompoundButton(mActivity, mAttrSet);
     92         new MockCompoundButton(mActivity);
     93     }
     94 
     95     @Test(expected=NullPointerException.class)
     96     public void testConstructorWithNullContext1() {
     97         new MockCompoundButton(null);
     98     }
     99 
    100     @Test(expected=NullPointerException.class)
    101     public void testConstructorWithNullContext2() {
    102         new MockCompoundButton(null, null);
    103     }
    104 
    105     @Test(expected=NullPointerException.class)
    106     public void testConstructorWithNullContext3() {
    107         new MockCompoundButton(null, null, -1);
    108     }
    109 
    110     @UiThreadTest
    111     @Test
    112     public void testAccessChecked() {
    113         CompoundButton.OnCheckedChangeListener mockCheckedChangeListener =
    114                 mock(CompoundButton.OnCheckedChangeListener.class);
    115         mCompoundButton.setOnCheckedChangeListener(mockCheckedChangeListener);
    116         assertFalse(mCompoundButton.isChecked());
    117         verifyZeroInteractions(mockCheckedChangeListener);
    118 
    119         mCompoundButton.setChecked(true);
    120         assertTrue(mCompoundButton.isChecked());
    121         verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCompoundButton, true);
    122 
    123         reset(mockCheckedChangeListener);
    124         mCompoundButton.setChecked(true);
    125         assertTrue(mCompoundButton.isChecked());
    126         verifyZeroInteractions(mockCheckedChangeListener);
    127 
    128         mCompoundButton.setChecked(false);
    129         assertFalse(mCompoundButton.isChecked());
    130         verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCompoundButton, false);
    131     }
    132 
    133     @UiThreadTest
    134     @Test
    135     public void testSetOnCheckedChangeListener() {
    136         CompoundButton.OnCheckedChangeListener mockCheckedChangeListener =
    137                 mock(CompoundButton.OnCheckedChangeListener.class);
    138         mCompoundButton.setOnCheckedChangeListener(mockCheckedChangeListener);
    139         assertFalse(mCompoundButton.isChecked());
    140         verifyZeroInteractions(mockCheckedChangeListener);
    141 
    142         mCompoundButton.setChecked(true);
    143         verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCompoundButton, true);
    144 
    145         // set null
    146         mCompoundButton.setOnCheckedChangeListener(null);
    147         reset(mockCheckedChangeListener);
    148         mCompoundButton.setChecked(false);
    149         verifyZeroInteractions(mockCheckedChangeListener);
    150     }
    151 
    152     @UiThreadTest
    153     @Test
    154     public void testToggle() {
    155         assertFalse(mCompoundButton.isChecked());
    156 
    157         mCompoundButton.toggle();
    158         assertTrue(mCompoundButton.isChecked());
    159 
    160         mCompoundButton.toggle();
    161         assertFalse(mCompoundButton.isChecked());
    162 
    163         mCompoundButton.setChecked(true);
    164         mCompoundButton.toggle();
    165         assertFalse(mCompoundButton.isChecked());
    166     }
    167 
    168     @UiThreadTest
    169     @Test
    170     public void testPerformClick() {
    171         assertFalse(mCompoundButton.isChecked());
    172 
    173         // performClick without OnClickListener will return false.
    174         assertFalse(mCompoundButton.performClick());
    175         assertTrue(mCompoundButton.isChecked());
    176 
    177         assertFalse(mCompoundButton.performClick());
    178         assertFalse(mCompoundButton.isChecked());
    179 
    180         // performClick with OnClickListener will return true.
    181         mCompoundButton.setOnClickListener((view) -> {});
    182         assertTrue(mCompoundButton.performClick());
    183         assertTrue(mCompoundButton.isChecked());
    184 
    185         assertTrue(mCompoundButton.performClick());
    186         assertFalse(mCompoundButton.isChecked());
    187     }
    188 
    189     @UiThreadTest
    190     @Test
    191     public void testDrawableStateChanged() {
    192         MockCompoundButton compoundButton = new MockCompoundButton(mActivity);
    193         assertFalse(compoundButton.isChecked());
    194         // drawableStateChanged without any drawables.
    195         compoundButton.drawableStateChanged();
    196 
    197         // drawableStateChanged when CheckMarkDrawable is not null.
    198         Drawable drawable = mActivity.getDrawable(R.drawable.statelistdrawable);
    199         compoundButton.setButtonDrawable(drawable);
    200         drawable.setState(null);
    201         assertNull(drawable.getState());
    202 
    203         compoundButton.drawableStateChanged();
    204         assertNotNull(drawable.getState());
    205         assertSame(compoundButton.getDrawableState(), drawable.getState());
    206     }
    207 
    208     @UiThreadTest
    209     @Test
    210     public void testSetButtonDrawableByDrawable() {
    211         // set null drawable
    212         mCompoundButton.setButtonDrawable(null);
    213         assertNull(mCompoundButton.getButtonDrawable());
    214 
    215         // set drawable when button is GONE
    216         mCompoundButton.setVisibility(View.GONE);
    217         Drawable firstDrawable = mActivity.getDrawable(R.drawable.scenery);
    218         firstDrawable.setVisible(true, false);
    219         assertEquals(StateSet.WILD_CARD, firstDrawable.getState());
    220 
    221         mCompoundButton.setButtonDrawable(firstDrawable);
    222         assertSame(firstDrawable, mCompoundButton.getButtonDrawable());
    223         assertFalse(firstDrawable.isVisible());
    224 
    225         // update drawable when button is VISIBLE
    226         mCompoundButton.setVisibility(View.VISIBLE);
    227         Drawable secondDrawable = mActivity.getDrawable(R.drawable.pass);
    228         secondDrawable.setVisible(true, false);
    229         assertEquals(StateSet.WILD_CARD, secondDrawable.getState());
    230 
    231         mCompoundButton.setButtonDrawable(secondDrawable);
    232         assertSame(secondDrawable, mCompoundButton.getButtonDrawable());
    233         assertTrue(secondDrawable.isVisible());
    234         // the firstDrawable is not active.
    235         assertFalse(firstDrawable.isVisible());
    236     }
    237 
    238     @UiThreadTest
    239     @Test
    240     public void testSetButtonDrawableById() {
    241         // resId is 0
    242         mCompoundButton.setButtonDrawable(0);
    243 
    244         // set drawable
    245         mCompoundButton.setButtonDrawable(R.drawable.scenery);
    246 
    247         // set the same drawable again
    248         mCompoundButton.setButtonDrawable(R.drawable.scenery);
    249 
    250         // update drawable
    251         mCompoundButton.setButtonDrawable(R.drawable.pass);
    252     }
    253 
    254     @Test
    255     public void testOnCreateDrawableState() {
    256         // compoundButton is not checked, append 0 to state array.
    257         MockCompoundButton compoundButton = new MockCompoundButton(mActivity);
    258         int[] state = compoundButton.onCreateDrawableState(0);
    259         assertEquals(0, state[state.length - 1]);
    260 
    261         // compoundButton is checked, append R.attr.state_checked to state array.
    262         compoundButton.setChecked(true);
    263         int[] checkedState = compoundButton.onCreateDrawableState(0);
    264         assertEquals(state[0], checkedState[0]);
    265         assertEquals(android.R.attr.state_checked,
    266                 checkedState[checkedState.length - 1]);
    267 
    268         // compoundButton is not checked again.
    269         compoundButton.setChecked(false);
    270         state = compoundButton.onCreateDrawableState(0);
    271         assertEquals(0, state[state.length - 1]);
    272     }
    273 
    274     @Test
    275     public void testOnDraw() {
    276         int viewHeight;
    277         int drawableWidth;
    278         int drawableHeight;
    279         Rect bounds;
    280         Drawable drawable;
    281         Canvas canvas = new Canvas(android.graphics.Bitmap.createBitmap(100, 100,
    282                 android.graphics.Bitmap.Config.ARGB_8888));
    283         MockCompoundButton compoundButton;
    284 
    285         // onDraw when there is no drawable
    286         compoundButton = new MockCompoundButton(mActivity);
    287         compoundButton.onDraw(canvas);
    288 
    289         // onDraw when Gravity.TOP, it's default.
    290         compoundButton = new MockCompoundButton(mActivity);
    291         drawable = mActivity.getDrawable(R.drawable.scenery);
    292         compoundButton.setButtonDrawable(drawable);
    293         viewHeight = compoundButton.getHeight();
    294         drawableWidth = drawable.getIntrinsicWidth();
    295         drawableHeight = drawable.getIntrinsicHeight();
    296 
    297         compoundButton.onDraw(canvas);
    298         bounds = drawable.copyBounds();
    299         assertEquals(0, bounds.left);
    300         assertEquals(drawableWidth, bounds.right);
    301         assertEquals(0, bounds.top);
    302         assertEquals(drawableHeight, bounds.bottom);
    303 
    304         // onDraw when Gravity.BOTTOM
    305         compoundButton.setGravity(Gravity.BOTTOM);
    306         compoundButton.onDraw(canvas);
    307         bounds = drawable.copyBounds();
    308         assertEquals(0, bounds.left);
    309         assertEquals(drawableWidth, bounds.right);
    310         assertEquals(viewHeight - drawableHeight, bounds.top);
    311         assertEquals(viewHeight, bounds.bottom);
    312 
    313         // onDraw when Gravity.CENTER_VERTICAL
    314         compoundButton.setGravity(Gravity.CENTER_VERTICAL);
    315         compoundButton.onDraw(canvas);
    316         bounds = drawable.copyBounds();
    317         assertEquals(0, bounds.left);
    318         assertEquals(drawableWidth, bounds.right);
    319         assertEquals( (viewHeight - drawableHeight) / 2, bounds.top);
    320         assertEquals( (viewHeight - drawableHeight) / 2 + drawableHeight, bounds.bottom);
    321     }
    322 
    323     @UiThreadTest
    324     @Test
    325     public void testAccessInstanceState() {
    326         Parcelable state;
    327 
    328         assertFalse(mCompoundButton.isChecked());
    329         assertFalse(mCompoundButton.getFreezesText());
    330 
    331         state = mCompoundButton.onSaveInstanceState();
    332         assertNotNull(state);
    333         assertFalse(mCompoundButton.getFreezesText());
    334 
    335         mCompoundButton.setChecked(true);
    336 
    337         mCompoundButton.onRestoreInstanceState(state);
    338         assertFalse(mCompoundButton.isChecked());
    339         assertTrue(mCompoundButton.isLayoutRequested());
    340     }
    341 
    342     @Test
    343     public void testVerifyDrawable() {
    344         MockCompoundButton compoundButton = new MockCompoundButton(mActivity);
    345         Drawable drawable = mActivity.getDrawable(R.drawable.scenery);
    346 
    347         assertTrue(compoundButton.verifyDrawable(null));
    348         assertFalse(compoundButton.verifyDrawable(drawable));
    349 
    350         compoundButton.setButtonDrawable(drawable);
    351         assertTrue(compoundButton.verifyDrawable(null));
    352         assertTrue(compoundButton.verifyDrawable(drawable));
    353     }
    354 
    355     @UiThreadTest
    356     @Test
    357     public void testButtonTint() {
    358         CompoundButton tintedButton = (CompoundButton) mActivity.findViewById(R.id.button_tint);
    359 
    360         assertEquals("Button tint inflated correctly",
    361                 Color.WHITE, tintedButton.getButtonTintList().getDefaultColor());
    362         assertEquals("Button tint mode inflated correctly",
    363                 PorterDuff.Mode.SRC_OVER, tintedButton.getButtonTintMode());
    364 
    365         Drawable mockDrawable = spy(new ColorDrawable(Color.GREEN));
    366 
    367         mCompoundButton.setButtonDrawable(mockDrawable);
    368         // No button tint applied by default
    369         verify(mockDrawable, never()).setTintList(any(ColorStateList.class));
    370 
    371         mCompoundButton.setButtonTintList(ColorStateList.valueOf(Color.WHITE));
    372         // Button tint applied when setButtonTintList() called after setButton()
    373         verify(mockDrawable, times(1)).setTintList(TestUtils.colorStateListOf(Color.WHITE));
    374 
    375         reset(mockDrawable);
    376         mCompoundButton.setButtonDrawable(null);
    377         mCompoundButton.setButtonDrawable(mockDrawable);
    378         // Button tint applied when setButtonTintList() called before setButton()
    379         verify(mockDrawable, times(1)).setTintList(TestUtils.colorStateListOf(Color.WHITE));
    380     }
    381 
    382     public static final class MockCompoundButton extends CompoundButton {
    383         public MockCompoundButton(Context context) {
    384             super(context);
    385         }
    386 
    387         public MockCompoundButton(Context context, AttributeSet attrs) {
    388             super(context, attrs, 0);
    389         }
    390 
    391         public MockCompoundButton(Context context, AttributeSet attrs, int defStyle) {
    392             super(context, attrs, defStyle);
    393         }
    394 
    395         @Override
    396         protected void drawableStateChanged() {
    397             super.drawableStateChanged();
    398         }
    399 
    400         @Override
    401         protected void onDraw(Canvas canvas) {
    402             super.onDraw(canvas);
    403         }
    404 
    405         @Override
    406         protected int[] onCreateDrawableState(int extraSpace) {
    407             return super.onCreateDrawableState(extraSpace);
    408         }
    409 
    410         @Override
    411         protected boolean verifyDrawable(Drawable who) {
    412             return super.verifyDrawable(who);
    413         }
    414     }
    415 }
    416