1/*
2 * Copyright (C) 2015 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
17package android.support.v7.app;
18
19import org.junit.Test;
20
21import android.content.Context;
22import android.content.res.Resources;
23import android.graphics.Color;
24import android.os.Build;
25import android.support.v7.appcompat.test.R;
26import android.support.v7.widget.AppCompatAutoCompleteTextView;
27import android.support.v7.widget.AppCompatButton;
28import android.support.v7.widget.AppCompatCheckBox;
29import android.support.v7.widget.AppCompatEditText;
30import android.support.v7.widget.AppCompatMultiAutoCompleteTextView;
31import android.support.v7.widget.AppCompatRadioButton;
32import android.support.v7.widget.AppCompatRatingBar;
33import android.support.v7.widget.AppCompatSpinner;
34import android.test.suitebuilder.annotation.SmallTest;
35import android.util.TypedValue;
36import android.view.LayoutInflater;
37import android.view.View;
38import android.view.ViewGroup;
39
40import static org.junit.Assert.assertEquals;
41import static org.junit.Assert.assertSame;
42import static org.junit.Assert.assertTrue;
43
44public class LayoutInflaterFactoryTestCase
45        extends BaseInstrumentationTestCase<LayoutInflaterFactoryTestActivity> {
46
47    public LayoutInflaterFactoryTestCase() {
48        super(LayoutInflaterFactoryTestActivity.class);
49    }
50
51    @Test
52    @SmallTest
53    public void testAndroidThemeInflation() throws Throwable {
54        runTestOnUiThread(new Runnable() {
55            @Override
56            public void run() {
57                final LayoutInflater inflater = LayoutInflater.from(getActivity());
58                assertThemedContext(inflater.inflate(R.layout.layout_android_theme, null));
59            }
60        });
61    }
62
63    @Test
64    @SmallTest
65    public void testAppThemeInflation() throws Throwable {
66        runTestOnUiThread(new Runnable() {
67            @Override
68            public void run() {
69                final LayoutInflater inflater = LayoutInflater.from(getActivity());
70                assertThemedContext(inflater.inflate(R.layout.layout_app_theme, null));
71            }
72        });
73    }
74
75    @Test
76    @SmallTest
77    public void testAndroidThemeWithChildrenInflation() throws Throwable {
78        if (Build.VERSION.SDK_INT < 11) {
79            // Propagation of themed context to children only works on API 11+. Ignoring test.
80            return;
81        }
82        runTestOnUiThread(new Runnable() {
83            @Override
84            public void run() {
85                LayoutInflater inflater = LayoutInflater.from(getActivity());
86                final ViewGroup root = (ViewGroup) inflater.inflate(
87                        R.layout.layout_android_theme_children, null);
88
89                assertThemedContext(root);
90
91                for (int i = 0; i < root.getChildCount(); i++) {
92                    final View child = root.getChildAt(i);
93                    assertThemedContext(child);
94                }
95            }
96        });
97    }
98
99    @Test
100    @SmallTest
101    public void testSpinnerInflation() throws Throwable {
102        testAppCompatWidgetInflation(R.layout.layout_spinner, AppCompatSpinner.class);
103    }
104
105    @Test
106    @SmallTest
107    public void testEditTextInflation() throws Throwable {
108        testAppCompatWidgetInflation(R.layout.layout_edittext, AppCompatEditText.class);
109    }
110
111    @Test
112    @SmallTest
113    public void testButtonInflation() throws Throwable {
114        testAppCompatWidgetInflation(R.layout.layout_button, AppCompatButton.class);
115    }
116
117    @Test
118    @SmallTest
119    public void testRadioButtonInflation() throws Throwable {
120        testAppCompatWidgetInflation(R.layout.layout_radiobutton, AppCompatRadioButton.class);
121    }
122
123    @Test
124    @SmallTest
125    public void testRadioButtonInflationWithVectorButton() throws Throwable {
126        testAppCompatWidgetInflation(R.layout.layout_radiobutton_vector,
127                AppCompatRadioButton.class);
128    }
129
130    @Test
131    @SmallTest
132    public void testCheckBoxInflation() throws Throwable {
133        testAppCompatWidgetInflation(R.layout.layout_checkbox, AppCompatCheckBox.class);
134    }
135
136    @Test
137    @SmallTest
138    public void testActvInflation() throws Throwable {
139        testAppCompatWidgetInflation(R.layout.layout_actv, AppCompatAutoCompleteTextView.class);
140    }
141
142    @Test
143    @SmallTest
144    public void testMactvInflation() throws Throwable {
145        testAppCompatWidgetInflation(R.layout.layout_mactv,
146                AppCompatMultiAutoCompleteTextView.class);
147    }
148
149    @Test
150    @SmallTest
151    public void testRatingBarInflation() throws Throwable {
152        testAppCompatWidgetInflation(R.layout.layout_ratingbar, AppCompatRatingBar.class);
153    }
154
155    @Test
156    @SmallTest
157    public void testDeclarativeOnClickWithContextWrapper() throws Throwable {
158        runTestOnUiThread(new Runnable() {
159            @Override
160            public void run() {
161                LayoutInflater inflater = LayoutInflater.from(getActivity());
162                View view = inflater.inflate(R.layout.layout_button_themed_onclick, null);
163
164                assertTrue(view.performClick());
165                assertTrue(getActivity().wasDeclarativeOnClickCalled());
166            }
167        });
168    }
169
170    private void testAppCompatWidgetInflation(final int layout, final Class<?> expectedClass)
171            throws Throwable {
172        runTestOnUiThread(new Runnable() {
173            @Override
174            public void run() {
175                LayoutInflater inflater = LayoutInflater.from(getActivity());
176                View view = inflater.inflate(layout, null);
177                assertSame("View is " + expectedClass.getSimpleName(), expectedClass,
178                        view.getClass());
179            }
180        });
181    }
182
183    private static void assertThemedContext(View view) {
184        final Context viewContext = view.getContext();
185
186        final TypedValue colorAccentValue = getColorAccentValue(viewContext.getTheme());
187        assertTrue(colorAccentValue.type >= TypedValue.TYPE_FIRST_COLOR_INT
188                && colorAccentValue.type <= TypedValue.TYPE_LAST_COLOR_INT);
189        assertEquals("View does not have ContextThemeWrapper context",
190                Color.MAGENTA, colorAccentValue.data);
191    }
192
193    private static TypedValue getColorAccentValue(final Resources.Theme theme) {
194        final TypedValue typedValue = new TypedValue();
195        theme.resolveAttribute(R.attr.colorAccent, typedValue, true);
196        return typedValue;
197    }
198}
199