AppCompatSpinnerTest.java revision 1d6e3840486930e276d142861afb6c7e72d5ce72
1/*
2 * Copyright (C) 2016 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 */
16package android.support.v7.widget;
17
18import android.content.res.Resources;
19import android.support.annotation.ColorInt;
20import android.support.annotation.ColorRes;
21import android.support.annotation.IdRes;
22import android.support.v4.content.ContextCompat;
23import android.support.v4.content.res.ResourcesCompat;
24import android.support.v7.appcompat.test.R;
25import android.test.suitebuilder.annotation.SmallTest;
26import org.hamcrest.Matcher;
27import org.junit.Test;
28
29import static android.support.test.espresso.Espresso.onView;
30import static android.support.test.espresso.action.ViewActions.click;
31import static android.support.test.espresso.assertion.ViewAssertions.matches;
32import static android.support.test.espresso.matcher.RootMatchers.isPlatformPopup;
33import static android.support.test.espresso.matcher.ViewMatchers.withId;
34import static android.support.test.espresso.matcher.ViewMatchers.withText;
35import static android.support.v7.testutils.TestUtilsMatchers.hasChild;
36import static android.support.v7.testutils.TestUtilsMatchers.isCombinedBackground;
37
38/**
39 * In addition to all tinting-related tests done by the base class, this class provides
40 * tests specific to {@link AppCompatSpinner} class.
41 */
42@SmallTest
43public class AppCompatSpinnerTest
44        extends AppCompatBaseViewTest<AppCompatSpinnerActivity, AppCompatSpinner> {
45    public AppCompatSpinnerTest() {
46        super(AppCompatSpinnerActivity.class);
47    }
48
49    @Override
50    protected boolean hasBackgroundByDefault() {
51        // Spinner has default background set on it
52        return true;
53    }
54
55    /**
56     * Helper method that verifies that the popup for the specified {@link AppCompatSpinner}
57     * is themed with the specified color.
58     */
59    private void verifySpinnerPopupTheming(@IdRes int spinnerId,
60            @ColorRes int expectedPopupColorResId, boolean matchDropDownListView) {
61        final Resources res = mActivityTestRule.getActivity().getResources();
62        final @ColorInt int expectedPopupColor =
63                ResourcesCompat.getColor(res, expectedPopupColorResId, null);
64        final AppCompatSpinner spinner = (AppCompatSpinner) mContainer.findViewById(spinnerId);
65
66        // Click the spinner to show its popup content
67        onView(withId(spinnerId)).perform(click());
68
69        // The internal implementation details of the AppCompatSpinner's popup content depends
70        // on the platform version itself (in android.widget.PopupWindow) as well as on when the
71        // popup theme is being applied first (in XML or at runtime). Instead of trying to catch
72        // all possible variations of how the popup content is wrapped, we use a view matcher that
73        // creates a single bitmap that combines backgrounds starting from the parent of the
74        // popup content items upwards (drawing them in reverse order), and then tests that the
75        // combined bitmap matches the expected color fill. This should remove dependency on the
76        // internal implementation details on which exact "chrome" part of the popup has the
77        // matching background.
78        String itemText = (String) spinner.getAdapter().getItem(2);
79        Matcher popupContentMatcher = hasChild(withText(itemText));
80        onView(popupContentMatcher).inRoot(isPlatformPopup()).check(
81                matches(isCombinedBackground(expectedPopupColor)));
82
83        // Click an entry in the popup to dismiss it
84        onView(withText(itemText)).perform(click());
85    }
86
87    @Test
88    public void testPopupThemingFromXmlAttribute() {
89        verifySpinnerPopupTheming(R.id.view_magenta_themed_popup, R.color.test_magenta, true);
90    }
91
92    @Test
93    public void testUnthemedPopupRuntimeTheming() {
94        final AppCompatSpinner spinner =
95                (AppCompatSpinner) mContainer.findViewById(R.id.view_unthemed_popup);
96        spinner.setPopupBackgroundResource(R.drawable.test_background_blue);
97        verifySpinnerPopupTheming(R.id.view_unthemed_popup, R.color.test_blue, false);
98
99        // Set a different popup background
100        spinner.setPopupBackgroundDrawable(ContextCompat.getDrawable(
101                mActivityTestRule.getActivity(), R.drawable.test_background_green));
102        verifySpinnerPopupTheming(R.id.view_unthemed_popup, R.color.test_green, false);
103    }
104
105    @Test
106    public void testThemedPopupRuntimeTheming() {
107        final AppCompatSpinner spinner =
108                (AppCompatSpinner) mContainer.findViewById(R.id.view_ocean_themed_popup);
109        verifySpinnerPopupTheming(R.id.view_ocean_themed_popup, R.color.ocean_default, true);
110
111        // Now set a different popup background
112        spinner.setPopupBackgroundResource(R.drawable.test_background_red);
113        verifySpinnerPopupTheming(R.id.view_ocean_themed_popup, R.color.test_red, false);
114
115        // Set a different popup background
116        spinner.setPopupBackgroundDrawable(ContextCompat.getDrawable(
117                mActivityTestRule.getActivity(), R.drawable.test_background_blue));
118        verifySpinnerPopupTheming(R.id.view_ocean_themed_popup, R.color.test_blue, false);
119    }
120}
121