| package org.robolectric.shadows; |
| |
| import android.app.Activity; |
| import android.content.res.ColorStateList; |
| import android.content.res.Configuration; |
| import android.content.res.Resources; |
| import android.content.res.TypedArray; |
| import android.content.res.XmlResourceParser; |
| import android.graphics.Bitmap; |
| import android.graphics.BitmapFactory; |
| import android.graphics.Color; |
| import android.graphics.drawable.AnimationDrawable; |
| import android.graphics.drawable.BitmapDrawable; |
| import android.graphics.drawable.ColorDrawable; |
| import android.graphics.drawable.Drawable; |
| import android.graphics.drawable.NinePatchDrawable; |
| import android.os.Build; |
| import android.os.Build.VERSION_CODES; |
| import android.util.AttributeSet; |
| import android.util.DisplayMetrics; |
| import android.util.TypedValue; |
| import android.util.Xml; |
| import android.view.Display; |
| import org.assertj.core.data.Offset; |
| import org.junit.Before; |
| import org.junit.Ignore; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.robolectric.R; |
| import org.robolectric.Robolectric; |
| import org.robolectric.RuntimeEnvironment; |
| import org.robolectric.Shadows; |
| import org.robolectric.TestRunners; |
| import org.robolectric.android.XmlResourceParserImpl; |
| import org.robolectric.annotation.Config; |
| import org.robolectric.shadow.api.Shadow; |
| import org.robolectric.util.TestUtil; |
| import org.xmlpull.v1.XmlPullParser; |
| |
| import java.io.File; |
| import java.io.InputStream; |
| |
| import static android.os.Build.VERSION_CODES.KITKAT; |
| import static android.os.Build.VERSION_CODES.LOLLIPOP; |
| import static android.os.Build.VERSION_CODES.N_MR1; |
| import static org.assertj.core.api.Assertions.assertThat; |
| import static org.junit.Assert.fail; |
| import static org.robolectric.Shadows.shadowOf; |
| |
| @RunWith(TestRunners.MultiApiSelfTest.class) |
| public class ShadowResourcesTest { |
| private Resources resources; |
| |
| @Before |
| public void setup() throws Exception { |
| resources = RuntimeEnvironment.application.getResources(); |
| } |
| |
| @Test |
| public void getString() throws Exception { |
| assertThat(resources.getString(R.string.hello)).isEqualTo("Hello"); |
| assertThat(resources.getString(R.string.say_it_with_item)).isEqualTo("flowers"); |
| } |
| |
| @Test |
| public void getString_withReference() throws Exception { |
| assertThat(resources.getString(R.string.greeting)).isEqualTo("Howdy"); |
| } |
| |
| @Test |
| public void getString_withInterpolation() throws Exception { |
| assertThat(resources.getString(R.string.interpolate, "value")).isEqualTo("Here is a value!"); |
| } |
| |
| @Test |
| public void getString_withHtml() throws Exception { |
| assertThat(resources.getString(R.string.some_html, "value")).isEqualTo("Hello, world"); |
| } |
| |
| @Test |
| public void getString_withSurroundingQuotes() throws Exception { |
| assertThat(resources.getString(R.string.surrounding_quotes, "value")).isEqualTo("This'll work"); |
| } |
| |
| @Test |
| public void getStringWithEscapedApostrophes() throws Exception { |
| assertThat(resources.getString(R.string.escaped_apostrophe)).isEqualTo("This'll also work"); |
| } |
| |
| @Test |
| public void getStringWithEscapedQuotes() throws Exception { |
| assertThat(resources.getString(R.string.escaped_quotes)).isEqualTo("Click \"OK\""); |
| } |
| |
| @Test |
| public void getStringShouldStripNewLines() { |
| assertThat(resources.getString(R.string.leading_and_trailing_new_lines)).isEqualTo("Some text"); |
| } |
| |
| @Test |
| public void preserveEscapedNewlineAndTab() { |
| assertThat(resources.getString(R.string.new_lines_and_tabs, 4)).isEqualTo("4\tmph\nfaster"); |
| } |
| |
| @Test |
| public void getStringShouldConvertCodePoints() { |
| assertThat(resources.getString(R.string.non_breaking_space)).isEqualTo("Closing soon:\u00A05pm"); |
| assertThat(resources.getString(R.string.space)).isEqualTo("Closing soon: 5pm"); |
| } |
| |
| @Test |
| public void getText_withHtml() throws Exception { |
| assertThat(resources.getText(R.string.some_html, "value")).isEqualTo("Hello, world"); |
| } |
| |
| @Test |
| public void getText_withLayoutId() throws Exception { |
| assertThat(resources.getText(R.layout.different_screen_sizes, "value")).endsWith(File.separator + "src" + File.separator + "test" + File.separator + "resources" + File.separator + "res" + File.separator + "layout" + File.separator + "different_screen_sizes.xml"); |
| } |
| |
| @Test |
| public void getStringArray() throws Exception { |
| assertThat(resources.getStringArray(R.array.items)).isEqualTo(new String[]{"foo", "bar"}); |
| assertThat(resources.getStringArray(R.array.greetings)).isEqualTo(new String[]{"hola", "Hello"}); |
| } |
| |
| @Test |
| public void withIdReferenceEntry_obtainTypedArray() { |
| TypedArray typedArray = resources.obtainTypedArray(R.array.typed_array_with_resource_id); |
| assertThat(typedArray.length()).isEqualTo(2); |
| |
| assertThat(typedArray.getResourceId(0, 0)).isEqualTo(R.id.id_declared_in_item_tag); |
| assertThat(typedArray.getResourceId(1, 0)).isEqualTo(R.id.id_declared_in_layout); |
| } |
| |
| @Test |
| public void obtainTypedArray() throws Exception { |
| final Display display = Shadow.newInstanceOf(Display.class); |
| final ShadowDisplay shadowDisplay = shadowOf(display); |
| // Standard xxhdpi screen |
| shadowDisplay.setDensityDpi(480); |
| final DisplayMetrics displayMetrics = new DisplayMetrics(); |
| display.getMetrics(displayMetrics); |
| |
| final TypedArray valuesTypedArray = resources.obtainTypedArray(R.array.typed_array_values); |
| assertThat(valuesTypedArray.getString(0)).isEqualTo("abcdefg"); |
| assertThat(valuesTypedArray.getInt(1, 0)).isEqualTo(3875); |
| assertThat(valuesTypedArray.getInteger(1, 0)).isEqualTo(3875); |
| assertThat(valuesTypedArray.getFloat(2, 0.0f)).isEqualTo(2.0f); |
| assertThat(valuesTypedArray.getColor(3, Color.BLACK)).isEqualTo(Color.MAGENTA); |
| assertThat(valuesTypedArray.getColor(4, Color.BLACK)).isEqualTo(Color.parseColor("#00ffff")); |
| assertThat(valuesTypedArray.getDimension(5, 0.0f)).isEqualTo(8.0f); |
| assertThat(valuesTypedArray.getDimension(6, 0.0f)).isEqualTo(12.0f); |
| assertThat(valuesTypedArray.getDimension(7, 0.0f)).isEqualTo(6.0f); |
| assertThat(valuesTypedArray.getDimension(8, 0.0f)).isEqualTo(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 3.0f, displayMetrics)); |
| assertThat(valuesTypedArray.getDimension(9, 0.0f)).isEqualTo(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_IN, 4.0f, displayMetrics)); |
| assertThat(valuesTypedArray.getDimension(10, 0.0f)).isEqualTo(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 36.0f, displayMetrics)); |
| assertThat(valuesTypedArray.getDimension(11, 0.0f)).isEqualTo(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PT, 18.0f, displayMetrics)); |
| |
| final TypedArray refsTypedArray = resources.obtainTypedArray(R.array.typed_array_references); |
| assertThat(refsTypedArray.getString(0)).isEqualTo("apple"); |
| assertThat(refsTypedArray.getString(1)).isEqualTo("banana"); |
| assertThat(refsTypedArray.getInt(2, 0)).isEqualTo(5); |
| assertThat(refsTypedArray.getBoolean(3, false)).isTrue(); |
| |
| if (RuntimeEnvironment.getApiLevel() >= LOLLIPOP) { |
| assertThat(refsTypedArray.getType(4)).isEqualTo(TypedValue.TYPE_NULL); |
| } |
| |
| assertThat(shadowOf(refsTypedArray.getDrawable(5)).getCreatedFromResId()).isEqualTo(R.drawable.an_image); |
| assertThat(refsTypedArray.getColor(6, Color.BLACK)).isEqualTo(Color.parseColor("#ff5c00")); |
| |
| if (RuntimeEnvironment.getApiLevel() >= LOLLIPOP) { |
| assertThat(refsTypedArray.getThemeAttributeId(7, -1)).isEqualTo(R.attr.animalStyle); |
| } |
| |
| assertThat(refsTypedArray.getResourceId(8, 0)).isEqualTo(R.array.typed_array_values); |
| assertThat(refsTypedArray.getTextArray(8)) |
| .containsExactly("abcdefg", "3875", "2.0", "#ffff00ff", "#00ffff", "8px", |
| "12dp", "6dip", "3mm", "4in", "36sp", "18pt"); |
| |
| assertThat(refsTypedArray.getResourceId(9, 0)).isEqualTo(R.style.Theme_Robolectric); |
| } |
| |
| @Test @Config(sdk = N_MR1) |
| public void getInt() throws Exception { |
| assertThat(resources.getInteger(R.integer.meaning_of_life)).isEqualTo(42); |
| assertThat(resources.getInteger(R.integer.test_integer1)).isEqualTo(2000); |
| assertThat(resources.getInteger(R.integer.test_integer2)).isEqualTo(9); |
| assertThat(resources.getInteger(R.integer.test_large_hex)).isEqualTo(-65536); |
| assertThat(resources.getInteger(R.integer.test_value_with_zero)).isEqualTo(7210); |
| assertThat(resources.getInteger(R.integer.meaning_of_life_as_item)).isEqualTo(42); |
| } |
| |
| @Test |
| public void getInt_withReference() throws Exception { |
| assertThat(resources.getInteger(R.integer.reference_to_meaning_of_life)).isEqualTo(42); |
| } |
| |
| @Test |
| public void getIntArray() throws Exception { |
| assertThat(resources.getIntArray(R.array.empty_int_array)).isEqualTo(new int[]{}); |
| assertThat(resources.getIntArray(R.array.zero_to_four_int_array)).isEqualTo(new int[]{0, 1, 2, 3, 4}); |
| assertThat(resources.getIntArray(R.array.with_references_int_array)).isEqualTo(new int[]{0, 2000, 1}); |
| assertThat(resources.getIntArray(R.array.referenced_colors_int_array)).isEqualTo(new int[]{0x1, 0xFFFFFFFF, 0xFF000000, 0xFFF5F5F5, 0x802C76AD}); |
| } |
| |
| @Test |
| public void getBoolean() throws Exception { |
| assertThat(resources.getBoolean(R.bool.false_bool_value)).isEqualTo(false); |
| assertThat(resources.getBoolean(R.bool.true_as_item)).isEqualTo(true); |
| } |
| |
| @Test |
| public void getBoolean_withReference() throws Exception { |
| assertThat(resources.getBoolean(R.bool.reference_to_true)).isEqualTo(true); |
| } |
| |
| @Test |
| public void getDimension() throws Exception { |
| assertThat(resources.getDimension(R.dimen.test_dip_dimen)).isEqualTo(20f); |
| assertThat(resources.getDimension(R.dimen.test_dp_dimen)).isEqualTo(8f); |
| assertThat(resources.getDimension(R.dimen.test_in_dimen)).isEqualTo(99f * 240); |
| assertThat(resources.getDimension(R.dimen.test_mm_dimen)).isEqualTo(((float) (42f / 25.4 * 240))); |
| assertThat(resources.getDimension(R.dimen.test_px_dimen)).isEqualTo(15f); |
| assertThat(resources.getDimension(R.dimen.test_pt_dimen)).isEqualTo(12 / 0.3f); |
| assertThat(resources.getDimension(R.dimen.test_sp_dimen)).isEqualTo(5); |
| } |
| |
| @Test |
| public void getDimensionPixelSize() throws Exception { |
| assertThat(resources.getDimensionPixelSize(R.dimen.test_dip_dimen)).isEqualTo(20); |
| assertThat(resources.getDimensionPixelSize(R.dimen.test_dp_dimen)).isEqualTo(8); |
| assertThat(resources.getDimensionPixelSize(R.dimen.test_in_dimen)).isEqualTo(99 * 240); |
| assertThat(resources.getDimensionPixelSize(R.dimen.test_mm_dimen)).isEqualTo(397); |
| assertThat(resources.getDimensionPixelSize(R.dimen.test_px_dimen)).isEqualTo(15); |
| assertThat(resources.getDimensionPixelSize(R.dimen.test_pt_dimen)).isEqualTo(40); |
| assertThat(resources.getDimensionPixelSize(R.dimen.test_sp_dimen)).isEqualTo(5); |
| } |
| |
| @Test |
| public void getDimensionPixelOffset() throws Exception { |
| assertThat(resources.getDimensionPixelOffset(R.dimen.test_dip_dimen)).isEqualTo(20); |
| assertThat(resources.getDimensionPixelOffset(R.dimen.test_dp_dimen)).isEqualTo(8); |
| assertThat(resources.getDimensionPixelOffset(R.dimen.test_in_dimen)).isEqualTo(99 * 240); |
| assertThat(resources.getDimensionPixelOffset(R.dimen.test_mm_dimen)).isEqualTo(396); |
| assertThat(resources.getDimensionPixelOffset(R.dimen.test_px_dimen)).isEqualTo(15); |
| assertThat(resources.getDimensionPixelOffset(R.dimen.test_pt_dimen)).isEqualTo(40); |
| assertThat(resources.getDimensionPixelOffset(R.dimen.test_sp_dimen)).isEqualTo(5); |
| } |
| |
| @Test |
| public void getDimension_withReference() throws Exception { |
| assertThat(resources.getBoolean(R.bool.reference_to_true)).isEqualTo(true); |
| } |
| |
| @Test(expected = Resources.NotFoundException.class) |
| public void getStringArray_shouldThrowExceptionIfNotFound() throws Exception { |
| resources.getStringArray(-1); |
| } |
| |
| @Test(expected = Resources.NotFoundException.class) |
| public void getIntegerArray_shouldThrowExceptionIfNotFound() throws Exception { |
| resources.getIntArray(-1); |
| } |
| |
| // todo: PluralRules.forLocale() returns fewer rules than expected, why? seems to successfully load icudt56b/plurals.res |
| @Test |
| public void getQuantityString() throws Exception { |
| assertThat(resources.getQuantityString(R.plurals.beer, 0)).isEqualTo("Howdy"); |
| assertThat(resources.getQuantityString(R.plurals.beer, 1)).isEqualTo("One beer"); |
| assertThat(resources.getQuantityString(R.plurals.beer, 2)).isEqualTo("Two beers"); |
| assertThat(resources.getQuantityString(R.plurals.beer, 3)).isEqualTo("%d beers, yay!"); |
| } |
| |
| @Test |
| public void getFraction() throws Exception { |
| final int myself = 300; |
| final int myParent = 600; |
| assertThat(resources.getFraction(R.fraction.half, myself, myParent)).isEqualTo(150f); |
| assertThat(resources.getFraction(R.fraction.half_of_parent, myself, myParent)).isEqualTo(300f); |
| |
| assertThat(resources.getFraction(R.fraction.quarter_as_item, myself, myParent)).isEqualTo(75f); |
| assertThat(resources.getFraction(R.fraction.quarter_of_parent_as_item, myself, myParent)).isEqualTo(150f); |
| |
| assertThat(resources.getFraction(R.fraction.fifth_as_reference, myself, myParent)).isEqualTo(60f, Offset.offset(0.01f)); |
| assertThat(resources.getFraction(R.fraction.fifth_of_parent_as_reference, myself, myParent)).isEqualTo(120f, Offset.offset(0.01f)); |
| } |
| |
| @Test |
| public void testConfiguration() { |
| Configuration configuration = resources.getConfiguration(); |
| assertThat(configuration).isNotNull(); |
| assertThat(configuration.locale).isNotNull(); |
| } |
| |
| @Test |
| public void testConfigurationReturnsTheSameInstance() { |
| assertThat(resources.getConfiguration()).isSameAs(resources.getConfiguration()); |
| } |
| |
| @Test |
| public void testNewTheme() { |
| assertThat(resources.newTheme()).isNotNull(); |
| } |
| |
| @Test(expected = Resources.NotFoundException.class) |
| public void testGetDrawableNullRClass() throws Exception { |
| assertThat(resources.getDrawable(-12345)).isInstanceOf(BitmapDrawable.class); |
| } |
| |
| @Test |
| public void testGetAnimationDrawable() { |
| assertThat(resources.getDrawable(R.anim.animation_list)).isInstanceOf(AnimationDrawable.class); |
| } |
| |
| @Test |
| @Config(qualifiers = "fr") |
| public void testGetValuesResFromSpecificQualifiers() { |
| assertThat(resources.getString(R.string.hello)).isEqualTo("Bonjour"); |
| } |
| |
| @Test |
| public void testGetColorDrawable() { |
| Drawable drawable = resources.getDrawable(R.color.color_with_alpha); |
| assertThat(drawable).isInstanceOf(ColorDrawable.class); |
| assertThat(((ColorDrawable) drawable).getColor()).isEqualTo(0x802C76AD); |
| } |
| |
| @Test |
| public void getColor() { |
| assertThat(resources.getColor(R.color.color_with_alpha)).isEqualTo(0x802C76AD); |
| } |
| |
| @Test |
| public void getColor_withReference() { |
| assertThat(resources.getColor(R.color.background)).isEqualTo(0xfff5f5f5); |
| } |
| |
| @Test(expected = Resources.NotFoundException.class) |
| public void testGetColor_Missing() { |
| resources.getColor(1293405); |
| } |
| |
| @Test |
| public void testGetColorStateList() { |
| assertThat(resources.getColorStateList(R.color.color_state_list)).isInstanceOf(ColorStateList.class); |
| } |
| |
| @Test |
| public void testGetBitmapDrawable() { |
| assertThat(resources.getDrawable(R.drawable.an_image)).isInstanceOf(BitmapDrawable.class); |
| } |
| |
| @Test |
| public void testGetNinePatchDrawable() { |
| assertThat(resources.getDrawable(R.drawable.nine_patch_drawable)).isInstanceOf(NinePatchDrawable.class); |
| } |
| |
| @Test(expected = Resources.NotFoundException.class) |
| public void testGetBitmapDrawableForUnknownId() { |
| assertThat(resources.getDrawable(Integer.MAX_VALUE)).isInstanceOf(BitmapDrawable.class); |
| } |
| |
| @Test |
| public void testGetIdentifier() throws Exception { |
| |
| final String resourceType = "string"; |
| final String packageName = RuntimeEnvironment.application.getPackageName(); |
| |
| final String resourceName = "hello"; |
| final int resId1 = resources.getIdentifier(resourceName, resourceType, packageName); |
| assertThat(resId1).isEqualTo(R.string.hello); |
| |
| final String typedResourceName = resourceType + "/" + resourceName; |
| final int resId2 = resources.getIdentifier(typedResourceName, resourceType, packageName); |
| assertThat(resId2).isEqualTo(R.string.hello); |
| |
| final String fqn = packageName + ":" + typedResourceName; |
| final int resId3 = resources.getIdentifier(fqn, resourceType, packageName); |
| assertThat(resId3).isEqualTo(R.string.hello); |
| } |
| |
| @Test |
| public void getIdentifier() { |
| String string = resources.getString(R.string.hello); |
| assertThat(string).isEqualTo("Hello"); |
| |
| int id = resources.getIdentifier("hello", "string", "org.robolectric"); |
| assertThat(id).isEqualTo(R.string.hello); |
| |
| String hello = resources.getString(id); |
| assertThat(hello).isEqualTo("Hello"); |
| } |
| |
| @Test |
| public void getIdentifier_nonExistantResource() { |
| int id = resources.getIdentifier("just_alot_of_crap", "string", "org.robolectric"); |
| assertThat(id).isEqualTo(0); |
| } |
| |
| /** |
| * Public framework symbols are defined here: https://android.googlesource.com/platform/frameworks/base/+/master/core/res/res/values/public.xml |
| * Private framework symbols are defined here: https://android.googlesource.com/platform/frameworks/base/+/master/core/res/res/values/symbols.xml |
| * |
| * These generate android.R and com.android.internal.R respectively, when Framework Java code does not need to reference a framework resource |
| * it will not have an R value generated. Robolectric is then missing an identifier for this resource so we must generate a placeholder ourselves. |
| */ |
| @Test |
| @Config(sdk = Build.VERSION_CODES.LOLLIPOP) // android:color/secondary_text_material_dark was added in API 21 |
| public void shouldGenerateIdsForResourcesThatAreMissingRValues() throws Exception { |
| int identifier_missing_from_r_file = resources.getIdentifier("secondary_text_material_dark", "color", "android"); |
| |
| // We expect Robolectric to generate a placeholder identifier where one was not generated in the android R files. |
| assertThat(identifier_missing_from_r_file).isNotEqualTo(0); |
| |
| // We expect to be able to successfully android:color/secondary_text_material_dark to a ColorStateList. |
| assertThat(resources.getColorStateList(identifier_missing_from_r_file)).isNotNull(); |
| } |
| |
| @Test |
| public void testDensity() { |
| assertThat(RuntimeEnvironment.application.getResources().getDisplayMetrics().density).isEqualTo(1f); |
| |
| shadowOf(RuntimeEnvironment.application.getResources()).setDensity(1.5f); |
| assertThat(RuntimeEnvironment.application.getResources().getDisplayMetrics().density).isEqualTo(1.5f); |
| |
| Activity activity = Robolectric.setupActivity(Activity.class); |
| assertThat(activity.getResources().getDisplayMetrics().density).isEqualTo(1.5f); |
| } |
| |
| @Test |
| public void displayMetricsShouldNotHaveLotsOfZeros() throws Exception { |
| assertThat(RuntimeEnvironment.application.getResources().getDisplayMetrics().heightPixels).isEqualTo(800); |
| assertThat(RuntimeEnvironment.application.getResources().getDisplayMetrics().widthPixels).isEqualTo(480); |
| } |
| |
| @Test |
| public void getSystemShouldReturnSystemResources() throws Exception { |
| assertThat(Resources.getSystem()).isInstanceOf(Resources.class); |
| } |
| |
| @Test |
| public void multipleCallsToGetSystemShouldReturnSameInstance() throws Exception { |
| assertThat(Resources.getSystem()).isEqualTo(Resources.getSystem()); |
| } |
| |
| @Test |
| public void applicationResourcesShouldHaveBothSystemAndLocalValues() throws Exception { |
| assertThat(RuntimeEnvironment.application.getResources().getString(android.R.string.copy)).isEqualTo("Copy"); |
| assertThat(RuntimeEnvironment.application.getResources().getString(R.string.copy)).isEqualTo("Local Copy"); |
| } |
| |
| @Test |
| public void systemResourcesShouldReturnCorrectSystemId() throws Exception { |
| assertThat(Resources.getSystem().getIdentifier("copy", "string", "android")).isEqualTo(android.R.string.copy); |
| } |
| |
| @Test |
| public void systemResourcesShouldReturnZeroForLocalId() throws Exception { |
| assertThat(Resources.getSystem().getIdentifier("copy", "string", TestUtil.TEST_PACKAGE)).isEqualTo(0); |
| } |
| |
| @Test @Config(sdk = 25) // todo: unpin sdk |
| public void testGetXml() throws Exception { |
| XmlResourceParser parser = resources.getXml(R.xml.preferences); |
| assertThat(parser).isNotNull(); |
| assertThat(findRootTag(parser)).isEqualTo("PreferenceScreen"); |
| |
| parser = resources.getXml(R.layout.custom_layout); |
| assertThat(parser).isNotNull(); |
| assertThat(findRootTag(parser)).isEqualTo("org.robolectric.android.CustomView"); |
| |
| parser = resources.getXml(R.menu.test); |
| assertThat(parser).isNotNull(); |
| assertThat(findRootTag(parser)).isEqualTo("menu"); |
| |
| parser = resources.getXml(R.drawable.rainbow); |
| assertThat(parser).isNotNull(); |
| assertThat(findRootTag(parser)).isEqualTo("layer-list"); |
| |
| parser = resources.getXml(R.anim.test_anim_1); |
| assertThat(parser).isNotNull(); |
| assertThat(findRootTag(parser)).isEqualTo("set"); |
| |
| parser = resources.getXml(R.color.color_state_list); |
| assertThat(parser).isNotNull(); |
| assertThat(findRootTag(parser)).isEqualTo("selector"); |
| } |
| |
| @Test(expected = Resources.NotFoundException.class) |
| public void testGetXml_nonexistentResource() { |
| resources.getXml(0); |
| } |
| |
| @Test(expected = Resources.NotFoundException.class) |
| public void testGetXml_nonxmlfile() { |
| resources.getXml(R.drawable.an_image); |
| } |
| |
| @Test |
| public void openRawResource_shouldLoadRawResources() throws Exception { |
| InputStream resourceStream = resources.openRawResource(R.raw.raw_resource); |
| assertThat(resourceStream).isNotNull(); |
| assertThat(TestUtil.readString(resourceStream)).isEqualTo("raw txt file contents"); |
| } |
| |
| @Test |
| public void openRawResource_shouldLoadRawResourcesFromLibraries() throws Exception { |
| InputStream resourceStream = resources.openRawResource(R.raw.lib_raw_resource); |
| assertThat(resourceStream).isNotNull(); |
| assertThat(TestUtil.readString(resourceStream)).isEqualTo("from lib3"); |
| } |
| |
| @Test |
| public void openRawResource_shouldLoadRawResourcesFromSecondaryLibraries() throws Exception { |
| InputStream resourceStream = resources.openRawResource(R.raw.lib_raw_resource_from_2); |
| assertThat(resourceStream).isNotNull(); |
| assertThat(TestUtil.readString(resourceStream)).isEqualTo("I'm only defined in lib2"); |
| } |
| |
| @Test |
| public void openRawResource_shouldLoadRawResourcesFromTertiaryLibraries() throws Exception { |
| InputStream resourceStream = resources.openRawResource(R.raw.lib_raw_resource_from_3); |
| assertThat(resourceStream).isNotNull(); |
| assertThat(TestUtil.readString(resourceStream)).isEqualTo("I'm only defined in lib3"); |
| } |
| |
| @Test |
| public void openRawResource_shouldLoadDrawables() throws Exception { |
| InputStream resourceStream = resources.openRawResource(R.drawable.an_image); |
| Bitmap bitmap = BitmapFactory.decodeStream(resourceStream); |
| assertThat(bitmap.getHeight()).isEqualTo(53); |
| assertThat(bitmap.getWidth()).isEqualTo(64); |
| } |
| |
| @Test @Config(qualifiers = "hdpi") |
| public void openRawResource_shouldLoadDrawableWithQualifiers() throws Exception { |
| InputStream resourceStream = resources.openRawResource(R.drawable.an_image); |
| Bitmap bitmap = BitmapFactory.decodeStream(resourceStream); |
| assertThat(bitmap.getHeight()).isEqualTo(100); |
| assertThat(bitmap.getWidth()).isEqualTo(100); |
| } |
| |
| @Test |
| public void openRawResource_withNonFile_throwsNotFoundException() throws Exception { |
| try { |
| resources.openRawResource(R.string.hello); |
| fail("should throw"); |
| } catch (Resources.NotFoundException e) { |
| // cool |
| } |
| |
| try { |
| resources.openRawResource(R.string.hello, new TypedValue()); |
| fail("should throw"); |
| } catch (Resources.NotFoundException e) { |
| // cool |
| } |
| |
| try { |
| resources.openRawResource(-1234, new TypedValue()); |
| fail("should throw"); |
| } catch (Resources.NotFoundException e) { |
| // cool |
| } |
| } |
| |
| @Test |
| public void openRawResourceFd_returnsNull_todo_FIX() throws Exception { |
| assertThat(resources.openRawResourceFd(R.raw.raw_resource)).isNull(); |
| } |
| |
| @Test |
| public void openRawResourceFd_withNonFile_throwsNotFoundException() throws Exception { |
| try { |
| resources.openRawResourceFd(R.string.hello); |
| fail("should throw"); |
| } catch (Resources.NotFoundException e) { |
| // cool |
| } |
| |
| try { |
| resources.openRawResourceFd(-1234); |
| fail("should throw"); |
| } catch (Resources.NotFoundException e) { |
| // cool |
| } |
| } |
| |
| @Test |
| public void getXml_withNonFile_throwsNotFoundException() throws Exception { |
| try { |
| resources.getXml(R.string.hello); |
| fail("should throw"); |
| } catch (Resources.NotFoundException e) { |
| // cool |
| } |
| |
| try { |
| resources.getXml(-1234); |
| fail("should throw"); |
| } catch (Resources.NotFoundException e) { |
| // cool |
| } |
| } |
| |
| @Test |
| public void setScaledDensityShouldSetScaledDensityInDisplayMetrics() { |
| final DisplayMetrics displayMetrics = resources.getDisplayMetrics(); |
| |
| assertThat(displayMetrics.scaledDensity).isEqualTo(1f); |
| shadowOf(resources).setScaledDensity(2.5f); |
| assertThat(displayMetrics.scaledDensity).isEqualTo(2.5f); |
| } |
| |
| @Test |
| public void themeResolveAttribute_shouldSupportDereferenceResource() { |
| TypedValue out = new TypedValue(); |
| |
| Resources.Theme theme = resources.newTheme(); |
| theme.applyStyle(R.style.MyBlackTheme, false); |
| |
| theme.resolveAttribute(android.R.attr.windowBackground, out, true); |
| assertThat(out.type).isNotEqualTo(TypedValue.TYPE_REFERENCE); |
| assertThat(out.type).isBetween(TypedValue.TYPE_FIRST_COLOR_INT, TypedValue.TYPE_LAST_COLOR_INT); |
| |
| TypedValue expected = new TypedValue(); |
| ShadowAssetManager shadow = ShadowAssetManager.legacyShadowOf(resources.getAssets()); |
| shadow.getResourceValue(android.R.color.black, TypedValue.DENSITY_DEFAULT, expected, false); |
| assertThat(out.type).isEqualTo(expected.type); |
| assertThat(out.data).isEqualTo(expected.data); |
| } |
| |
| @Test |
| public void themeResolveAttribute_shouldSupportNotDereferencingResource() { |
| TypedValue out = new TypedValue(); |
| |
| Resources.Theme theme = resources.newTheme(); |
| theme.applyStyle(R.style.MyBlackTheme, false); |
| |
| theme.resolveAttribute(android.R.attr.windowBackground, out, false); |
| assertThat(out.type).isEqualTo(TypedValue.TYPE_REFERENCE); |
| assertThat(out.data).isEqualTo(android.R.color.black); |
| } |
| |
| @Test |
| public void obtainAttributes_shouldUseReferencedIdFromAttributeSet() throws Exception { |
| // android:id/mask was introduced in API 21, but it's still possible for apps built against API 21 to refer to it |
| // in older runtimes because referenced resource ids are compiled (by aapt) into the binary XML format. |
| AttributeSet attributeSet = Robolectric.buildAttributeSet() |
| .addAttribute(android.R.attr.id, "@android:id/mask").build(); |
| TypedArray typedArray = resources.obtainAttributes(attributeSet, new int[]{android.R.attr.id}); |
| assertThat(typedArray.getResourceId(0, -9)).isEqualTo(android.R.id.mask); |
| } |
| |
| @Test |
| public void obtainStyledAttributesShouldDereferenceValues() { |
| Resources.Theme theme = resources.newTheme(); |
| theme.applyStyle(R.style.MyBlackTheme, false); |
| TypedArray arr = theme.obtainStyledAttributes(new int[]{android.R.attr.windowBackground}); |
| TypedValue value = new TypedValue(); |
| arr.getValue(0, value); |
| arr.recycle(); |
| |
| assertThat(value.type).isGreaterThanOrEqualTo(TypedValue.TYPE_FIRST_COLOR_INT).isLessThanOrEqualTo(TypedValue.TYPE_LAST_INT); |
| } |
| |
| @Test |
| public void obtainStyledAttributes_shouldCheckXmlFirst_fromAttributeSetBuilder() throws Exception { |
| |
| // This simulates a ResourceProvider built from a 21+ SDK as viewportHeight / viewportWidth were introduced in API 21 |
| // but the public ID values they are assigned clash with private com.android.internal.R values on older SDKs. This |
| // test ensures that even on older SDKs, on calls to obtainStyledAttributes() Robolectric will first check for matching |
| // resource ID values in the AttributeSet before checking the theme. |
| |
| AttributeSet attributes = Robolectric.buildAttributeSet() |
| .addAttribute(android.R.attr.viewportWidth, "12.0") |
| .addAttribute(android.R.attr.viewportHeight, "24.0") |
| .build(); |
| |
| TypedArray typedArray = RuntimeEnvironment.application.getTheme().obtainStyledAttributes(attributes, new int[] { |
| android.R.attr.viewportWidth, |
| android.R.attr.viewportHeight |
| }, 0, 0); |
| assertThat(typedArray.getFloat(0, 0)).isEqualTo(12.0f); |
| assertThat(typedArray.getFloat(1, 0)).isEqualTo(24.0f); |
| typedArray.recycle(); |
| } |
| |
| @Test |
| public void obtainStyledAttributes_shouldCheckXmlFirst_fromXmlLoadedFromResources() throws Exception { |
| |
| // This simulates a ResourceProvider built from a 21+ SDK as viewportHeight / viewportWidth were introduced in API 21 |
| // but the public ID values they are assigned clash with private com.android.internal.R values on older SDKs. This |
| // test ensures that even on older SDKs, on calls to obtainStyledAttributes() Robolectric will first check for matching |
| // resource ID values in the AttributeSet before checking the theme. |
| |
| XmlResourceParser xml = RuntimeEnvironment.application.getResources().getXml(R.drawable.vector); |
| xml.next(); |
| xml.next(); |
| AttributeSet attributeSet = Xml.asAttributeSet(xml); |
| |
| TypedArray typedArray = RuntimeEnvironment.application.getTheme().obtainStyledAttributes(attributeSet, new int[] { |
| android.R.attr.viewportWidth, |
| android.R.attr.viewportHeight |
| }, 0, 0); |
| assertThat(typedArray.getFloat(0, 0)).isEqualTo(12.0f); |
| assertThat(typedArray.getFloat(1, 0)).isEqualTo(24.0f); |
| typedArray.recycle(); |
| } |
| |
| @Test |
| public void obtainStyledAttributesShouldCheckXmlFirst_andFollowReferences() throws Exception { |
| |
| // This simulates a ResourceProvider built from a 21+ SDK as viewportHeight / viewportWidth were introduced in API 21 |
| // but the public ID values they are assigned clash with private com.android.internal.R values on older SDKs. This |
| // test ensures that even on older SDKs, on calls to obtainStyledAttributes() Robolectric will first check for matching |
| // resource ID values in the AttributeSet before checking the theme. |
| |
| AttributeSet attributes = Robolectric.buildAttributeSet() |
| .addAttribute(android.R.attr.viewportWidth, "@integer/test_integer1") |
| .addAttribute(android.R.attr.viewportHeight, "@integer/test_integer2") |
| .build(); |
| |
| TypedArray typedArray = RuntimeEnvironment.application.getTheme().obtainStyledAttributes(attributes, new int[] { |
| android.R.attr.viewportWidth, |
| android.R.attr.viewportHeight |
| }, 0, 0); |
| assertThat(typedArray.getFloat(0, 0)).isEqualTo(2000); |
| assertThat(typedArray.getFloat(1, 0)).isEqualTo(9); |
| typedArray.recycle(); |
| } |
| |
| @Test |
| @Config(minSdk = LOLLIPOP) |
| public void whenAttrIsDefinedInRuntimeSdk_getResourceName_findsResource() { |
| assertThat(RuntimeEnvironment.application.getResources().getResourceName(android.R.attr.viewportHeight)) |
| .isEqualTo("android:attr/viewportHeight"); |
| } |
| |
| @Test |
| @Config(sdk = KITKAT) |
| public void whenAttrIsNotDefinedInRuntimeSdk_getResourceName_doesntFindRequestedResourceButInsteadFindsInternalResourceWithSameId() { |
| // asking for an attr defined after the current SDK doesn't have a defined result; in this case it returns |
| // numberPickerStyle from com.internal.android.R |
| assertThat(RuntimeEnvironment.application.getResources().getResourceName(android.R.attr.viewportHeight)) |
| .isEqualTo("android:attr/numberPickerStyle"); |
| |
| assertThat(RuntimeEnvironment.application.getResources().getIdentifier("viewportHeight", "attr", "android")).isEqualTo(0); |
| } |
| |
| @Test |
| public void subClassInitializedOK() { |
| SubClassResources subClassResources = new SubClassResources(RuntimeEnvironment.application.getResources()); |
| assertThat(subClassResources.openRawResource(R.raw.raw_resource)).isNotNull(); |
| } |
| |
| @Test |
| public void getValueShouldClearTypedArrayBetweenCalls() throws Exception { |
| TypedValue outValue = new TypedValue(); |
| |
| resources.getValue(R.string.hello, outValue, true); |
| assertThat(outValue.type).isEqualTo(TypedValue.TYPE_STRING); |
| assertThat(outValue.string).isEqualTo(resources.getString(R.string.hello)); |
| assertThat(outValue.data).isEqualTo(TypedValue.DATA_NULL_UNDEFINED); |
| assertThat(outValue.assetCookie).isNotEqualTo(0); |
| |
| resources.getValue(R.color.blue, outValue, true); |
| assertThat(outValue.type).isEqualTo(TypedValue.TYPE_INT_COLOR_ARGB8); |
| assertThat(outValue.data).isEqualTo(ResourceHelper.getColor("#0000ff")); |
| assertThat(outValue.string).isNull(); |
| assertThat(outValue.assetCookie).isEqualTo(TypedValue.DATA_NULL_UNDEFINED); |
| |
| resources.getValue(R.integer.loneliest_number, outValue, true); |
| assertThat(outValue.type).isEqualTo(TypedValue.TYPE_INT_HEX); |
| assertThat(outValue.data).isEqualTo(1); |
| assertThat(outValue.string).isNull(); |
| assertThat(outValue.assetCookie).isEqualTo(TypedValue.DATA_NULL_UNDEFINED); |
| |
| resources.getValue(R.bool.true_bool_value, outValue, true); |
| assertThat(outValue.type).isEqualTo(TypedValue.TYPE_INT_BOOLEAN); |
| assertThat(outValue.data).isEqualTo(1); |
| assertThat(outValue.string).isNull(); |
| assertThat(outValue.assetCookie).isEqualTo(TypedValue.DATA_NULL_UNDEFINED); |
| } |
| |
| @Test |
| public void getXml() throws Exception { |
| XmlResourceParser xmlResourceParser = resources.getXml(R.xml.preferences); |
| assertThat(xmlResourceParser).isNotNull(); |
| assertThat(xmlResourceParser.next()).isEqualTo(XmlResourceParser.START_DOCUMENT); |
| assertThat(xmlResourceParser.next()).isEqualTo(XmlResourceParser.START_TAG); |
| assertThat(xmlResourceParser.getName()).isEqualTo("PreferenceScreen"); |
| } |
| |
| @Test |
| public void getXml_shouldHavePackageContextForReferenceResolution() throws Exception { |
| XmlResourceParserImpl xmlResourceParser = |
| (XmlResourceParserImpl) resources.getXml(R.xml.preferences); |
| assertThat(xmlResourceParser.qualify("?ref")).isEqualTo("?org.robolectric:attr/ref"); |
| |
| xmlResourceParser = |
| (XmlResourceParserImpl) resources.getXml(android.R.layout.list_content); |
| assertThat(xmlResourceParser.qualify("?ref")).isEqualTo("?android:attr/ref"); |
| } |
| |
| @Test |
| public void whenMissingXml_loadXmlResourceParser() throws Exception { |
| try { |
| resources.getXml(R.id.ungulate); |
| fail(); |
| } catch (Resources.NotFoundException e) { |
| assertThat(e.getMessage()).contains("org.robolectric:id/ungulate"); |
| } |
| } |
| |
| @Test @Ignore("for non-ARSC resources") |
| public void stringWithSpacesWithOldResourceLoader() throws Exception { |
| assertThat(resources.getString(R.string.string_with_spaces, "25", "USD")) |
| .isEqualTo("Up to 25 USD"); |
| } |
| |
| @Test |
| public void stringWithSpaces() throws Exception { |
| assertThat(resources.getString(R.string.string_with_spaces, "25", "USD")) |
| .isEqualTo("Up to 25 USD"); |
| } |
| |
| private static String findRootTag(XmlResourceParser parser) throws Exception { |
| int event; |
| do { |
| event = parser.next(); |
| } while (event != XmlPullParser.START_TAG); |
| return parser.getName(); |
| } |
| |
| private static class SubClassResources extends Resources { |
| public SubClassResources(Resources res) { |
| super(res.getAssets(), res.getDisplayMetrics(), res.getConfiguration()); |
| } |
| } |
| } |