1 package org.robolectric.shadows;
2 
3 import static org.assertj.core.api.Assertions.assertThat;
4 import static org.junit.Assert.fail;
5 import static org.robolectric.Robolectric.buildActivity;
6 import static org.robolectric.Shadows.shadowOf;
7 
8 import android.app.Activity;
9 import android.content.res.Resources;
10 import android.content.res.TypedArray;
11 import android.graphics.Color;
12 import android.graphics.drawable.ColorDrawable;
13 import android.os.Bundle;
14 import android.util.AttributeSet;
15 import android.util.TypedValue;
16 import android.view.View;
17 import android.widget.Button;
18 import org.junit.Before;
19 import org.junit.Test;
20 import org.junit.runner.RunWith;
21 import org.robolectric.R;
22 import org.robolectric.Robolectric;
23 import org.robolectric.RobolectricTestRunner;
24 import org.robolectric.RuntimeEnvironment;
25 import org.robolectric.android.controller.ActivityController;
26 
27 @RunWith(RobolectricTestRunner.class)
28 public class ShadowThemeTest {
29 
30   private Resources resources;
31 
32   @Before
setUp()33   public void setUp() throws Exception {
34     resources = RuntimeEnvironment.application.getResources();
35   }
36 
withEmptyTheme_returnsEmptyAttributes()37   @Test public void withEmptyTheme_returnsEmptyAttributes() throws Exception {
38     assertThat(resources.newTheme().obtainStyledAttributes(new int[] {R.attr.string1}).hasValue(0)).isFalse();
39   }
40 
whenExplicitlySetOnActivity_afterSetContentView_activityGetsThemeFromActivityInManifest()41   @Test public void whenExplicitlySetOnActivity_afterSetContentView_activityGetsThemeFromActivityInManifest() throws Exception {
42     TestActivity activity = buildActivity(TestActivityWithAnotherTheme.class).create().get();
43     activity.setTheme(R.style.Theme_Robolectric);
44     Button theButton = (Button) activity.findViewById(R.id.button);
45     ColorDrawable background = (ColorDrawable) theButton.getBackground();
46     assertThat(background.getColor()).isEqualTo(0xffff0000);
47   }
48 
whenExplicitlySetOnActivity_beforeSetContentView_activityUsesNewTheme()49   @Test public void whenExplicitlySetOnActivity_beforeSetContentView_activityUsesNewTheme() throws Exception {
50     ActivityController<TestActivityWithAnotherTheme> activityController = buildActivity(TestActivityWithAnotherTheme.class);
51     TestActivity activity = activityController.get();
52     activity.setTheme(R.style.Theme_Robolectric);
53     activityController.create();
54     Button theButton = (Button) activity.findViewById(R.id.button);
55     ColorDrawable background = (ColorDrawable) theButton.getBackground();
56     assertThat(background.getColor()).isEqualTo(0xff00ff00);
57   }
58 
whenSetOnActivityInManifest_activityGetsThemeFromActivityInManifest()59   @Test public void whenSetOnActivityInManifest_activityGetsThemeFromActivityInManifest() throws Exception {
60     TestActivity activity = buildActivity(TestActivityWithAnotherTheme.class).create().get();
61     Button theButton = (Button) activity.findViewById(R.id.button);
62     ColorDrawable background = (ColorDrawable) theButton.getBackground();
63     assertThat(background.getColor()).isEqualTo(0xffff0000);
64   }
65 
whenNotSetOnActivityInManifest_activityGetsThemeFromApplicationInManifest()66   @Test public void whenNotSetOnActivityInManifest_activityGetsThemeFromApplicationInManifest() throws Exception {
67     TestActivity activity = buildActivity(TestActivity.class).create().get();
68     Button theButton = (Button) activity.findViewById(R.id.button);
69     ColorDrawable background = (ColorDrawable) theButton.getBackground();
70     assertThat(background.getColor()).isEqualTo(0xff00ff00);
71   }
72 
shouldResolveReferencesThatStartWithAQuestionMark()73   @Test public void shouldResolveReferencesThatStartWithAQuestionMark() throws Exception {
74     TestActivity activity = buildActivity(TestActivityWithAnotherTheme.class).create().get();
75     Button theButton = (Button) activity.findViewById(R.id.button);
76     assertThat(theButton.getMinWidth()).isEqualTo(8);
77     assertThat(theButton.getMinHeight()).isEqualTo(8);
78   }
79 
shouldLookUpStylesFromStyleResId()80   @Test public void shouldLookUpStylesFromStyleResId() throws Exception {
81     TestActivity activity = buildActivity(TestActivityWithAnotherTheme.class).create().get();
82     TypedArray a = activity.obtainStyledAttributes(null, R.styleable.CustomView, 0, R.style.MyCustomView);
83     boolean enabled = a.getBoolean(R.styleable.CustomView_aspectRatioEnabled, false);
84     assertThat(enabled).isTrue();
85   }
86 
shouldApplyStylesFromResourceReference()87   @Test public void shouldApplyStylesFromResourceReference() throws Exception {
88     TestActivity activity = buildActivity(TestActivityWithAnotherTheme.class).create().get();
89     TypedArray a = activity.obtainStyledAttributes(null, R.styleable.CustomView, 0, R.attr.animalStyle);
90     int animalStyleId = a.getResourceId(R.styleable.CustomView_animalStyle, 0);
91     assertThat(animalStyleId).isEqualTo(R.style.Gastropod);
92     assertThat(a.getFloat(R.styleable.CustomView_aspectRatio, 0.2f)).isEqualTo(1.69f);
93   }
94 
shouldApplyStylesFromAttributeReference()95   @Test public void shouldApplyStylesFromAttributeReference() throws Exception {
96     TestActivity activity = buildActivity(TestActivityWithAThirdTheme.class).create().get();
97     TypedArray a = activity.obtainStyledAttributes(null, R.styleable.CustomView, 0, R.attr.animalStyle);
98     int animalStyleId = a.getResourceId(R.styleable.CustomView_animalStyle, 0);
99     assertThat(animalStyleId).isEqualTo(R.style.Gastropod);
100     assertThat(a.getFloat(R.styleable.CustomView_aspectRatio, 0.2f)).isEqualTo(1.69f);
101   }
102 
obtainStyledAttributes_findsAttributeValueDefinedInDependencyLibrary()103   @Test public void obtainStyledAttributes_findsAttributeValueDefinedInDependencyLibrary() throws Exception {
104     TestActivity activity = buildActivity(TestActivityWithAThirdTheme.class).create().get();
105 
106     TypedArray a  = activity.getTheme().obtainStyledAttributes(new int[]{org.robolectric.R.attr.attrFromLib1});
107     assertThat(a.getString(0)).isEqualTo("value from theme");
108   }
109 
shouldGetValuesFromAttributeReference()110   @Test public void shouldGetValuesFromAttributeReference() throws Exception {
111     TestActivity activity = buildActivity(TestActivityWithAThirdTheme.class).create().get();
112 
113     TypedValue value1 = new TypedValue();
114     TypedValue value2 = new TypedValue();
115     boolean resolved1 = activity.getTheme().resolveAttribute(R.attr.someLayoutOne, value1, true);
116     boolean resolved2 = activity.getTheme().resolveAttribute(R.attr.someLayoutTwo, value2, true);
117 
118     assertThat(resolved1).isTrue();
119     assertThat(resolved2).isTrue();
120     assertThat(value1.resourceId).isEqualTo(R.layout.activity_main);
121     assertThat(value2.resourceId).isEqualTo(R.layout.activity_main);
122     assertThat(value1.coerceToString()).isEqualTo(value2.coerceToString());
123   }
124 
withResolveRefsFalse_shouldResolveValue()125   @Test public void withResolveRefsFalse_shouldResolveValue() throws Exception {
126     TestActivity activity = buildActivity(TestActivityWithAnotherTheme.class).create().get();
127 
128     TypedValue value = new TypedValue();
129     boolean resolved = activity.getTheme().resolveAttribute(R.attr.logoWidth, value, false);
130 
131     assertThat(resolved).isTrue();
132     assertThat(value.type).isEqualTo(TypedValue.TYPE_REFERENCE);
133     assertThat(value.data).isEqualTo(R.dimen.test_dp_dimen);
134   }
135 
withResolveRefsFalse_shouldNotResolveResource()136   @Test public void withResolveRefsFalse_shouldNotResolveResource() throws Exception {
137     TestActivity activity = buildActivity(TestActivityWithAnotherTheme.class).create().get();
138 
139     TypedValue value = new TypedValue();
140     boolean resolved = activity.getTheme().resolveAttribute(R.attr.logoHeight, value, false);
141 
142     assertThat(resolved).isTrue();
143     assertThat(value.type).isEqualTo(TypedValue.TYPE_REFERENCE);
144     assertThat(value.data).isEqualTo(R.dimen.test_dp_dimen);
145   }
146 
withResolveRefsTrue_shouldResolveResource()147   @Test public void withResolveRefsTrue_shouldResolveResource() throws Exception {
148     TestActivity activity = buildActivity(TestActivityWithAnotherTheme.class).create().get();
149 
150     TypedValue value = new TypedValue();
151     boolean resolved = activity.getTheme().resolveAttribute(R.attr.logoHeight, value, true);
152 
153     assertThat(resolved).isTrue();
154     assertThat(value.type).isEqualTo(TypedValue.TYPE_DIMENSION);
155     assertThat(value.resourceId).isEqualTo(R.dimen.test_dp_dimen);
156     assertThat(value.coerceToString()).isEqualTo("8.0dip");
157   }
158 
failToResolveCircularReference()159   @Test public void failToResolveCircularReference() throws Exception {
160     TestActivity activity = buildActivity(TestActivityWithAnotherTheme.class).create().get();
161 
162     TypedValue value = new TypedValue();
163     boolean resolved = activity.getTheme().resolveAttribute(R.attr.isSugary, value, false);
164 
165     assertThat(resolved).isFalse();
166   }
167 
canResolveAttrReferenceToDifferentPackage()168   @Test public void canResolveAttrReferenceToDifferentPackage() throws Exception {
169     TestActivity activity = buildActivity(TestActivityWithAnotherTheme.class).create().get();
170 
171     TypedValue value = new TypedValue();
172     boolean resolved = activity.getTheme().resolveAttribute(R.attr.styleReference, value, false);
173 
174     assertThat(resolved).isTrue();
175     assertThat(value.type).isEqualTo(TypedValue.TYPE_REFERENCE);
176     assertThat(value.data).isEqualTo(R.style.Widget_AnotherTheme_Button);
177   }
178 
forStylesWithImplicitParents_shouldInheritValuesNotDefinedInChild()179   @Test public void forStylesWithImplicitParents_shouldInheritValuesNotDefinedInChild() throws Exception {
180     Resources.Theme theme = resources.newTheme();
181     theme.applyStyle(R.style.Theme_Robolectric_ImplicitChild, true);
182     assertThat(theme.obtainStyledAttributes(new int[] {R.attr.string1}).getString(0))
183         .isEqualTo("string 1 from Theme.Robolectric");
184     assertThat(theme.obtainStyledAttributes(new int[] {R.attr.string3}).getString(0))
185         .isEqualTo("string 3 from Theme.Robolectric.ImplicitChild");
186   }
187 
whenAThemeHasExplicitlyEmptyParentAttr_shouldHaveNoParent()188   @Test public void whenAThemeHasExplicitlyEmptyParentAttr_shouldHaveNoParent() throws Exception {
189     Resources.Theme theme = resources.newTheme();
190     theme.applyStyle(R.style.Theme_Robolectric_EmptyParent, true);
191     assertThat(theme.obtainStyledAttributes(new int[] {R.attr.string1}).hasValue(0)).isFalse();
192   }
193 
shouldApplyParentStylesFromAttrs()194   @Test public void shouldApplyParentStylesFromAttrs() throws Exception {
195     Resources.Theme theme = resources.newTheme();
196     theme.applyStyle(R.style.Theme_AnotherTheme, true);
197     assertThat(theme.obtainStyledAttributes(new int[] {R.attr.string1}).getString(0))
198         .isEqualTo("string 1 from Theme.AnotherTheme");
199     assertThat(theme.obtainStyledAttributes(new int[] {R.attr.string3}).getString(0))
200         .isEqualTo("string 3 from Theme.Robolectric");
201   }
202 
203   @Test
setTo_shouldCopyAllAttributesToEmptyTheme()204   public void setTo_shouldCopyAllAttributesToEmptyTheme() throws Exception {
205     Resources.Theme theme1 = resources.newTheme();
206     theme1.applyStyle(R.style.Theme_Robolectric, false);
207     assertThat(theme1.obtainStyledAttributes(new int[]{R.attr.string1}).getString(0))
208         .isEqualTo("string 1 from Theme.Robolectric");
209 
210     Resources.Theme theme2 = resources.newTheme();
211     theme2.setTo(theme1);
212 
213     assertThat(theme2.obtainStyledAttributes(new int[]{R.attr.string1}).getString(0))
214         .isEqualTo("string 1 from Theme.Robolectric");
215   }
216 
217   @Test
setTo_whenDestThemeIsModified_sourceThemeShouldNotMutate()218   public void setTo_whenDestThemeIsModified_sourceThemeShouldNotMutate() throws Exception {
219     Resources.Theme sourceTheme = resources.newTheme();
220     sourceTheme.applyStyle(R.style.Theme_Robolectric, false);
221     assertThat(sourceTheme.obtainStyledAttributes(new int[]{R.attr.string1}).getString(0))
222         .isEqualTo("string 1 from Theme.Robolectric");
223 
224     Resources.Theme destTheme = resources.newTheme();
225     destTheme.setTo(sourceTheme);
226     destTheme.applyStyle(R.style.Theme_AnotherTheme, true);
227 
228     assertThat(sourceTheme.obtainStyledAttributes(new int[]{R.attr.string1}).getString(0))
229         .isEqualTo("string 1 from Theme.Robolectric");
230   }
231 
232   @Test
setTo_whenSourceThemeIsModified_destThemeShouldNotMutate()233   public void setTo_whenSourceThemeIsModified_destThemeShouldNotMutate() throws Exception {
234     Resources.Theme sourceTheme = resources.newTheme();
235     sourceTheme.applyStyle(R.style.Theme_Robolectric, false);
236     assertThat(sourceTheme.obtainStyledAttributes(new int[]{R.attr.string1}).getString(0))
237         .isEqualTo("string 1 from Theme.Robolectric");
238 
239     Resources.Theme destTheme = resources.newTheme();
240     destTheme.setTo(sourceTheme);
241     sourceTheme.applyStyle(R.style.Theme_AnotherTheme, true);
242 
243     assertThat(destTheme.obtainStyledAttributes(new int[]{R.attr.string1}).getString(0))
244         .isEqualTo("string 1 from Theme.Robolectric");
245   }
246 
247   @Test
applyStyle_withForceFalse_shouldApplyButNotOverwriteExistingAttributeValues()248   public void applyStyle_withForceFalse_shouldApplyButNotOverwriteExistingAttributeValues() throws Exception {
249     Resources.Theme theme = resources.newTheme();
250     theme.applyStyle(R.style.Theme_Robolectric, false);
251     assertThat(theme.obtainStyledAttributes(new int[]{R.attr.string1}).getString(0))
252         .isEqualTo("string 1 from Theme.Robolectric");
253 
254     theme.applyStyle(R.style.Theme_AnotherTheme, false);
255     assertThat(theme.obtainStyledAttributes(new int[]{R.attr.string1}).getString(0))
256         .isEqualTo("string 1 from Theme.Robolectric");
257     assertThat(theme.obtainStyledAttributes(new int[]{R.attr.string2}).getString(0))
258         .isEqualTo("string 2 from Theme.AnotherTheme");
259   }
260 
261   @Test
applyStyle_withForceTrue_shouldApplyAndOverwriteExistingAttributeValues()262   public void applyStyle_withForceTrue_shouldApplyAndOverwriteExistingAttributeValues() throws Exception {
263     Resources.Theme theme = resources.newTheme();
264     theme.applyStyle(R.style.Theme_Robolectric, false);
265     assertThat(theme.obtainStyledAttributes(new int[]{R.attr.string1}).getString(0))
266         .isEqualTo("string 1 from Theme.Robolectric");
267 
268     theme.applyStyle(R.style.Theme_AnotherTheme, true);
269     assertThat(theme.obtainStyledAttributes(new int[]{R.attr.string1}).getString(0))
270         .isEqualTo("string 1 from Theme.AnotherTheme");
271 
272     // force apply the original theme; values should be overwritten
273     theme.applyStyle(R.style.Theme_Robolectric, true);
274     assertThat(theme.obtainStyledAttributes(new int[]{R.attr.string1}).getString(0))
275         .isEqualTo("string 1 from Theme.Robolectric");
276   }
277 
278   @Test
whenStyleSpecifiesAttr_obtainStyledAttribute_findsCorrectValue()279   public void whenStyleSpecifiesAttr_obtainStyledAttribute_findsCorrectValue() throws Exception {
280     Resources.Theme theme = resources.newTheme();
281     theme.applyStyle(R.style.Theme_Robolectric, false);
282     theme.applyStyle(R.style.Theme_ThemeContainingStyleReferences, true);
283 
284     assertThat(theme.obtainStyledAttributes(
285         Robolectric.buildAttributeSet().setStyleAttribute("?attr/styleReference").build(), new int[]{R.attr.string2}, 0, 0).getString(0))
286         .isEqualTo("string 2 from StyleReferredToByParentAttrReference");
287 
288     assertThat(theme.obtainStyledAttributes(
289         Robolectric.buildAttributeSet().setStyleAttribute("?styleReference").build(), new int[]{R.attr.string2}, 0, 0).getString(0))
290         .isEqualTo("string 2 from StyleReferredToByParentAttrReference");
291   }
292 
293   @Test
whenStyleSpecifiesAttrWithoutExplicitType_obtainStyledAttribute_findsCorrectValue()294   public void whenStyleSpecifiesAttrWithoutExplicitType_obtainStyledAttribute_findsCorrectValue() throws Exception {
295     Resources.Theme theme = resources.newTheme();
296     theme.applyStyle(R.style.Theme_Robolectric, false);
297     theme.applyStyle(R.style.Theme_ThemeContainingStyleReferences, true);
298 
299     assertThat(theme.obtainStyledAttributes(
300         Robolectric.buildAttributeSet().setStyleAttribute("?attr/styleReferenceWithoutExplicitType").build(), new int[]{R.attr.string2}, 0, 0).getString(0))
301         .isEqualTo("string 2 from StyleReferredToByParentAttrReference");
302 
303     assertThat(theme.obtainStyledAttributes(
304         Robolectric.buildAttributeSet().setStyleAttribute("?styleReferenceWithoutExplicitType").build(), new int[]{R.attr.string2}, 0, 0).getString(0))
305         .isEqualTo("string 2 from StyleReferredToByParentAttrReference");
306   }
307 
308   @Test
whenAttrSetAttrSpecifiesAttr_obtainStyledAttribute_returnsItsValue()309   public void whenAttrSetAttrSpecifiesAttr_obtainStyledAttribute_returnsItsValue() throws Exception {
310     Resources.Theme theme = resources.newTheme();
311     theme.applyStyle(R.style.Theme_Robolectric, false);
312     theme.applyStyle(R.style.Theme_ThemeContainingStyleReferences, true);
313 
314     assertThat(theme.obtainStyledAttributes(
315         Robolectric.buildAttributeSet().addAttribute(R.attr.string2, "?attr/string1").build(), new int[]{R.attr.string2}, 0, 0).getString(0))
316         .isEqualTo("string 1 from Theme.Robolectric");
317   }
318 
319   @Test
whenAttrSetAttrSpecifiesUnknownAttr_obtainStyledAttribute_usesNull()320   public void whenAttrSetAttrSpecifiesUnknownAttr_obtainStyledAttribute_usesNull() throws Exception {
321     Resources.Theme theme = resources.newTheme();
322     theme.applyStyle(R.style.Theme_Robolectric, false);
323     theme.applyStyle(R.style.Theme_ThemeContainingStyleReferences, true);
324 
325     assertThat(theme.obtainStyledAttributes(
326         Robolectric.buildAttributeSet().addAttribute(R.attr.string2, "?attr/noSuchAttr").build(),
327         new int[]{R.attr.string2}, 0, 0).getString(0))
328         .isNull();
329 
330     // todo: assert that a strict warning was displayed
331   }
332 
333   @Test
forStrict_whenAttrSetAttrSpecifiesUnknownAttr_obtainStyledAttribute_throwsException()334   public void forStrict_whenAttrSetAttrSpecifiesUnknownAttr_obtainStyledAttribute_throwsException() throws Exception {
335     shadowOf(resources.getAssets()).strictErrors = true;
336 
337     Resources.Theme theme = resources.newTheme();
338     theme.applyStyle(R.style.Theme_Robolectric, false);
339     theme.applyStyle(R.style.Theme_ThemeContainingStyleReferences, true);
340 
341     try {
342       theme.obtainStyledAttributes(
343           Robolectric.buildAttributeSet().addAttribute(R.attr.string2, "?attr/noSuchAttr").build(),
344           new int[]{R.attr.string2}, 0, 0);
345       fail();
346     } catch (Exception e) {
347       assertThat(e.getMessage()).contains("no such attr ?org.robolectric:attr/noSuchAttr");
348       assertThat(e.getMessage()).contains("Theme_ThemeContainingStyleReferences");
349       assertThat(e.getMessage()).contains("Theme_Robolectric");
350       assertThat(e.getMessage()).contains("while resolving value for org.robolectric:attr/string2");
351     }
352   }
353 
354   @Test
shouldFindInheritedAndroidAttributeInTheme()355   public void shouldFindInheritedAndroidAttributeInTheme() throws Exception {
356     RuntimeEnvironment.application.setTheme(R.style.Theme_AnotherTheme);
357     Resources.Theme theme1 = RuntimeEnvironment.application.getTheme();
358 
359 //    Resources.Theme theme1 = resources.newTheme();
360 //    theme1.setTo(RuntimeEnvironment.application.getTheme());
361 //    theme1.applyStyle(R.style.Theme_AnotherTheme, false);
362 
363     TypedArray typedArray = theme1.obtainStyledAttributes(
364         new int[]{R.attr.typeface, android.R.attr.buttonStyle});
365     assertThat(typedArray.hasValue(0)).isTrue(); // animalStyle
366     assertThat(typedArray.hasValue(1)).isTrue(); // layout_height
367   }
368 
369   public static class TestActivity extends Activity {
onCreate(Bundle savedInstanceState)370     @Override protected void onCreate(Bundle savedInstanceState) {
371       super.onCreate(savedInstanceState);
372       setContentView(R.layout.styles_button_layout);
373     }
374   }
375 
376   @Test
themesShouldBeApplyableAcrossResources()377   public void themesShouldBeApplyableAcrossResources() throws Exception {
378     Resources.Theme themeFromSystem = Resources.getSystem().newTheme();
379     themeFromSystem.applyStyle(android.R.style.Theme_Light, true);
380 
381     Resources.Theme themeFromApp = RuntimeEnvironment.application.getResources().newTheme();
382     themeFromApp.applyStyle(android.R.style.Theme, true);
383 
384     // themeFromSystem is Theme_Light, which has a white background...
385     assertThat(shadowOf(themeFromSystem).obtainStyledAttributes(new int[]{android.R.attr.colorBackground}).getColor(0, 123))
386         .isEqualTo(Color.WHITE);
387 
388     // themeFromApp is Theme, which has a black background...
389     assertThat(shadowOf(themeFromApp).obtainStyledAttributes(new int[]{android.R.attr.colorBackground}).getColor(0, 123))
390         .isEqualTo(Color.BLACK);
391 
392     themeFromApp.setTo(themeFromSystem);
393 
394     // themeFromApp now has style values from themeFromSystem, so now it has a black background...
395     assertThat(shadowOf(themeFromApp).obtainStyledAttributes(new int[]{android.R.attr.colorBackground}).getColor(0, 123))
396         .isEqualTo(Color.WHITE);
397   }
398 
399   @Test
styleResolutionShouldIgnoreThemes()400   public void styleResolutionShouldIgnoreThemes() throws Exception {
401     Resources.Theme themeFromSystem = resources.newTheme();
402     themeFromSystem.applyStyle(android.R.style.Theme_DeviceDefault, true);
403     themeFromSystem.applyStyle(R.style.ThemeWithSelfReferencingTextAttr, true);
404     assertThat(themeFromSystem.obtainStyledAttributes(new int[]{android.R.attr.textAppearance})
405         .getResourceId(0, 0)).isEqualTo(0);
406   }
407 
408   @Test
dimenRef()409   public void dimenRef() throws Exception {
410     AttributeSet attributeSet = Robolectric.buildAttributeSet()
411         .addAttribute(android.R.attr.layout_height, "@dimen/test_px_dimen")
412         .build();
413     TypedArray typedArray = resources.newTheme().obtainStyledAttributes(
414         attributeSet, new int[]{android.R.attr.layout_height}, 0, 0);
415     assertThat(typedArray.getDimensionPixelSize(0, -1)).isEqualTo(15);
416   }
417 
418   @Test
dimenRefRef()419   public void dimenRefRef() throws Exception {
420     AttributeSet attributeSet = Robolectric.buildAttributeSet()
421         .addAttribute(android.R.attr.layout_height, "@dimen/ref_to_px_dimen")
422         .build();
423     TypedArray typedArray = resources.newTheme().obtainStyledAttributes(
424         attributeSet, new int[]{android.R.attr.layout_height}, 0, 0);
425     assertThat(typedArray.getDimensionPixelSize(0, -1)).isEqualTo(15);
426   }
427 
428   public static class TestActivityWithAnotherTheme extends TestActivity {
429   }
430 
431   public static class TestActivityWithAThirdTheme extends TestActivity {
432   }
433 
shouldApplyFromStyleAttribute()434   @Test public void shouldApplyFromStyleAttribute() throws Exception {
435     TestWithStyleAttrActivity activity = buildActivity(TestWithStyleAttrActivity.class).create().get();
436     View button = activity.findViewById(R.id.button);
437     assertThat(button.getLayoutParams().width).isEqualTo(42); // comes via style attr
438   }
439 
440   public static class TestWithStyleAttrActivity extends Activity {
onCreate(Bundle savedInstanceState)441     @Override protected void onCreate(Bundle savedInstanceState) {
442       super.onCreate(savedInstanceState);
443       setContentView(R.layout.styles_button_with_style_layout);
444     }
445   }
446 }
447