aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Williams & Dimitris Couchell <github+xian+dimitris@squareup.com>2012-11-16 13:26:26 -0800
committerChristian Williams & Dimitris Couchell <github+xian+dimitris@squareup.com>2012-11-16 13:26:26 -0800
commit9e11c64f01e0d72a3f469d5866b695c778387c26 (patch)
tree55ac8eab369bbdc4c044ed094e807d7872ab1677
parent75038b993ec0db85953f392a0c129648212d9ad6 (diff)
parent809d8cbbad66c0e51847c681f0e04526929f99b8 (diff)
downloadrobolectric-shadows-9e11c64f01e0d72a3f469d5866b695c778387c26.tar.gz
Merge remote-tracking branch 'square/master' into robolectric-2-master
* square/master: (152 commits) Reverted pom to r2 since our build server can't handle r3 Implement ShadowBitmapDrawable.mutate() Attempt to be DRY about SDK. Ha. And update the manifest to API 16. Update resource loading to use API 16. 'snapshots' -> 'url' Update to a Maps dependnecy from this decade. Allow for specifying a custom nexus URL via profile. Allow system features to be toggled. Fix Fragment resume state tracking. Return drawables when setting CompoundDrawables with resourceIds Include text values in TextView dump. Implement TextUtils.htmlEncode. Implement CheckedTestView toggling etc. Call View#onAttachedToWindow, View#onDetachedFromWindow, Fragment#onAttach, and Fragment#onDetach as appropriate. Add Robolectric.dump() and Robolectric.innerText() convenience methods. Include visibility attribute in view dump. Implement TypedArray#getTextArray. Provide a way to inject a Resources object on resources-related shadows (implement UsesResources). Support enabling bluetooth Add getOnFocusChangeListener to View When popping a fragment from the back stack, restore the previoius fragment. Implement Bundle.set/get*Array. ... Conflicts: .gitignore .pairs README.md build.xml find-android.bat lib/main/junit-dep-4.8.2.jar pom.xml src/main/java/android/os/TestVibrator.java src/main/java/android/webkit/TestWebSettings.java src/main/java/com/xtremelabs/robolectric/Robolectric.java src/main/java/com/xtremelabs/robolectric/RobolectricConfig.java src/main/java/com/xtremelabs/robolectric/RobolectricTestRunner.java src/main/java/com/xtremelabs/robolectric/res/ColorResourceLoader.java src/main/java/com/xtremelabs/robolectric/res/DrawableResourceLoader.java src/main/java/com/xtremelabs/robolectric/res/IntegerResourceLoader.java src/main/java/com/xtremelabs/robolectric/res/ResourceLoader.java src/main/java/com/xtremelabs/robolectric/res/RobolectricPackageManager.java src/main/java/com/xtremelabs/robolectric/res/ViewLoader.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowActivity.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowAlertDialog.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowApplication.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowBitmapDrawable.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowBitmapFactory.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowBluetoothAdapter.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowBundle.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowCanvas.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowCheckedTextView.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowContentResolver.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowContext.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowContextWrapper.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowDialog.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowDialogFragment.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowEditText.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowFragment.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowFragmentActivity.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowFrameLayout.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowHtml.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowImageView.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowIntent.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowLinearLayout.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowListActivity.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowLocation.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowLocationManager.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowRect.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowResources.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowSQLiteCloseable.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowSensorManager.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowSettings.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowTextUtils.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowTextView.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowTypedArray.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowView.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowViewAnimator.java src/main/java/com/xtremelabs/robolectric/shadows/ShadowViewGroup.java src/main/java/com/xtremelabs/robolectric/tester/android/util/TestAttributeSet.java src/main/java/com/xtremelabs/robolectric/tester/android/view/TestMenuItem.java src/main/java/com/xtremelabs/robolectric/tester/org/apache/http/FakeHttpLayer.java src/test/java/android/webkit/TestWebSettingsTest.java src/test/java/com/xtremelabs/robolectric/R.java src/test/java/com/xtremelabs/robolectric/RobolectricConfigTest.java src/test/java/com/xtremelabs/robolectric/res/DrawableResourceLoaderTest.java src/test/java/com/xtremelabs/robolectric/res/IntegerResourceLoaderTest.java src/test/java/com/xtremelabs/robolectric/res/MenuResourceLoaderTest.java src/test/java/com/xtremelabs/robolectric/res/RawResourceLoaderTest.java src/test/java/com/xtremelabs/robolectric/res/ResourceLoaderTest.java src/test/java/com/xtremelabs/robolectric/res/TestAttributeSetTest.java src/test/java/com/xtremelabs/robolectric/res/ViewLoaderTest.java src/test/java/com/xtremelabs/robolectric/shadows/ActivityTest.java src/test/java/com/xtremelabs/robolectric/shadows/BitmapFactoryTest.java src/test/java/com/xtremelabs/robolectric/shadows/BluetoothAdapterTest.java src/test/java/com/xtremelabs/robolectric/shadows/CheckedTextViewTest.java src/test/java/com/xtremelabs/robolectric/shadows/ContextTest.java src/test/java/com/xtremelabs/robolectric/shadows/DefaultRequestDirectorTest.java src/test/java/com/xtremelabs/robolectric/shadows/DialogFragmentTest.java src/test/java/com/xtremelabs/robolectric/shadows/DialogTest.java src/test/java/com/xtremelabs/robolectric/shadows/EditTextTest.java src/test/java/com/xtremelabs/robolectric/shadows/FragmentTest.java src/test/java/com/xtremelabs/robolectric/shadows/FrameLayoutTest.java src/test/java/com/xtremelabs/robolectric/shadows/HtmlTest.java src/test/java/com/xtremelabs/robolectric/shadows/LocationTest.java src/test/java/com/xtremelabs/robolectric/shadows/PreferenceActivityTest.java src/test/java/com/xtremelabs/robolectric/shadows/ResourcesTest.java src/test/java/com/xtremelabs/robolectric/shadows/SettingsTest.java src/test/java/com/xtremelabs/robolectric/shadows/SpannableStringBuilderTest.java src/test/java/com/xtremelabs/robolectric/shadows/TextUtilsTest.java src/test/java/com/xtremelabs/robolectric/shadows/TextViewTest.java src/test/java/com/xtremelabs/robolectric/shadows/TypedArrayTest.java src/test/java/com/xtremelabs/robolectric/shadows/ViewAnimatorTest.java src/test/java/com/xtremelabs/robolectric/shadows/ViewGroupTest.java src/test/java/com/xtremelabs/robolectric/shadows/ViewTest.java src/test/java/com/xtremelabs/robolectric/shadows/testing/OnMethodTestActivity.java src/test/java/com/xtremelabs/robolectric/tester/android/view/TestWindowTest.java src/test/java/com/xtremelabs/robolectric/util/TestUtil.java
-rw-r--r--.gitignore38
-rw-r--r--README.md2
-rw-r--r--pom.xml5
-rw-r--r--src/main/java/android/os/TestVibrator.java4
-rw-r--r--src/main/java/android/webkit/TestWebSettings.java36
-rw-r--r--src/main/java/com/xtremelabs/robolectric/Robolectric.java42
-rw-r--r--src/main/java/com/xtremelabs/robolectric/RobolectricConfig.java103
-rw-r--r--src/main/java/com/xtremelabs/robolectric/bytecode/ShadowWrangler.java1
-rw-r--r--src/main/java/com/xtremelabs/robolectric/matchers/ViewVisibilityMatcher.java63
-rw-r--r--src/main/java/com/xtremelabs/robolectric/res/AttrResourceLoader.java147
-rw-r--r--src/main/java/com/xtremelabs/robolectric/res/ColorResourceLoader.java32
-rw-r--r--src/main/java/com/xtremelabs/robolectric/res/DrawableResourceLoader.java7
-rw-r--r--src/main/java/com/xtremelabs/robolectric/res/MenuLoader.java38
-rw-r--r--src/main/java/com/xtremelabs/robolectric/res/PreferenceLoader.java147
-rw-r--r--src/main/java/com/xtremelabs/robolectric/res/ResourceLoader.java674
-rw-r--r--src/main/java/com/xtremelabs/robolectric/res/RobolectricPackageManager.java8
-rw-r--r--src/main/java/com/xtremelabs/robolectric/res/ViewLoader.java24
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowAbsoluteLayout.java28
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowActivity.java25
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowAlertDialog.java4
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowApplication.java8
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowBitmapDrawable.java17
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowBitmapFactory.java55
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowBluetoothAdapter.java9
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowCanvas.java2
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowCheckedTextView.java18
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowClipboardManager.java2
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowConfiguration.java132
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowContentProviderOperationBuilder.java7
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowContentResolver.java11
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowContext.java10
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowContextWrapper.java22
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowDateFormat.java11
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowDefaultRequestDirector.java8
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowDialog.java19
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowDialogFragment.java4
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowDisplay.java5
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowDownloadManager.java223
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowEnvironment.java6
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowFragment.java112
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowFrameLayout.java16
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowImageButton.java15
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowImageView.java12
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowLinearLayout.java7
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowListActivity.java20
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowLocalActivityManager.java36
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowLocation.java15
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowLocationManager.java124
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowMeasureSpec.java50
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowNotificationManager.java54
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowPointF.java2
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowPreferenceActivity.java20
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowRect.java224
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowRectF.java261
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowResources.java72
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowSQLiteCloseable.java10
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowSensorManager.java23
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowService.java3
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowSpannableStringBuilder.java9
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowSpannedString.java29
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowTextUtils.java18
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowTextView.java30
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowTypedArray.java30
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowView.java118
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowViewAnimator.java38
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/ShadowViewGroup.java59
-rw-r--r--src/main/java/com/xtremelabs/robolectric/shadows/UsesResources.java10
-rw-r--r--src/main/java/com/xtremelabs/robolectric/tester/android/content/TestSharedPreferences.java24
-rw-r--r--src/main/java/com/xtremelabs/robolectric/tester/android/content/pm/StubPackageManager.java16
-rw-r--r--src/main/java/com/xtremelabs/robolectric/tester/android/database/TestCursor.java4
-rw-r--r--src/main/java/com/xtremelabs/robolectric/tester/android/util/TestAttributeSet.java32
-rw-r--r--src/main/java/com/xtremelabs/robolectric/tester/android/view/TestMenuItem.java4
-rw-r--r--src/main/java/com/xtremelabs/robolectric/tester/android/view/TestWindow.java57
-rw-r--r--src/main/java/com/xtremelabs/robolectric/tester/org/apache/http/FakeHttpLayer.java24
-rw-r--r--src/main/java/com/xtremelabs/robolectric/tester/org/apache/http/HttpEntityStub.java2
-rw-r--r--src/main/java/com/xtremelabs/robolectric/util/ReflectionUtil.java20
-rw-r--r--src/main/java/com/xtremelabs/robolectric/util/Transcript.java25
-rw-r--r--src/test/java/com/xtremelabs/robolectric/R.java28
-rw-r--r--src/test/java/com/xtremelabs/robolectric/RobolectricConfigTest.java23
-rw-r--r--src/test/java/com/xtremelabs/robolectric/matchers/ViewVisibilityMatcherTest.java73
-rw-r--r--src/test/java/com/xtremelabs/robolectric/res/AttrResourceLoaderTest.java60
-rw-r--r--src/test/java/com/xtremelabs/robolectric/res/ColorResourceLoaderTest.java6
-rw-r--r--src/test/java/com/xtremelabs/robolectric/res/DrawableResourceLoaderTest.java2
-rw-r--r--src/test/java/com/xtremelabs/robolectric/res/IntegerResourceLoaderTest.java20
-rw-r--r--src/test/java/com/xtremelabs/robolectric/res/PreferenceLoaderTest.java58
-rw-r--r--src/test/java/com/xtremelabs/robolectric/res/RawResourceLoaderTest.java26
-rw-r--r--src/test/java/com/xtremelabs/robolectric/res/ResourceLoaderTest.java4
-rw-r--r--src/test/java/com/xtremelabs/robolectric/res/TestAttributeSetTest.java72
-rw-r--r--src/test/java/com/xtremelabs/robolectric/res/ViewLoaderTest.java42
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/AbsoluteLayoutTest.java20
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/ActivityTest.java43
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/AlertDialogTest.java10
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/ApplicationTest.java25
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/BitmapDrawableTest.java22
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/BitmapFactoryTest.java123
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/BluetoothAdapterTest.java27
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/CheckedTextViewTest.java8
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/ClipboardManagerTest.java6
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/ConfigurationTest.java9
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/ContextTest.java17
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/ContextWrapperTest.java6
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/DateFormatTest.java38
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/DefaultRequestDirectorTest.java20
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/DialogTest.java15
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/DisplayTest.java18
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/EditTextTest.java12
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/FrameLayoutTest.java7
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/HtmlTest.java8
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/ImageButtonTest.java20
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/ImageViewTest.java6
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/IntentTest.java2
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/ListActivityTest.java32
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/LocalActivityManagerTest.java31
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/LocationTest.java53
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/NotificationManagerTest.java22
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/PreferenceActivityTest.java87
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/ResolveInfoTest.java4
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/ResourcesTest.java93
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/SensorManagerTest.java7
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/ShadowEditTextTest.java19
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/SpannableStringBuilderTest.java16
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/SpannedStringTest.java33
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/TextUtilsTest.java7
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/TextViewTest.java27
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/TypedArrayTest.java26
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/ViewAnimatorTest.java73
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/ViewGroupTest.java29
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/ViewTest.java153
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/testing/InnerActivity.java16
-rw-r--r--src/test/java/com/xtremelabs/robolectric/shadows/testing/LocalActivityManagerContainer.java40
-rw-r--r--src/test/java/com/xtremelabs/robolectric/tester/android/view/TestWindowTest.java29
-rw-r--r--src/test/java/com/xtremelabs/robolectric/util/CustomFragment.java23
-rw-r--r--src/test/java/com/xtremelabs/robolectric/util/TestUtil.java22
-rw-r--r--src/test/resources/project.properties9
-rw-r--r--src/test/resources/res/layout-land/multi_orientation.xml23
-rw-r--r--src/test/resources/res/layout/edit_text.xml6
-rw-r--r--src/test/resources/res/layout/fragment.xml7
-rw-r--r--src/test/resources/res/layout/fragment_contents.xml18
-rw-r--r--src/test/resources/res/layout/lam_inner.xml17
-rw-r--r--src/test/resources/res/layout/lam_outer.xml17
-rw-r--r--src/test/resources/res/layout/multi_orientation.xml25
-rw-r--r--src/test/resources/res/values/attrs.xml23
-rw-r--r--src/test/resources/res/values/colors.xml2
-rw-r--r--src/test/resources/res/values/integers.xml7
-rw-r--r--src/test/resources/res/xml/preferences.xml95
145 files changed, 4502 insertions, 1087 deletions
diff --git a/.gitignore b/.gitignore
index eec04e897..c70a1f0a3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,19 +1,37 @@
+# Eclipse
+.classpath
+.project
+.settings
+eclipsebin
+
+# Ant
bin/
+gen/
+build/
out/
+lib/
+
+# Maven
+target
+pom.xml.*
+release.properties
+
+# IntelliJ
.idea
-robolectric.iml
-tmp/
-target/
-pages
-.DS_Store
-local.properties
-.project
-.classpath
-.settings
-*.iws
*.iml
+*.iws
*.ipr
+classes
+
+# Other editors
*.orig
*.swp
*~
\#*\#
+
+# Mac
+.DS_Store
+
+tmp
+local.properties
+pages
diff --git a/README.md b/README.md
index 33ebc3052..9dd4a46a8 100644
--- a/README.md
+++ b/README.md
@@ -23,5 +23,3 @@ cd maven-android-sdk-deployer/
maven install -P <ANDROID_VERSION>
```
-
-
diff --git a/pom.xml b/pom.xml
index 31833afa8..8aa20316c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -84,21 +84,20 @@
<groupId>com.google.android</groupId>
<artifactId>android</artifactId>
<version>4.1.1.4</version>
- <!-- <version>4.0.1.2</version> -->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.android.maps</groupId>
<artifactId>maps</artifactId>
- <version>10_r2</version>
+ <version>16_r2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.android</groupId>
<artifactId>support-v4</artifactId>
- <version>r6</version>
+ <version>r7</version>
</dependency>
<dependency>
diff --git a/src/main/java/android/os/TestVibrator.java b/src/main/java/android/os/TestVibrator.java
index ad3326d2a..26cedb618 100644
--- a/src/main/java/android/os/TestVibrator.java
+++ b/src/main/java/android/os/TestVibrator.java
@@ -4,23 +4,19 @@ public class TestVibrator extends Vibrator {
@Override
public void cancel() {
- // TODO Auto-generated method stub
}
@Override
public boolean hasVibrator() {
- // TODO Auto-generated method stub
return false;
}
@Override
public void vibrate(long arg0) {
- // TODO Auto-generated method stub
}
@Override
public void vibrate(long[] arg0, int arg1) {
- // TODO Auto-generated method stub
}
}
diff --git a/src/main/java/android/webkit/TestWebSettings.java b/src/main/java/android/webkit/TestWebSettings.java
index 660c53cea..0df72c6f8 100644
--- a/src/main/java/android/webkit/TestWebSettings.java
+++ b/src/main/java/android/webkit/TestWebSettings.java
@@ -26,24 +26,24 @@ public class TestWebSettings extends WebSettings {
private boolean supportMultipleWindows = false;
private boolean supportZoom = true;
- public TestWebSettings() {
- }
-
- public boolean getAllowFileAccessFromFileURLs() {
- return allowFileAccessFromFile;
- }
-
- public boolean getAllowUniversalAccessFromFileURLs() {
- return allowUniversalAccessFromFile;
- }
-
- public void setAllowFileAccessFromFileURLs(boolean allow) {
- allowFileAccessFromFile = allow;
- }
-
- public void setAllowUniversalAccessFromFileURLs(boolean allow) {
- allowUniversalAccessFromFile = allow;
- }
+ public TestWebSettings() {
+ }
+
+ public boolean getAllowFileAccessFromFileURLs() {
+ return allowFileAccessFromFile;
+ }
+
+ public boolean getAllowUniversalAccessFromFileURLs() {
+ return allowUniversalAccessFromFile;
+ }
+
+ public void setAllowFileAccessFromFileURLs(boolean allow) {
+ allowFileAccessFromFile = allow;
+ }
+
+ public void setAllowUniversalAccessFromFileURLs(boolean allow) {
+ allowUniversalAccessFromFile = allow;
+ }
@Implementation
public boolean getAllowFileAccess() {
diff --git a/src/main/java/com/xtremelabs/robolectric/Robolectric.java b/src/main/java/com/xtremelabs/robolectric/Robolectric.java
index 76338d192..b71b2940d 100644
--- a/src/main/java/com/xtremelabs/robolectric/Robolectric.java
+++ b/src/main/java/com/xtremelabs/robolectric/Robolectric.java
@@ -20,6 +20,7 @@ import android.hardware.Camera;
import android.hardware.SensorManager;
import android.location.Address;
import android.location.Geocoder;
+import android.location.Location;
import android.location.LocationManager;
import android.media.AudioManager;
import android.media.MediaPlayer;
@@ -165,6 +166,7 @@ public class Robolectric {
return Arrays.asList(
ShadowAbsListView.class,
ShadowAbsoluteLayout.class,
+ ShadowAbsoluteLayout.ShadowLayoutParams.class,
ShadowAbsSeekBar.class,
ShadowAbsSpinner.class,
ShadowAbstractCursor.class,
@@ -243,6 +245,9 @@ public class Robolectric {
ShadowDialog.class,
ShadowDialogFragment.class,
ShadowDialogPreference.class,
+ ShadowDownloadManager.class,
+ ShadowDownloadManager.ShadowRequest.class,
+ ShadowDownloadManager.ShadowQuery.class,
ShadowEditText.class,
ShadowEditTextPreference.class,
ShadowEnvironment.class,
@@ -261,6 +266,7 @@ public class Robolectric {
ShadowHandler.class,
ShadowHandlerThread.class,
ShadowHtml.class,
+ ShadowImageButton.class,
ShadowImageView.class,
ShadowInputMethodManager.class,
ShadowInputDevice.class,
@@ -284,6 +290,7 @@ public class Robolectric {
ShadowListActivity.class,
ShadowListPreference.class,
ShadowListView.class,
+ ShadowLocalActivityManager.class,
ShadowLocalBroadcastManager.class,
ShadowLocation.class,
ShadowLocationManager.class,
@@ -295,6 +302,7 @@ public class Robolectric {
ShadowMarginLayoutParams.class,
ShadowMatrix.class,
ShadowMatrixCursor.class,
+ ShadowMeasureSpec.class,
ShadowMediaPlayer.class,
ShadowMediaRecorder.class,
ShadowMediaStore.ShadowImages.ShadowMedia.class,
@@ -338,6 +346,7 @@ public class Robolectric {
ShadowRadioGroup.class,
ShadowRatingBar.class,
ShadowRect.class,
+ ShadowRectF.class,
ShadowRelativeLayout.class,
ShadowRelativeLayoutParams.class,
ShadowResolveInfo.class,
@@ -362,6 +371,7 @@ public class Robolectric {
ShadowSmsManager.class,
ShadowSpannableString.class,
ShadowSpannableStringBuilder.class,
+ ShadowSpannedString.class,
ShadowSparseArray.class,
ShadowSparseBooleanArray.class,
ShadowSparseIntArray.class,
@@ -687,6 +697,10 @@ public class Robolectric {
return (ShadowExpandableListView) shadowOf_(instance);
}
+ public static ShadowLocation shadowOf(Location instance) {
+ return (ShadowLocation) shadowOf_(instance);
+ }
+
public static ShadowFilter shadowOf(Filter instance) {
return (ShadowFilter) shadowOf_(instance);
}
@@ -1040,6 +1054,10 @@ public class Robolectric {
return (ShadowTextView) shadowOf_(instance);
}
+ public static ShadowResources.ShadowTheme shadowOf(Resources.Theme instance) {
+ return (ShadowResources.ShadowTheme) shadowOf_(instance);
+ }
+
public static ShadowToast shadowOf(Toast instance) {
return (ShadowToast) shadowOf_(instance);
}
@@ -1198,7 +1216,7 @@ public class Robolectric {
* @return the requested request.
*/
public static HttpRequest getSentHttpRequest(int index) {
- return ShadowDefaultRequestDirector.getSentHttpRequest(index);
+ return getFakeHttpLayer().getSentHttpRequestInfo(index).getHttpRequest();
}
public static HttpRequest getLatestSentHttpRequest() {
@@ -1225,7 +1243,26 @@ public class Robolectric {
* @return the requested request metadata.
*/
public static HttpRequestInfo getSentHttpRequestInfo(int index) {
- return ShadowDefaultRequestDirector.getSentHttpRequestInfo(index);
+ return getFakeHttpLayer().getSentHttpRequestInfo(index);
+ }
+
+ /**
+ * Accessor to obtain HTTP requests made during the current test in the order in which they were made.
+ *
+ * @return the requested request or null if there are none.
+ */
+ public static HttpRequest getNextSentHttpRequest() {
+ HttpRequestInfo httpRequestInfo = getFakeHttpLayer().getNextSentHttpRequestInfo();
+ return httpRequestInfo == null ? null : httpRequestInfo.getHttpRequest();
+ }
+
+ /**
+ * Accessor to obtain metadata for an HTTP request made during the current test in the order in which they were made.
+ *
+ * @return the requested request metadata or null if there are none.
+ */
+ public static HttpRequestInfo getNextSentHttpRequestInfo() {
+ return getFakeHttpLayer().getNextSentHttpRequestInfo();
}
/**
@@ -1442,5 +1479,4 @@ public class Robolectric {
return oldValue;
}
}
-
}
diff --git a/src/main/java/com/xtremelabs/robolectric/RobolectricConfig.java b/src/main/java/com/xtremelabs/robolectric/RobolectricConfig.java
index 31ab3d2c6..565642c3c 100644
--- a/src/main/java/com/xtremelabs/robolectric/RobolectricConfig.java
+++ b/src/main/java/com/xtremelabs/robolectric/RobolectricConfig.java
@@ -9,10 +9,13 @@ import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Properties;
import static android.content.pm.ApplicationInfo.*;
import static com.xtremelabs.robolectric.Robolectric.DEFAULT_SDK_VERSION;
@@ -69,11 +72,58 @@ public class RobolectricConfig {
}
public static RobolectricConfig fromBaseDirWithLibraries(File baseDir) {
- return new RobolectricConfig(baseDir);
- // todo:
-// List<File> resources = new ArrayList<File>();
-// buildResourcePath(baseDir, resources);
-// return new RobolectricConfig(new File(baseDir, "AndroidManifest.xml"), resources, new File(baseDir, "assets"));
+ List<File> resources = new ArrayList<File>();
+ buildResourcePath(baseDir, resources);
+ return new RobolectricConfig(new File(baseDir, "AndroidManifest.xml"), resources, new File(baseDir, "assets"));
+ }
+
+ private static void buildResourcePath(File baseDir, List<File> resources) {
+ resources.add(new File(baseDir, "res"));
+
+ Properties properties = getProperties(new File(baseDir, "project.properties"));
+ if (properties != null) {
+ int libRef = 1;
+ String lib;
+ while ((lib = properties.getProperty("android.library.reference." + libRef)) != null) {
+ buildResourcePath(new File(baseDir, lib), resources);
+ libRef++;
+ }
+ return;
+ } else {
+ // Try unpack folder from maven.
+ File unpack = new File(baseDir, "target/unpack/apklibs");
+ if (unpack.exists()) {
+ File[] libs = unpack.listFiles();
+ if (libs != null) {
+ for (File lib : libs) {
+ resources.add(new File(lib, "res"));
+ }
+ }
+ }
+ }
+ }
+
+ private static Properties getProperties(File propertiesFile) {
+ if (!propertiesFile.exists()) return null;
+
+ Properties properties = new Properties();
+ FileInputStream stream;
+ try {
+ stream = new FileInputStream(propertiesFile);
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+
+ try {
+ try {
+ properties.load(stream);
+ } finally {
+ stream.close();
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return properties;
}
public String getRClassName() throws Exception {
@@ -86,8 +136,10 @@ public class RobolectricConfig {
throw new FileNotFoundException(androidManifestFile.getAbsolutePath() + " not found or not a file; it should point to your project's AndroidManifest.xml");
}
- if (!getResourceDirectory().exists() || !getResourceDirectory().isDirectory()) {
- throw new FileNotFoundException(getResourceDirectory().getAbsolutePath() + " not found or not a directory; it should point to your project's res directory");
+ for (File f : getResourcePath()) {
+ if (!f.exists() || !f.isDirectory()) {
+ throw new FileNotFoundException(f.getAbsolutePath() + " not found or not a directory; it should point to a res directory");
+ }
}
}
@@ -120,7 +172,7 @@ public class RobolectricConfig {
processName = getTagAttributeText(manifestDocument, "application", "android:process");
if (processName == null) {
- processName = packageName;
+ processName = packageName;
}
parseApplicationFlags(manifestDocument);
@@ -187,14 +239,14 @@ public class RobolectricConfig {
}
private int getApplicationFlag(final Document doc, final String attribute, final int attributeValue) {
- String flagString = getTagAttributeText(doc, "application", attribute);
- return "true".equalsIgnoreCase(flagString) ? attributeValue : 0;
+ String flagString = getTagAttributeText(doc, "application", attribute);
+ return "true".equalsIgnoreCase(flagString) ? attributeValue : 0;
}
-
+
private Integer getTagAttributeIntValue(final Document doc, final String tag, final String attribute) {
return getTagAttributeIntValue(doc, tag, attribute, null);
}
-
+
private Integer getTagAttributeIntValue(final Document doc, final String tag, final String attribute, final Integer defaultValue) {
String valueString = getTagAttributeText(doc, tag, attribute);
if (valueString != null) {
@@ -212,11 +264,11 @@ public class RobolectricConfig {
parseAndroidManifest();
return packageName;
}
-
+
public int getMinSdkVersion() {
- parseAndroidManifest();
- return minSdkVersion;
- }
+ parseAndroidManifest();
+ return minSdkVersion;
+ }
public int getSdkVersion() {
parseAndroidManifest();
@@ -224,8 +276,8 @@ public class RobolectricConfig {
}
public int getApplicationFlags() {
- parseAndroidManifest();
- return applicationFlags;
+ parseAndroidManifest();
+ return applicationFlags;
}
public String getProcessName() {
@@ -262,11 +314,11 @@ public class RobolectricConfig {
}
public boolean getStrictI18n() {
- return strictI18n;
+ return strictI18n;
}
-
+
public void setStrictI18n(boolean strict) {
- strictI18n = strict;
+ strictI18n = strict;
}
public void setValuesResQualifiers( String qualifiers ){
@@ -293,7 +345,7 @@ public class RobolectricConfig {
}
return null;
}
-
+
private static Application newApplicationInstance(final String packageName, final String applicationName) {
Application application;
try {
@@ -323,7 +375,8 @@ public class RobolectricConfig {
if (getAssetsDirectory() != null ? !getAssetsDirectory().equals(that.getAssetsDirectory()) : that.getAssetsDirectory() != null) {
return false;
}
- if (getResourceDirectory() != null ? !getResourceDirectory().equals(that.getResourceDirectory()) : that.getResourceDirectory() != null) {
+
+ if (getResourcePath() != null ? !getResourcePath().equals(that.getResourcePath()) : that.getResourcePath() != null) {
return false;
}
@@ -333,11 +386,11 @@ public class RobolectricConfig {
@Override
public int hashCode() {
int result = androidManifestFile != null ? androidManifestFile.hashCode() : 0;
- result = 31 * result + (getResourceDirectory() != null ? getResourceDirectory().hashCode() : 0);
+ result = 31 * result + (getResourcePath() != null ? getResourcePath().hashCode() : 0);
result = 31 * result + (getAssetsDirectory() != null ? getAssetsDirectory().hashCode() : 0);
return result;
}
-
+
public int getRealSdkVersion() {
parseAndroidManifest();
if (sdkVersionSpecified) {
diff --git a/src/main/java/com/xtremelabs/robolectric/bytecode/ShadowWrangler.java b/src/main/java/com/xtremelabs/robolectric/bytecode/ShadowWrangler.java
index e74e27ab8..b75b957a8 100644
--- a/src/main/java/com/xtremelabs/robolectric/bytecode/ShadowWrangler.java
+++ b/src/main/java/com/xtremelabs/robolectric/bytecode/ShadowWrangler.java
@@ -8,7 +8,6 @@ import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.CtField;
import javassist.NotFoundException;
-
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.*;
diff --git a/src/main/java/com/xtremelabs/robolectric/matchers/ViewVisibilityMatcher.java b/src/main/java/com/xtremelabs/robolectric/matchers/ViewVisibilityMatcher.java
new file mode 100644
index 000000000..ef7db47f8
--- /dev/null
+++ b/src/main/java/com/xtremelabs/robolectric/matchers/ViewVisibilityMatcher.java
@@ -0,0 +1,63 @@
+package com.xtremelabs.robolectric.matchers;
+
+import android.view.View;
+import org.hamcrest.Description;
+import org.hamcrest.Factory;
+import org.hamcrest.Matcher;
+import org.junit.internal.matchers.TypeSafeMatcher;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ViewVisibilityMatcher<T extends View> extends TypeSafeMatcher<T> {
+
+ private static final Map<Integer, String> VISIBILITY_DESCRIPTIONS;
+ static {
+ VISIBILITY_DESCRIPTIONS = new HashMap<Integer, String>();
+ VISIBILITY_DESCRIPTIONS.put(View.VISIBLE, "'Visible'");
+ VISIBILITY_DESCRIPTIONS.put(View.INVISIBLE, "'Invisible'");
+ VISIBILITY_DESCRIPTIONS.put(View.GONE, "'Gone'");
+ }
+
+ private final int expectedVisibility;
+ private int actualVisibility = -1;
+
+ public ViewVisibilityMatcher(int expectedVisibility) {
+ this.expectedVisibility = expectedVisibility;
+ }
+
+ @Override
+ public boolean matchesSafely(T t) {
+ if (t == null){
+ return false;
+ }
+ actualVisibility = t.getVisibility();
+ return expectedVisibility == actualVisibility;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ if (actualVisibility >= 0){
+ description.appendText(VISIBILITY_DESCRIPTIONS.get(actualVisibility));
+ description.appendText(" to be ");
+ description.appendText(VISIBILITY_DESCRIPTIONS.get(expectedVisibility));
+ } else {
+ description.appendText("View to be non-null.");
+ }
+ }
+
+ @Factory
+ public static <T extends View> Matcher<T> isVisible() {
+ return new ViewVisibilityMatcher<T>(View.VISIBLE);
+ }
+
+ @Factory
+ public static <T extends View> Matcher<T> isInvisible() {
+ return new ViewVisibilityMatcher<T>(View.INVISIBLE);
+ }
+
+ @Factory
+ public static <T extends View> Matcher<T> isGone() {
+ return new ViewVisibilityMatcher<T>(View.GONE);
+ }
+}
diff --git a/src/main/java/com/xtremelabs/robolectric/res/AttrResourceLoader.java b/src/main/java/com/xtremelabs/robolectric/res/AttrResourceLoader.java
index 1ec1dd436..790729d4a 100644
--- a/src/main/java/com/xtremelabs/robolectric/res/AttrResourceLoader.java
+++ b/src/main/java/com/xtremelabs/robolectric/res/AttrResourceLoader.java
@@ -7,6 +7,7 @@ import org.w3c.dom.NodeList;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.File;
import java.util.HashMap;
@@ -15,59 +16,143 @@ import java.util.Map;
import java.util.Set;
public class AttrResourceLoader extends XmlLoader {
- Map<String, String> classAttrEnumToValue = new HashMap<String, String>();
- Set<String> knownClassAttrs = new HashSet<String>();
+ private static final String ANDROID_XML_NAMESPACE = "http://schemas.android.com/apk/res/android";
+ private static final String ANDROID_PREFIX = "android:";
+ Map<String, EnumDef> enums = new HashMap<String, EnumDef>();
+ Map<String, EnumRef> enumRefs = new HashMap<String, EnumRef>();
+ boolean resolved = false;
+
+ Map<String, String> classEnumToValue = new HashMap<String, String>();
+ Set<String> knownClassEnums = new HashSet<String>();
+
public AttrResourceLoader(ResourceExtractor resourceExtractor) {
super(resourceExtractor);
}
- @Override
- protected void processResourceXml(File xmlFile, Document document, boolean isSystem) throws Exception {
- XPathExpression stringsXPath = XPathFactory.newInstance().newXPath().compile("/resources/declare-styleable/attr/enum");
- NodeList stringNodes = (NodeList) stringsXPath.evaluate(document, XPathConstants.NODESET);
- for (int i = 0; i < stringNodes.getLength(); i++) {
- Node node = stringNodes.item(i);
- String viewName = node.getParentNode().getParentNode().getAttributes().getNamedItem("name").getNodeValue();
- String enumName = node.getParentNode().getAttributes().getNamedItem("name").getNodeValue();
- String name = node.getAttributes().getNamedItem("name").getNodeValue();
- String value = node.getAttributes().getNamedItem("value").getNodeValue();
-
- classAttrEnumToValue.put(key(viewName, enumName, name, isSystem), value);
- knownClassAttrs.add(key(viewName, enumName, isSystem));
+ static class EnumDef {
+ final String name;
+ final Map<String, String> values = new HashMap<String, String>();
+
+ EnumDef(String name) { this.name = name; }
+ }
+
+ static class EnumRef {
+ final String viewName;
+ final String enumName;
+
+ EnumRef(String viewName, String enumName) {
+ this.enumName = enumName;
+ this.viewName = viewName;
+ }
+ }
+
+ @Override protected void processResourceXml(File xmlFile, Document document, boolean system) throws Exception {
+
+ // Pick up inline enum definitions
+ {
+ NodeList nodeList = findNodes(document, "/resources/declare-styleable/attr/enum|/resources/declare-styleable/attr/flag");
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ Node node = nodeList.item(i);
+ String viewName = node.getParentNode().getParentNode().getAttributes().getNamedItem("name").getNodeValue();
+ String enumName = enumName(node.getParentNode().getAttributes().getNamedItem("name").getNodeValue(), system);
+ String name = node.getAttributes().getNamedItem("name").getNodeValue();
+ String value = node.getAttributes().getNamedItem("value").getNodeValue();
+
+ classEnumToValue.put(key(viewName, enumName, name), value);
+ knownClassEnums.add(key(viewName, enumName));
+ }
+ }
+
+ // Look for any global enum definitions.
+ {
+ NodeList nodeList = findNodes(document, "/resources/attr/enum|/resources/attr/flag");
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ Node node = nodeList.item(i);
+
+ String enumName = enumName(node.getParentNode().getAttributes().getNamedItem("name").getNodeValue(), system);
+ EnumDef enumDef = enums.get(enumName);
+ if (enumDef == null) {
+ enumDef = new EnumDef(enumName);
+ enums.put(enumName, enumDef);
+ }
+ enumDef.values.put(node.getAttributes().getNamedItem("name").getNodeValue(),
+ node.getAttributes().getNamedItem("value").getNodeValue());
+ }
+ }
+
+ // Note uses of system enums and top level local enums by childless attr nodes
+ {
+ NodeList nodeList = findNodes(document, "/resources/declare-styleable/attr[not(node())]");
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ Node node = nodeList.item(i);
+
+ String viewName = node.getParentNode().getAttributes().getNamedItem("name").getNodeValue();
+ String enumName = enumName(node.getAttributes().getNamedItem("name").getNodeValue(), system);
+
+ enumRefs.put(key(viewName, enumName), new EnumRef(viewName, enumName));
+ }
}
}
public String convertValueToEnum(Class<? extends View> viewClass, String namespace, String attrName, String attrValue) {
- boolean isSystem = "android".equals(namespace);
- String className = findKnownAttrClass(attrName, viewClass, isSystem);
- return classAttrEnumToValue.get(key(className, attrName, attrValue, isSystem));
+ resolveReferences();
+ if (ANDROID_XML_NAMESPACE.equals(namespace)) attrName = ANDROID_PREFIX + attrName;
+ String className = findKnownAttrClass(attrName, viewClass).getSimpleName();
+ return classEnumToValue.get(key(className, attrName, attrValue));
}
public boolean hasAttributeFor(Class<? extends View> viewClass, String namespace, String attrName) {
- boolean isSystem = "android".equals(namespace);
- return findKnownAttrClass(attrName, viewClass, isSystem) != null;
+ resolveReferences();
+ if (ANDROID_XML_NAMESPACE.equals(namespace)) attrName = ANDROID_PREFIX + attrName;
+ return findKnownAttrClass(attrName, viewClass) != null;
}
- private String findKnownAttrClass(String attrName, Class<?> clazz, boolean isSystem) {
- while (clazz != null) {
- String className = clazz.getName();
- if (isSystem) {
- className = clazz.getSimpleName();
+ private String enumName(String name, boolean system) {
+ String enumName = name;
+ enumName = system ? ANDROID_PREFIX + enumName : enumName;
+ return enumName;
+ }
+
+ private NodeList findNodes(Document document, String path) throws XPathExpressionException {
+ XPathExpression nestedEnumsXPath = XPathFactory.newInstance().newXPath().compile(path);
+ return (NodeList) nestedEnumsXPath.evaluate(document, XPathConstants.NODESET);
+ }
+
+ private void resolveReferences() {
+ if (!resolved) {
+ for (EnumRef enumRef : enumRefs.values()) {
+ noteEnumUses(enumRef.viewName, enumRef.enumName);
}
- if (knownClassAttrs.contains(key(className, attrName, isSystem))) {
- return className;
+ resolved = true;
+ }
+ }
+
+ private void noteEnumUses(String viewName, String enumName) {
+ EnumDef enumDef = enums.get(enumName);
+ if (enumDef == null) return;
+
+ for (Map.Entry<String, String> entry : enumDef.values.entrySet()) {
+ classEnumToValue.put(key(viewName, enumName, entry.getKey()), entry.getValue());
+ }
+ knownClassEnums.add(key(viewName, enumName));
+ }
+
+ private Class<?> findKnownAttrClass(String attrName, Class<?> clazz) {
+ while (clazz != null) {
+ if (knownClassEnums.contains(key(clazz.getSimpleName(), attrName))) {
+ return clazz;
}
clazz = clazz.getSuperclass();
}
return null;
}
- private String key(String viewName, String attrName, String name, boolean isSystem) {
- return key(viewName, attrName, isSystem) + "#" + name;
+ private String key(String viewName, String enumName, String name) {
+ return viewName + "#" + enumName + "#" + name;
}
- private String key(String viewName, String attrName, boolean isSystem) {
- return (isSystem ? "android:" : "") + viewName + "#" + attrName;
+ private String key(String viewName, String enunName) {
+ return viewName + "#" + enunName;
}
}
diff --git a/src/main/java/com/xtremelabs/robolectric/res/ColorResourceLoader.java b/src/main/java/com/xtremelabs/robolectric/res/ColorResourceLoader.java
index f81046daa..fd4f2eed5 100644
--- a/src/main/java/com/xtremelabs/robolectric/res/ColorResourceLoader.java
+++ b/src/main/java/com/xtremelabs/robolectric/res/ColorResourceLoader.java
@@ -9,6 +9,7 @@ import java.util.Map;
public class ColorResourceLoader extends XpathResourceXmlLoader implements ResourceValueConverter {
private ResourceReferenceResolver<Integer> colorResolver = new ResourceReferenceResolver<Integer>("color");
private static Map<String, Integer> androidColors = new HashMap<String, Integer>();
+ private static Map<Integer, Integer> androidColorsFromIds = new HashMap<Integer, Integer>();
static {
androidColors.put("black", Color.BLACK);
@@ -22,6 +23,24 @@ public class ColorResourceLoader extends XpathResourceXmlLoader implements Resou
androidColors.put("yellow", Color.YELLOW);
androidColors.put("cyan", Color.CYAN);
androidColors.put("magenta", Color.MAGENTA);
+ androidColors.put("transparent", Color.TRANSPARENT);
+
+ androidColors.put("@android:color/black", Color.BLACK);
+ androidColors.put("@android:color/darkgray", Color.DKGRAY);
+ androidColors.put("@android:color/gray", Color.GRAY);
+ androidColors.put("@android:color/lightgray", Color.LTGRAY);
+ androidColors.put("@android:color/white", Color.WHITE);
+ androidColors.put("@android:color/red", Color.RED);
+ androidColors.put("@android:color/green", Color.GREEN);
+ androidColors.put("@android:color/blue", Color.BLUE);
+ androidColors.put("@android:color/yellow", Color.YELLOW);
+ androidColors.put("@android:color/cyan", Color.CYAN);
+ androidColors.put("@android:color/magenta", Color.MAGENTA);
+ androidColors.put("@android:color/transparent", Color.TRANSPARENT);
+
+ androidColorsFromIds.put(android.R.color.black, Color.BLACK);
+ androidColorsFromIds.put(android.R.color.white, Color.WHITE);
+ androidColorsFromIds.put(android.R.color.transparent, Color.TRANSPARENT);
}
public ColorResourceLoader(ResourceExtractor resourceExtractor) {
@@ -29,13 +48,14 @@ public class ColorResourceLoader extends XpathResourceXmlLoader implements Resou
}
public int getValue(int colorId) {
- String resourceName = resourceExtractor.getResourceName(colorId);
- if (resourceName == null) {
- return -1;
+ if (androidColorsFromIds.containsKey(colorId)) {
+ return androidColorsFromIds.get(colorId);
+ } else {
+ String resourceName = resourceExtractor.getResourceName(colorId);
+ if (resourceName == null) return -1;
+ Integer resolved = colorResolver.getValue(resourceName);
+ return resolved == null ? -1 : resolved;
}
-
- Integer colorResolverValue = colorResolver.getValue(resourceName);
- return colorResolverValue == null ? -1 : colorResolverValue;
}
@Override
diff --git a/src/main/java/com/xtremelabs/robolectric/res/DrawableResourceLoader.java b/src/main/java/com/xtremelabs/robolectric/res/DrawableResourceLoader.java
index bac82e164..001f4ac25 100644
--- a/src/main/java/com/xtremelabs/robolectric/res/DrawableResourceLoader.java
+++ b/src/main/java/com/xtremelabs/robolectric/res/DrawableResourceLoader.java
@@ -38,18 +38,13 @@ public class DrawableResourceLoader extends XmlLoader {
/** document */
protected Map<String, Document> documents = new HashMap<String, Document>();
- /** resource directory */
- protected File resourceDirectory;
-
/**
* DrawableResourceLoader constructor.
*
* @param extractor Extractor
- * @param resourceDirectory Resource directory
*/
- public DrawableResourceLoader(ResourceExtractor extractor, File resourceDirectory) {
+ public DrawableResourceLoader(ResourceExtractor extractor) {
super(extractor);
- this.resourceDirectory = resourceDirectory;
}
/**
diff --git a/src/main/java/com/xtremelabs/robolectric/res/MenuLoader.java b/src/main/java/com/xtremelabs/robolectric/res/MenuLoader.java
index 8f2ba007b..821b123cf 100644
--- a/src/main/java/com/xtremelabs/robolectric/res/MenuLoader.java
+++ b/src/main/java/com/xtremelabs/robolectric/res/MenuLoader.java
@@ -1,24 +1,22 @@
package com.xtremelabs.robolectric.res;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
import android.content.Context;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
-
import com.xtremelabs.robolectric.tester.android.util.TestAttributeSet;
import com.xtremelabs.robolectric.util.I18nException;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
public class MenuLoader extends XmlLoader {
private Map<String, MenuNode> menuNodesByMenuName = new HashMap<String, MenuNode>();
@@ -94,21 +92,20 @@ public class MenuLoader extends XmlLoader {
|| nodei.getNodeName().equals("group");
}
- public void inflateMenu(Context context, String key, Menu root) {
- inflateMenu(context, key, null, root);
+ public boolean inflateMenu(Context context, String key, Menu root) {
+ return inflateMenu(context, key, null, root);
}
- public void inflateMenu(Context context, int resourceId, Menu root) {
- inflateMenu(context, resourceExtractor.getResourceName(resourceId),
+ public boolean inflateMenu(Context context, int resourceId, Menu root) {
+ return inflateMenu(context, resourceExtractor.getResourceName(resourceId),
root);
}
- private void inflateMenu(Context context, String key,
+ private boolean inflateMenu(Context context, String key,
Map<String, String> attributes, Menu root) {
MenuNode menuNode = menuNodesByMenuName.get(key);
- if (menuNode == null) {
- throw new RuntimeException("Could not find menu " + key);
- }
+ if (menuNode == null) return false;
+
try {
if (attributes != null) {
for (Map.Entry<String, String> entry : attributes.entrySet()) {
@@ -119,6 +116,7 @@ public class MenuLoader extends XmlLoader {
}
}
menuNode.inflate(context, root);
+ return true;
} catch (I18nException e) {
throw e;
} catch (Exception e) {
diff --git a/src/main/java/com/xtremelabs/robolectric/res/PreferenceLoader.java b/src/main/java/com/xtremelabs/robolectric/res/PreferenceLoader.java
index 1d80ae490..16c186aa9 100644
--- a/src/main/java/com/xtremelabs/robolectric/res/PreferenceLoader.java
+++ b/src/main/java/com/xtremelabs/robolectric/res/PreferenceLoader.java
@@ -1,5 +1,18 @@
package com.xtremelabs.robolectric.res;
+import android.content.Context;
+import android.preference.Preference;
+import android.preference.PreferenceGroup;
+import android.preference.PreferenceScreen;
+import android.util.AttributeSet;
+import com.xtremelabs.robolectric.Robolectric;
+import com.xtremelabs.robolectric.tester.android.util.TestAttributeSet;
+import com.xtremelabs.robolectric.util.I18nException;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
import java.io.File;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
@@ -7,35 +20,20 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import org.w3c.dom.Document;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import com.xtremelabs.robolectric.Robolectric;
-import com.xtremelabs.robolectric.tester.android.util.TestAttributeSet;
-import com.xtremelabs.robolectric.util.I18nException;
-
-import android.content.Context;
-import android.preference.Preference;
-import android.preference.PreferenceGroup;
-import android.preference.PreferenceScreen;
-import android.util.AttributeSet;
-
public class PreferenceLoader extends XmlLoader {
-
+
private Map<String, PreferenceNode> prefNodesByResourceName = new HashMap<String, PreferenceNode>();
- public PreferenceLoader(ResourceExtractor resourceExtractor) {
- super(resourceExtractor);
- }
+ public PreferenceLoader(ResourceExtractor resourceExtractor) {
+ super(resourceExtractor);
+ }
- @Override
- protected void processResourceXml(File xmlFile, Document document, boolean isSystem) throws Exception {
- PreferenceNode topLevelNode = new PreferenceNode("top-level", new HashMap<String, String>());
- processChildren(document.getChildNodes(), topLevelNode);
- prefNodesByResourceName.put( "xml/" + xmlFile.getName().replace(".xml", ""), topLevelNode.getChildren().get(0));
- }
+ @Override
+ protected void processResourceXml(File xmlFile, Document document, boolean isSystem) throws Exception {
+ PreferenceNode topLevelNode = new PreferenceNode("top-level", new HashMap<String, String>());
+ processChildren(document.getChildNodes(), topLevelNode);
+ prefNodesByResourceName.put( "xml/" + xmlFile.getName().replace(".xml", ""), topLevelNode.getChildren().get(0));
+ }
private void processChildren(NodeList childNodes, PreferenceNode parent) {
for (int i = 0; i < childNodes.getLength(); i++) {
@@ -43,12 +41,12 @@ public class PreferenceLoader extends XmlLoader {
processNode(node, parent);
}
}
-
+
private void processNode(Node node, PreferenceNode parent) {
String name = node.getNodeName();
NamedNodeMap attributes = node.getAttributes();
Map<String, String> attrMap = new HashMap<String, String>();
-
+
if (attributes != null) {
int length = attributes.getLength();
for (int i = 0; i < length; i++) {
@@ -56,34 +54,34 @@ public class PreferenceLoader extends XmlLoader {
attrMap.put(attr.getNodeName(), attr.getNodeValue());
}
}
-
+
if (!name.startsWith("#")) {
- PreferenceNode prefNode = new PreferenceNode(name, attrMap);
- if (parent != null) parent.addChild(prefNode);
-
- processChildren(node.getChildNodes(), prefNode);
+ PreferenceNode prefNode = new PreferenceNode(name, attrMap);
+ if (parent != null) parent.addChild(prefNode);
+
+ processChildren(node.getChildNodes(), prefNode);
}
}
-
- public PreferenceScreen inflatePreferences(Context context, int resourceId) {
- return inflatePreferences(context, resourceExtractor.getResourceName(resourceId));
- }
-
- public PreferenceScreen inflatePreferences(Context context, String key) {
+
+ public PreferenceScreen inflatePreferences(Context context, int resourceId) {
+ return inflatePreferences(context, resourceExtractor.getResourceName(resourceId));
+ }
+
+ public PreferenceScreen inflatePreferences(Context context, String key) {
try {
- PreferenceNode prefNode = prefNodesByResourceName.get(key);
- return (PreferenceScreen) prefNode.inflate(context, null);
+ PreferenceNode prefNode = prefNodesByResourceName.get(key);
+ return (PreferenceScreen) prefNode.inflate(context, null);
} catch (I18nException e) {
- throw e;
+ throw e;
} catch (Exception e) {
throw new RuntimeException("error inflating " + key, e);
}
- }
+ }
public class PreferenceNode {
private String name;
private final Map<String, String> attributes;
-
+
private List<PreferenceNode> children = new ArrayList<PreferenceNode>();
public PreferenceNode(String name, Map<String, String> attributes) {
@@ -98,47 +96,56 @@ public class PreferenceLoader extends XmlLoader {
public void addChild(PreferenceNode prefNode) {
children.add(prefNode);
}
-
+
public Preference inflate(Context context, Preference parent) throws Exception {
- Preference preference = create(context, (PreferenceGroup) parent);
+ Preference preference = create(context, (PreferenceGroup) parent);
for (PreferenceNode child : children) {
child.inflate(context, preference);
}
-
- return preference;
+
+ return preference;
}
-
+
private Preference create(Context context, PreferenceGroup parent) throws Exception {
- Preference preference = constructPreference(context, parent);
+ Preference preference = constructPreference(context, parent);
if (parent != null && parent != preference) {
parent.addPreference(preference);
- }
+ }
return preference;
}
-
+
private Preference constructPreference(Context context, PreferenceGroup parent) throws Exception {
- Class<? extends Preference> clazz = pickViewClass();
-
- if (clazz.equals(PreferenceScreen.class)) {
- return Robolectric.newInstanceOf(PreferenceScreen.class);
- }
-
- try {
- TestAttributeSet attributeSet = new TestAttributeSet(attributes);
- if (strictI18n) {
- attributeSet.validateStrictI18n();
- }
+ Class<? extends Preference> clazz = pickViewClass();
+
+ TestAttributeSet attributeSet = new TestAttributeSet(attributes);
+ if (strictI18n) {
+ attributeSet.validateStrictI18n();
+ }
+
+ /**
+ * This block is required because the PreferenceScreen(Context, AttributeSet) constructor is somehow hidden
+ * from reflection. The only way to set keys/titles/summaries on PreferenceScreens is to set them manually.
+ */
+ if (clazz.equals(PreferenceScreen.class)) {
+ PreferenceScreen screen = Robolectric.newInstanceOf(PreferenceScreen.class);
+ screen.setKey(attributes.get("android:key"));
+ screen.setTitle(attributes.get("android:title"));
+ screen.setSummary(attributes.get("android:summary"));
+ return screen;
+ }
+
+ try {
return ((Constructor<? extends Preference>) clazz.getConstructor(Context.class, AttributeSet.class)).newInstance(context, attributeSet);
} catch (NoSuchMethodException e) {
- try {
- return ((Constructor<? extends Preference>) clazz.getConstructor(Context.class)).newInstance(context);
- } catch (NoSuchMethodException e1) {
- return ((Constructor<? extends Preference>) clazz.getConstructor(Context.class, String.class)).newInstance(context, "");
- }
+ try {
+ return ((Constructor<? extends Preference>) clazz.getConstructor(Context.class)).newInstance(context);
+ } catch (NoSuchMethodException e1) {
+ return ((Constructor<? extends Preference>) clazz.getConstructor(Context.class, String.class)).newInstance(context, "");
+ }
}
}
-
+
private Class<? extends Preference> pickViewClass() {
Class<? extends Preference> clazz = loadClass(name);
if (clazz == null) {
@@ -149,7 +156,7 @@ public class PreferenceLoader extends XmlLoader {
}
return clazz;
}
-
+
private Class<? extends Preference> loadClass(String className) {
try {
//noinspection unchecked
@@ -157,6 +164,6 @@ public class PreferenceLoader extends XmlLoader {
} catch (ClassNotFoundException e) {
return null;
}
- }
+ }
}
}
diff --git a/src/main/java/com/xtremelabs/robolectric/res/ResourceLoader.java b/src/main/java/com/xtremelabs/robolectric/res/ResourceLoader.java
index 93c98dc93..d30bf2995 100644
--- a/src/main/java/com/xtremelabs/robolectric/res/ResourceLoader.java
+++ b/src/main/java/com/xtremelabs/robolectric/res/ResourceLoader.java
@@ -27,6 +27,8 @@ import java.util.List;
import java.util.Properties;
import java.util.Set;
+import java.util.*;
+
import static com.xtremelabs.robolectric.Robolectric.shadowOf;
public class ResourceLoader {
@@ -49,36 +51,41 @@ public class ResourceLoader {
}
};
- private File resourceDir;
- private File assetsDir;
- private int sdkVersion;
- private Class rClass;
+ private List<File> resourcePath;
+ private File assetsDir;
+ private int sdkVersion;
+ private Class rClass;
- private final ResourceExtractor resourceExtractor;
- private ViewLoader viewLoader;
- private MenuLoader menuLoader;
+ private final ResourceExtractor resourceExtractor;
+ private ViewLoader viewLoader;
+ private MenuLoader menuLoader;
private XmlFileLoader xmlFileLoader;
- private PreferenceLoader preferenceLoader;
- private final StringResourceLoader stringResourceLoader;
- private final PluralResourceLoader pluralResourceLoader;
- private final StringArrayResourceLoader stringArrayResourceLoader;
- private final AttrResourceLoader attrResourceLoader;
- private final ColorResourceLoader colorResourceLoader;
- private final DrawableResourceLoader drawableResourceLoader;
- private final RawResourceLoader rawResourceLoader;
- private final DimenResourceLoader dimenResourceLoader;
- private final IntegerResourceLoader integerResourceLoader;
- private final BoolResourceLoader boolResourceLoader;
- private boolean isInitialized = false;
- private boolean strictI18n = false;
-
- private final Set<Integer> ninePatchDrawableIds = new HashSet<Integer>();
+ private PreferenceLoader preferenceLoader;
+ private final StringResourceLoader stringResourceLoader;
+ private final DimenResourceLoader dimenResourceLoader;
+ private final IntegerResourceLoader integerResourceLoader;
+ private final PluralResourceLoader pluralResourceLoader;
+ private final StringArrayResourceLoader stringArrayResourceLoader;
+ private final AttrResourceLoader attrResourceLoader;
+ private final ColorResourceLoader colorResourceLoader;
+ private final DrawableResourceLoader drawableResourceLoader;
+ private final BoolResourceLoader boolResourceLoader;
+ private final List<RawResourceLoader> rawResourceLoaders = new ArrayList<RawResourceLoader>();
+ private boolean isInitialized = false;
+ private boolean strictI18n = false;
+ private boolean isSystem = false;
+ private final Set<Integer> ninePatchDrawableIds = new HashSet<Integer>();
+
+ @Deprecated
+ public ResourceLoader(int sdkVersion, Class rClass, File resourceDir, File assetsDir) throws Exception {
+ this(sdkVersion, rClass, safeFileList(resourceDir), assetsDir);
+ }
- public ResourceLoader( int sdkVersion, Class rClass, List<File> resourcePath, File assetsDir) throws Exception {
- this(sdkVersion, rClass, resourcePath.get(0), assetsDir); // todo
+ private static List<File> safeFileList(File resourceDir) {
+ return resourceDir == null ? Collections.<File> emptyList() : Collections.singletonList(resourceDir);
}
- public ResourceLoader( int sdkVersion, Class rClass, File resourceDir, File assetsDir) throws Exception {
+ public ResourceLoader(int sdkVersion, Class rClass, List<File> resourcePath, File assetsDir) throws Exception {
this.sdkVersion = sdkVersion;
this.assetsDir = assetsDir;
this.rClass = rClass;
@@ -87,190 +94,226 @@ public class ResourceLoader {
resourceExtractor.addLocalRClass( rClass );
resourceExtractor.addSystemRClass( R.class );
- stringResourceLoader = new StringResourceLoader( resourceExtractor );
- pluralResourceLoader = new PluralResourceLoader( resourceExtractor, stringResourceLoader );
- stringArrayResourceLoader = new StringArrayResourceLoader( resourceExtractor, stringResourceLoader );
- colorResourceLoader = new ColorResourceLoader( resourceExtractor );
- attrResourceLoader = new AttrResourceLoader( resourceExtractor );
- drawableResourceLoader = new DrawableResourceLoader( resourceExtractor, resourceDir );
- rawResourceLoader = new RawResourceLoader( resourceExtractor, resourceDir );
- dimenResourceLoader = new DimenResourceLoader( resourceExtractor );
- integerResourceLoader = new IntegerResourceLoader( resourceExtractor );
- boolResourceLoader = new BoolResourceLoader( resourceExtractor );
-
- this.resourceDir = resourceDir;
- }
+ stringResourceLoader = new StringResourceLoader(resourceExtractor);
+ dimenResourceLoader = new DimenResourceLoader( resourceExtractor );
+ integerResourceLoader = new IntegerResourceLoader(resourceExtractor);
+ pluralResourceLoader = new PluralResourceLoader(resourceExtractor, stringResourceLoader);
+ stringArrayResourceLoader = new StringArrayResourceLoader(resourceExtractor, stringResourceLoader);
+ colorResourceLoader = new ColorResourceLoader(resourceExtractor);
+ attrResourceLoader = new AttrResourceLoader(resourceExtractor);
+ drawableResourceLoader = new DrawableResourceLoader(resourceExtractor);
+ boolResourceLoader = new BoolResourceLoader( resourceExtractor );
+
+ this.resourcePath = Collections.unmodifiableList(resourcePath);
+ }
+
+ public ResourceLoader(ResourceLoader toCopy) throws Exception {
+ this.sdkVersion = toCopy.sdkVersion;
+ this.assetsDir = toCopy.assetsDir;
+ resourceExtractor = new ResourceExtractor();
+ resourceExtractor.addLocalRClass(toCopy.rClass);
+ resourceExtractor.addSystemRClass(R.class);
+
+ stringResourceLoader = new StringResourceLoader(resourceExtractor);
+ dimenResourceLoader = new DimenResourceLoader(resourceExtractor);
+ integerResourceLoader = new IntegerResourceLoader(resourceExtractor);
+ pluralResourceLoader = new PluralResourceLoader(resourceExtractor, stringResourceLoader);
+ stringArrayResourceLoader = new StringArrayResourceLoader(resourceExtractor, stringResourceLoader);
+ colorResourceLoader = new ColorResourceLoader(resourceExtractor);
+ attrResourceLoader = new AttrResourceLoader(resourceExtractor);
+ drawableResourceLoader = new DrawableResourceLoader(resourceExtractor);
+ boolResourceLoader = new BoolResourceLoader(resourceExtractor);
+
+ this.resourcePath = Collections.unmodifiableList(toCopy.resourcePath);
+ }
- public void setStrictI18n( boolean strict ) {
- this.strictI18n = strict;
- if ( viewLoader != null ) {
- viewLoader.setStrictI18n( strict );
- }
- if ( menuLoader != null ) {
- menuLoader.setStrictI18n( strict );
- }
- if ( preferenceLoader != null ) {
- preferenceLoader.setStrictI18n( strict );
- }
- if ( xmlFileLoader != null ) {
- xmlFileLoader.setStrictI18n( strict );
- }
- }
+ /*
+ * For tests only...
+ */
+ protected ResourceLoader(StringResourceLoader stringResourceLoader) {
+ resourceExtractor = new ResourceExtractor();
+ resourcePath = Collections.emptyList();
+ this.stringResourceLoader = stringResourceLoader;
+ this.integerResourceLoader = null;
+ pluralResourceLoader = null;
+ viewLoader = null;
+ stringArrayResourceLoader = null;
+ attrResourceLoader = null;
+ colorResourceLoader = null;
+ drawableResourceLoader = null;
+ dimenResourceLoader = null;
+ boolResourceLoader = null;
+ }
- public boolean getStrictI18n() {
- return strictI18n;
- }
+ public void setStrictI18n(boolean strict) {
+ this.strictI18n = strict;
+ if (viewLoader != null ) { viewLoader.setStrictI18n(strict); }
+ if (menuLoader != null ) { menuLoader.setStrictI18n(strict); }
+ if (preferenceLoader != null ) { preferenceLoader.setStrictI18n(strict); }
+ if (xmlFileLoader != null) { xmlFileLoader.setStrictI18n( strict ); }
+ }
+
+ public boolean getStrictI18n() { return strictI18n; }
+
+ private void init() {
+ if (isInitialized) {
+ return;
+ }
+
+ if (!resourcePath.isEmpty()) {
+ try {
+ viewLoader = new ViewLoader(resourceExtractor, attrResourceLoader);
+ menuLoader = new MenuLoader(resourceExtractor, attrResourceLoader);
+ preferenceLoader = new PreferenceLoader(resourceExtractor);
+
+ viewLoader.setStrictI18n(strictI18n);
+ menuLoader.setStrictI18n(strictI18n);
+ preferenceLoader.setStrictI18n(strictI18n);
+
+ File systemResourceDir = getSystemResourceDir(getPathToAndroidResources());
+ File systemValueResourceDir = getValueResourceDir(systemResourceDir, null, false);
+
+ loadStringResources(systemValueResourceDir, stringResourceLoader, true);
+ loadPluralsResources(systemValueResourceDir, true);
+ loadValueResources(systemValueResourceDir, stringArrayResourceLoader, colorResourceLoader, attrResourceLoader, true);
+ loadDimenResources( systemValueResourceDir, true );
+ loadIntegerResources(systemValueResourceDir, integerResourceLoader, true);
+ loadViewResources(systemResourceDir, viewLoader, true);
+
+ if (!isSystem) {
+ loadLocalResources();
+ }
+ } catch(I18nException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ isInitialized = true;
+ }
- private void init() {
- if ( isInitialized ) {
- return;
- }
-
- try {
- if ( resourceDir != null ) {
- viewLoader = new ViewLoader( resourceExtractor, attrResourceLoader );
- menuLoader = new MenuLoader( resourceExtractor, attrResourceLoader );
- preferenceLoader = new PreferenceLoader( resourceExtractor );
- xmlFileLoader = new XmlFileLoader( resourceExtractor );
-
- viewLoader.setStrictI18n( strictI18n );
- menuLoader.setStrictI18n( strictI18n );
- preferenceLoader.setStrictI18n( strictI18n );
- xmlFileLoader.setStrictI18n( strictI18n );
-
- File systemResourceDir = getSystemResourceDir( getPathToAndroidResources() );
- File localValueResourceDir = getValueResourceDir( resourceDir, null, true );
- File systemValueResourceDir = getValueResourceDir( systemResourceDir, null, false );
- File preferenceDir = getPreferenceResourceDir( resourceDir );
-
- loadStringResources( localValueResourceDir, systemValueResourceDir );
- loadPluralsResources( localValueResourceDir, systemValueResourceDir );
- loadValueResources( localValueResourceDir, systemValueResourceDir );
- loadDimenResources( localValueResourceDir, systemValueResourceDir );
- loadIntegerResource( localValueResourceDir, systemValueResourceDir );
- loadViewResources( systemResourceDir, resourceDir );
- loadMenuResources( resourceDir );
- loadDrawableResources( resourceDir );
- loadPreferenceResources( preferenceDir );
- loadXmlFileResources( preferenceDir );
- loadOtherResources(resourceDir); // todo ?
-
- listNinePatchResources(ninePatchDrawableIds, resourceDir);
- } else {
- viewLoader = null;
- menuLoader = null;
- preferenceLoader = null;
- xmlFileLoader = null;
- }
- } catch ( I18nException e ) {
- throw e;
- } catch ( Exception e ) {
- throw new RuntimeException( e );
- }
- isInitialized = true;
- }
+ private void loadLocalResources() throws Exception {
+ for (File resourceDir : resourcePath) {
+ File localValueResourceDir = getValueResourceDir(resourceDir, null, true);
+ RawResourceLoader rawResourceLoader = new RawResourceLoader(resourceExtractor, resourceDir);
+ File preferenceDir = getPreferenceResourceDir(resourceDir);
+
+ loadStringResources(localValueResourceDir, stringResourceLoader, false);
+ loadPluralsResources(localValueResourceDir, false);
+ loadValueResources(localValueResourceDir, stringArrayResourceLoader, colorResourceLoader, attrResourceLoader, false);
+ loadDimenResources(localValueResourceDir, false);
+ loadIntegerResources(localValueResourceDir, integerResourceLoader, false);
+ loadViewResources(resourceDir, viewLoader, false);
+ loadMenuResources(resourceDir, menuLoader);
+ loadDrawableResources(resourceDir);
+ loadPreferenceResources(preferenceDir);
+ loadOtherResources(resourceDir);
+
+ listNinePatchResources(ninePatchDrawableIds, resourceDir);
+
+ rawResourceLoaders.add(rawResourceLoader);
+ }
+ }
- /**
- * Reload values resources, include String, Plurals, Dimen, Prefs, Menu
- *
- * @param locale
- */
- public void reloadValuesResouces( String qualifiers ) {
-
- File systemResourceDir = getSystemResourceDir( getPathToAndroidResources() );
- File localValueResourceDir = getValueResourceDir( resourceDir, qualifiers, true );
- File systemValueResourceDir = getValueResourceDir( systemResourceDir, null, false );
- File preferenceDir = getPreferenceResourceDir( resourceDir );
-
- try {
- loadStringResources( localValueResourceDir, systemValueResourceDir );
- loadPluralsResources( localValueResourceDir, systemValueResourceDir );
- loadValueResources( localValueResourceDir, systemValueResourceDir );
- loadDimenResources( localValueResourceDir, systemValueResourceDir );
- loadIntegerResource( localValueResourceDir, systemValueResourceDir );
- loadMenuResources( resourceDir );
- loadPreferenceResources( preferenceDir );
- } catch ( Exception e ) {
- throw new RuntimeException( e );
- }
- }
-
- private File getSystemResourceDir( String pathToAndroidResources ) {
- return pathToAndroidResources != null ? new File( pathToAndroidResources ) : null;
- }
+ /**
+ * Reload values resources, include String, Plurals, Dimen, Prefs, Menu
+ *
+ * @param qualifiers
+ */
+ public void reloadValuesResouces( String qualifiers ) {
+
+ File systemResourceDir = getSystemResourceDir( getPathToAndroidResources() );
+ File systemValueResourceDir = getValueResourceDir( systemResourceDir, null, false );
+
+ try {
+ loadStringResources(systemValueResourceDir, stringResourceLoader, true);
+ loadPluralsResources(systemValueResourceDir, true);
+ loadValueResources(systemValueResourceDir, stringArrayResourceLoader, colorResourceLoader, attrResourceLoader, true);
+ loadDimenResources( systemValueResourceDir, true );
+ loadIntegerResources(systemValueResourceDir, integerResourceLoader, true);
+ loadViewResources(systemResourceDir, viewLoader, true);
+
+ if (!isSystem) {
+ loadLocalResources();
+ }
+ } catch ( Exception e ) {
+ throw new RuntimeException( e );
+ }
+ }
- private void loadStringResources( File localResourceDir, File systemValueResourceDir ) throws Exception {
- DocumentLoader stringResourceDocumentLoader = new DocumentLoader( this.stringResourceLoader );
- loadValueResourcesFromDirs( stringResourceDocumentLoader, localResourceDir, systemValueResourceDir );
- }
- private void loadPluralsResources( File localResourceDir, File systemValueResourceDir ) throws Exception {
- DocumentLoader stringResourceDocumentLoader = new DocumentLoader( this.pluralResourceLoader );
- loadValueResourcesFromDirs( stringResourceDocumentLoader, localResourceDir, systemValueResourceDir );
- }
+ private File getSystemResourceDir(String pathToAndroidResources) {
+ return pathToAndroidResources != null ? new File(pathToAndroidResources) : null;
+ }
- private void loadValueResources( File localResourceDir, File systemValueResourceDir ) throws Exception {
- DocumentLoader valueResourceLoader = new DocumentLoader( stringArrayResourceLoader, colorResourceLoader,
- attrResourceLoader );
- loadValueResourcesFromDirs( valueResourceLoader, localResourceDir, systemValueResourceDir );
- }
+ private void loadStringResources(File resourceDir, StringResourceLoader stringResourceLoader, boolean system) throws Exception {
+ DocumentLoader stringResourceDocumentLoader = new DocumentLoader(stringResourceLoader);
+ loadValueResourcesFromDirs(stringResourceDocumentLoader, resourceDir, system);
+ }
- private void loadDimenResources( File localResourceDir, File systemValueResourceDir ) throws Exception {
- DocumentLoader dimenResourceDocumentLoader = new DocumentLoader( this.dimenResourceLoader );
- loadValueResourcesFromDirs( dimenResourceDocumentLoader, localResourceDir, systemValueResourceDir );
- }
+ private void loadPluralsResources(File resourceDir, boolean system) throws Exception {
+ DocumentLoader stringResourceDocumentLoader = new DocumentLoader(this.pluralResourceLoader);
+ loadValueResourcesFromDirs(stringResourceDocumentLoader, resourceDir, system);
+ }
- private void loadIntegerResource( File localResourceDir, File systemValueResourceDir ) throws Exception {
- DocumentLoader integerResourceDocumentLoader = new DocumentLoader( this.integerResourceLoader );
- loadValueResourcesFromDirs( integerResourceDocumentLoader, localResourceDir, systemValueResourceDir );
- }
+ private void loadValueResources(File resourceDir, StringArrayResourceLoader stringArrayResourceLoader, ColorResourceLoader colorResourceLoader, AttrResourceLoader attrResourceLoader, boolean system) throws Exception {
+ DocumentLoader valueResourceLoader = new DocumentLoader(stringArrayResourceLoader, colorResourceLoader, attrResourceLoader);
+ loadValueResourcesFromDirs(valueResourceLoader, resourceDir, system);
+ }
- private void loadViewResources( File systemResourceDir, File xmlResourceDir ) throws Exception {
- DocumentLoader viewDocumentLoader = new DocumentLoader( viewLoader );
- loadLayoutResourceXmlSubDirs( viewDocumentLoader, xmlResourceDir, false );
- loadLayoutResourceXmlSubDirs( viewDocumentLoader, systemResourceDir, true );
- }
+ private void loadDimenResources( File resourceDir, boolean system) throws Exception {
+ DocumentLoader dimenResourceDocumentLoader = new DocumentLoader( this.dimenResourceLoader );
+ loadValueResourcesFromDirs(dimenResourceDocumentLoader, resourceDir, system);
+ }
- private void loadMenuResources( File xmlResourceDir ) throws Exception {
- DocumentLoader menuDocumentLoader = new DocumentLoader( menuLoader );
- loadMenuResourceXmlDirs( menuDocumentLoader, xmlResourceDir );
- }
+ private void loadIntegerResources(File resourceDir, IntegerResourceLoader integerResourceLoader, boolean system) throws Exception {
+ DocumentLoader integerResourceDocumentLoader = new DocumentLoader(integerResourceLoader);
+ loadValueResourcesFromDirs(integerResourceDocumentLoader, resourceDir, system);
+ }
- private void loadDrawableResources( File xmlResourceDir ) throws Exception {
- DocumentLoader drawableDocumentLoader = new DocumentLoader( drawableResourceLoader );
- loadDrawableResourceXmlDirs( drawableDocumentLoader, xmlResourceDir );
- }
+ private void loadViewResources(File resourceDir, ViewLoader viewLoader, boolean system) throws Exception {
+ DocumentLoader viewDocumentLoader = new DocumentLoader(viewLoader);
+ loadLayoutResourceXmlSubDirs(viewDocumentLoader, resourceDir, system);
+ }
+
+ private void loadMenuResources(File xmlResourceDir, MenuLoader menuLoader /* todo , boolean system */) throws Exception {
+ DocumentLoader menuDocumentLoader = new DocumentLoader(menuLoader);
+ loadMenuResourceXmlDirs(menuDocumentLoader, xmlResourceDir);
+ }
- private void loadPreferenceResources( File xmlResourceDir ) throws Exception {
+ private void loadDrawableResources( File xmlResourceDir ) throws Exception {
+ DocumentLoader drawableDocumentLoader = new DocumentLoader( drawableResourceLoader );
+ loadDrawableResourceXmlDirs( drawableDocumentLoader, xmlResourceDir );
+ }
+
+ private void loadPreferenceResources( File xmlResourceDir ) throws Exception {
if ( xmlResourceDir.exists() ) {
DocumentLoader preferenceDocumentLoader = new DocumentLoader( preferenceLoader );
preferenceDocumentLoader.loadResourceXmlDir( xmlResourceDir );
}
}
-
+
/**
- * All the Xml files should be loaded.
+ * All the Xml files should be loaded.
*/
private void loadXmlFileResources( File xmlResourceDir ) throws Exception {
if ( xmlResourceDir.exists() ) {
- DocumentLoader xmlFileDocumentLoader =
+ DocumentLoader xmlFileDocumentLoader =
new DocumentLoader( xmlFileLoader );
xmlFileDocumentLoader.loadResourceXmlDir( xmlResourceDir );
}
}
- // todo ?
protected void loadOtherResources(File xmlResourceDir) {
}
- private void loadLayoutResourceXmlSubDirs( DocumentLoader layoutDocumentLoader, File xmlResourceDir, boolean isSystem )
- throws Exception {
- if ( xmlResourceDir != null ) {
- layoutDocumentLoader.loadResourceXmlDirs( isSystem, xmlResourceDir.listFiles( LAYOUT_DIR_FILE_FILTER ) );
- }
- }
+ private void loadLayoutResourceXmlSubDirs(DocumentLoader layoutDocumentLoader, File xmlResourceDir, boolean isSystem) throws Exception {
+ if (xmlResourceDir != null) {
+ layoutDocumentLoader.loadResourceXmlDirs(isSystem, xmlResourceDir.listFiles(LAYOUT_DIR_FILE_FILTER));
+ }
+ }
- private void loadMenuResourceXmlDirs( DocumentLoader menuDocumentLoader, File xmlResourceDir ) throws Exception {
+ private void loadMenuResourceXmlDirs( DocumentLoader menuDocumentLoader, File xmlResourceDir ) throws Exception {
if ( xmlResourceDir != null ) {
menuDocumentLoader.loadResourceXmlDirs( xmlResourceDir.listFiles( MENU_DIR_FILE_FILTER ) );
}
@@ -282,11 +325,13 @@ public class ResourceLoader {
}
}
- private void loadValueResourcesFromDirs( DocumentLoader documentLoader, File localValueResourceDir,
- File systemValueResourceDir ) throws Exception {
- loadValueResourcesFromDir( documentLoader, localValueResourceDir );
- loadSystemResourceXmlDir( documentLoader, systemValueResourceDir );
- }
+ private void loadValueResourcesFromDirs(DocumentLoader documentLoader, File resourceDir, boolean system) throws Exception {
+ if (system) {
+ loadSystemResourceXmlDir(documentLoader, resourceDir);
+ } else {
+ loadValueResourcesFromDir(documentLoader, resourceDir);
+ }
+ }
private void loadValueResourcesFromDir( DocumentLoader documentloader, File xmlResourceDir ) throws Exception {
if ( xmlResourceDir != null ) {
@@ -332,32 +377,32 @@ public class ResourceLoader {
return null;
}
- private String getAndroidResourcePathFromLocalProperties() {
- // Hand tested
- // This is the path most often taken by IntelliJ
- File rootDir = resourceDir.getParentFile();
- String localPropertiesFileName = "local.properties";
- File localPropertiesFile = new File( rootDir, localPropertiesFileName );
- if ( !localPropertiesFile.exists() ) {
- localPropertiesFile = new File( localPropertiesFileName );
- }
- if ( localPropertiesFile.exists() ) {
- Properties localProperties = new Properties();
- try {
- localProperties.load( new FileInputStream( localPropertiesFile ) );
- PropertiesHelper.doSubstitutions( localProperties );
- String sdkPath = localProperties.getProperty( "sdk.dir" );
- if ( sdkPath != null ) {
- return getResourcePathFromSdkPath( sdkPath );
- }
- } catch ( IOException e ) {
- // fine, we'll try something else
- }
- }
- return null;
- }
+ private String getAndroidResourcePathFromLocalProperties() {
+ // Hand tested
+ // This is the path most often taken by IntelliJ
+ File rootDir = resourcePath.get(0).getParentFile();
+ String localPropertiesFileName = "local.properties";
+ File localPropertiesFile = new File(rootDir, localPropertiesFileName);
+ if (!localPropertiesFile.exists()) {
+ localPropertiesFile = new File(localPropertiesFileName);
+ }
+ if (localPropertiesFile.exists()) {
+ Properties localProperties = new Properties();
+ try {
+ localProperties.load(new FileInputStream(localPropertiesFile));
+ PropertiesHelper.doSubstitutions(localProperties);
+ String sdkPath = localProperties.getProperty("sdk.dir");
+ if (sdkPath != null) {
+ return getResourcePathFromSdkPath(sdkPath);
+ }
+ } catch (IOException e) {
+ // fine, we'll try something else
+ }
+ }
+ return null;
+ }
- private String getAndroidResourcePathFromSystemEnvironment() {
+ private String getAndroidResourcePathFromSystemEnvironment() {
// Hand tested
String resourcePath = System.getenv().get( "ANDROID_HOME" );
if ( resourcePath != null ) {
@@ -375,23 +420,23 @@ public class ResourceLoader {
return null;
}
- private String getAndroidResourcePathByExecingWhichAndroid() {
- // Hand tested
- // Should always work from the command line. Often fails in IDEs because
- // they don't pass the full PATH in the environment
- try {
- Process process = Runtime.getRuntime().exec( new String[] { "which", "android" } );
- String sdkPath = new BufferedReader( new InputStreamReader( process.getInputStream() ) ).readLine();
- if ( sdkPath != null && sdkPath.endsWith( "tools/android" ) ) {
- return getResourcePathFromSdkPath( sdkPath.substring( 0, sdkPath.indexOf( "tools/android" ) ) );
- }
- } catch ( IOException e ) {
- // fine we'll try something else
- }
- return null;
- }
+ private String getAndroidResourcePathByExecingWhichAndroid() {
+ // Hand tested
+ // Should always work from the command line. Often fails in IDEs because
+ // they don't pass the full PATH in the environment
+ try {
+ Process process = Runtime.getRuntime().exec( new String[] { "which", "android" } );
+ String sdkPath = new BufferedReader( new InputStreamReader( process.getInputStream() ) ).readLine();
+ if ( sdkPath != null && sdkPath.endsWith( "tools/android" ) ) {
+ return getResourcePathFromSdkPath( sdkPath.substring( 0, sdkPath.indexOf( "tools/android" ) ) );
+ }
+ } catch ( IOException e ) {
+ // fine we'll try something else
+ }
+ return null;
+ }
- private String getResourcePathFromSdkPath( String sdkPath ) {
+ private String getResourcePathFromSdkPath( String sdkPath ) {
File androidResourcePath = new File( sdkPath, getAndroidResourceSubPath() );
return androidResourcePath.exists() ? androidResourcePath.toString() : null;
}
@@ -400,35 +445,17 @@ public class ResourceLoader {
return "platforms/android-" + sdkVersion + "/data/res";
}
- static boolean isLayoutDirectory( String path ) {
- return path.contains( File.separator + "layout" );
- }
-
- static boolean isDrawableDirectory( String path ) {
- return path.contains( File.separator + "drawable" );
- }
+ static boolean isLayoutDirectory( String path ) {
+ return path.contains( File.separator + "layout" );
+ }
- static boolean isMenuDirectory( String path ) {
- return path.contains( File.separator + "menu" );
- }
+ static boolean isDrawableDirectory( String path ) {
+ return path.contains( File.separator + "drawable" );
+ }
- /*
- * For tests only...
- */
- protected ResourceLoader( StringResourceLoader stringResourceLoader ) {
- resourceExtractor = new ResourceExtractor();
- this.stringResourceLoader = stringResourceLoader;
- pluralResourceLoader = null;
- viewLoader = null;
- stringArrayResourceLoader = null;
- attrResourceLoader = null;
- colorResourceLoader = null;
- drawableResourceLoader = null;
- rawResourceLoader = null;
- dimenResourceLoader = null;
- integerResourceLoader = null;
- boolResourceLoader = null;
- }
+ static boolean isMenuDirectory( String path ) {
+ return path.contains( File.separator + "menu" );
+ }
public static ResourceLoader getFrom( Context context ) {
ResourceLoader resourceLoader = shadowOf( context.getApplicationContext() ).getResourceLoader();
@@ -441,42 +468,58 @@ public class ResourceLoader {
return resourceExtractor.getResourceName( viewId );
}
- public View inflateView( Context context, int resource, ViewGroup viewGroup ) {
- init();
- return viewLoader.inflateView( context, resource, viewGroup );
- }
+ public View inflateView(Context context, int resource, ViewGroup viewGroup) {
+ init();
- public int getColorValue( int id ) {
- init();
- return colorResourceLoader.getValue( id );
- }
+ View viewNode = viewLoader.inflateView(context, resource, viewGroup);
+ if (viewNode != null) return viewNode;
- public String getStringValue( int id ) {
- init();
- return stringResourceLoader.getValue( id );
- }
+ throw new RuntimeException("Could not find layout " + resourceExtractor.getResourceName(resource));
+ }
- public String getPluralStringValue( int id, int quantity ) {
- init();
- return pluralResourceLoader.getValue( id, quantity );
- }
+ public int getColorValue(int id) {
+ init();
- public float getDimenValue( int id ) {
- init();
- return dimenResourceLoader.getValue( id );
- }
+ int value = colorResourceLoader.getValue(id);
+ if (value != -1) return value;
- public int getIntegerValue( int id ) {
- init();
- return integerResourceLoader.getValue( id );
- }
-
- public boolean getBooleanValue( int id ) {
- init();
- return boolResourceLoader.getValue( id );
- }
-
- public XmlResourceParser getXml( int id ) {
+ return -1;
+ }
+
+ public String getStringValue(int id) {
+ init();
+
+ String value = stringResourceLoader.getValue(id);
+ if (value != null) return value;
+
+ return null;
+ }
+
+ public String getPluralStringValue(int id, int quantity) {
+ init();
+ return pluralResourceLoader.getValue(id, quantity);
+ }
+
+ public float getDimenValue( int id ) {
+ init();
+ return dimenResourceLoader.getValue( id );
+ }
+
+ public int getIntegerValue(int id) {
+ init();
+
+ Integer value = integerResourceLoader.getValue(id);
+ if (value != null) return value;
+
+ return 0;
+ }
+
+ public boolean getBooleanValue( int id ) {
+ init();
+ return boolResourceLoader.getValue( id );
+ }
+
+ public XmlResourceParser getXml( int id ) {
init();
return xmlFileLoader.getXml( id );
}
@@ -568,20 +611,33 @@ public class ResourceLoader {
}
}
- public InputStream getRawValue( int id ) {
- init();
- return rawResourceLoader.getValue( id );
- }
+ public InputStream getRawValue(int id) {
+ init();
- public String[] getStringArrayValue( int id ) {
- init();
- return stringArrayResourceLoader.getArrayValue( id );
- }
+ for (RawResourceLoader rawResourceLoader : rawResourceLoaders) {
+ InputStream stream = rawResourceLoader.getValue(id);
+ if (stream != null) return stream;
+ }
- public void inflateMenu( Context context, int resource, Menu root ) {
- init();
- menuLoader.inflateMenu( context, resource, root );
- }
+ return null;
+ }
+
+ public String[] getStringArrayValue(int id) {
+ init();
+
+ String[] arrayValue = stringArrayResourceLoader.getArrayValue(id);
+ if (arrayValue != null) return arrayValue;
+
+ return null;
+ }
+
+ public void inflateMenu(Context context, int resource, Menu root) {
+ init();
+
+ if (menuLoader.inflateMenu(context, resource, root)) return;
+
+ throw new RuntimeException("Could not find menu " + resourceExtractor.getResourceName(resource));
+ }
public PreferenceScreen inflatePreferences( Context context, int resourceId ) {
init();
@@ -597,20 +653,24 @@ public class ResourceLoader {
return rClass;
}
- public void setLocalRClass( Class clazz ) {
- rClass = clazz;
- }
+ public ViewLoader.ViewNode getLayoutViewNode(String layoutName) {
+ return viewLoader.viewNodesByLayoutName.get(layoutName);
+ }
- public ResourceExtractor getResourceExtractor() {
- return resourceExtractor;
- }
+ public void setSystem(boolean isSystem) {
+ this.isSystem = isSystem;
+ }
- public ViewLoader.ViewNode getLayoutViewNode( String layoutName ) {
- return viewLoader.viewNodesByLayoutName.get( layoutName );
- }
+ public void setLayoutQualifierSearchPath( String... locations ) {
+ init();
+ viewLoader.setLayoutQualifierSearchPath( locations );
+ }
- public void setLayoutQualifierSearchPath( String... locations ) {
- init();
- viewLoader.setLayoutQualifierSearchPath( locations );
- }
+ public void setLocalRClass( Class clazz ) {
+ rClass = clazz;
+ }
+
+ public ResourceExtractor getResourceExtractor() {
+ return resourceExtractor;
+ }
}
diff --git a/src/main/java/com/xtremelabs/robolectric/res/RobolectricPackageManager.java b/src/main/java/com/xtremelabs/robolectric/res/RobolectricPackageManager.java
index d58a7c5c8..5121ef030 100644
--- a/src/main/java/com/xtremelabs/robolectric/res/RobolectricPackageManager.java
+++ b/src/main/java/com/xtremelabs/robolectric/res/RobolectricPackageManager.java
@@ -1,8 +1,5 @@
package com.xtremelabs.robolectric.res;
-import java.util.*;
-import java.util.Map.Entry;
-
import android.content.ComponentName;
import android.content.ContextWrapper;
import android.content.Intent;
@@ -11,10 +8,11 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
-
import com.xtremelabs.robolectric.RobolectricConfig;
import com.xtremelabs.robolectric.tester.android.content.pm.StubPackageManager;
+import java.util.*;
+
public class RobolectricPackageManager extends StubPackageManager {
private Map<String, PackageInfo> packageList;
@@ -119,7 +117,7 @@ public class RobolectricPackageManager extends StubPackageManager {
drawableList.put( intent.getComponent(), d);
}
- @Override
+ @Override
public Intent getLaunchIntentForPackage(String packageName) {
Intent i = new Intent();
i.setComponent( new ComponentName(packageName, "") );
diff --git a/src/main/java/com/xtremelabs/robolectric/res/ViewLoader.java b/src/main/java/com/xtremelabs/robolectric/res/ViewLoader.java
index b3b847b29..4f7f3839b 100644
--- a/src/main/java/com/xtremelabs/robolectric/res/ViewLoader.java
+++ b/src/main/java/com/xtremelabs/robolectric/res/ViewLoader.java
@@ -24,6 +24,9 @@ import java.util.*;
import static com.xtremelabs.robolectric.Robolectric.shadowOf;
public class ViewLoader extends XmlLoader {
+ /**
+ * Map of "layout/foo" to the View nodes for that layout file
+ */
protected Map<String, ViewNode> viewNodesByLayoutName = new HashMap<String, ViewNode>();
private AttrResourceLoader attrResourceLoader;
private List<String> qualifierSearchPath = new ArrayList<String>();
@@ -37,11 +40,19 @@ public class ViewLoader extends XmlLoader {
protected void processResourceXml(File xmlFile, Document document, boolean isSystem) throws Exception {
ViewNode topLevelNode = new ViewNode("top-level", new HashMap<String, String>(), isSystem);
processChildren(document.getChildNodes(), topLevelNode);
- String layoutName = xmlFile.getParentFile().getName() + "/" + xmlFile.getName().replace(".xml", "");
+ String parentDir = xmlFile.getParentFile().getName();
+ String layoutName = "layout/" + xmlFile.getName().replace(".xml", "");
+ String specificLayoutName = parentDir + "/" + xmlFile.getName().replace(".xml", "");
if (isSystem) {
layoutName = "android:" + layoutName;
+ specificLayoutName = "android:" + specificLayoutName;
}
- viewNodesByLayoutName.put(layoutName, topLevelNode.getChildren().get(0));
+ // Check to see if the generic "layout/foo" is already in the map. If not, add it.
+ if (!viewNodesByLayoutName.containsKey(layoutName)) {
+ viewNodesByLayoutName.put(layoutName, topLevelNode.getChildren().get(0));
+ }
+ // Add the specific "layout-land/foo" to the map. If this happens to be "layout/foo", it's a no-op.
+ viewNodesByLayoutName.put(specificLayoutName, topLevelNode.getChildren().get(0));
}
private void processChildren(NodeList childNodes, ViewNode parent) {
@@ -68,7 +79,7 @@ public class ViewLoader extends XmlLoader {
parent.requestFocusOverride = true;
} else if (!name.startsWith("#")) {
ViewNode viewNode = new ViewNode(name, attrMap, parent.isSystem);
- if (parent != null) parent.addChild(viewNode);
+ parent.addChild(viewNode);
processChildren(node.getChildNodes(), viewNode);
}
@@ -153,7 +164,9 @@ public class ViewLoader extends XmlLoader {
child.inflate(context, view);
}
- invokeOnFinishInflate(view);
+ if (view != null) {
+ invokeOnFinishInflate(view);
+ }
return view;
}
@@ -166,8 +179,7 @@ public class ViewLoader extends XmlLoader {
private View create(Context context, ViewGroup parent) throws Exception {
if (name.equals("include")) {
String layout = attributes.get("layout");
- View view = inflateView(context, layout.substring(1), attributes, parent);
- return view;
+ return inflateView(context, layout.substring(1), attributes, parent);
} else if (name.equals("merge")) {
return parent;
} else if (name.equals("fragment")) {
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowAbsoluteLayout.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowAbsoluteLayout.java
index 9460425a5..bc1beddab 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowAbsoluteLayout.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowAbsoluteLayout.java
@@ -1,10 +1,38 @@
package com.xtremelabs.robolectric.shadows;
+import android.view.View;
+import android.view.ViewGroup;
import android.widget.AbsoluteLayout;
+import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
+import com.xtremelabs.robolectric.internal.RealObject;
@SuppressWarnings({"UnusedDeclaration"})
@Implements(AbsoluteLayout.class)
public class ShadowAbsoluteLayout extends ShadowViewGroup {
+ private AbsoluteLayout.LayoutParams layoutParams = new AbsoluteLayout.LayoutParams(0, 0, 0, 0);
+ @Implementation
+ @Override
+ public ViewGroup.LayoutParams getLayoutParams() {
+ return layoutParams;
+ }
+
+ @Implements(AbsoluteLayout.LayoutParams.class)
+ public static class ShadowLayoutParams {
+ @RealObject
+ AbsoluteLayout.LayoutParams realLayoutParams;
+
+ public void __constructor__(int width, int height, int x, int y) {
+ realLayoutParams.width = width;
+ realLayoutParams.height = height;
+ realLayoutParams.x = x;
+ realLayoutParams.y = y;
+ }
+ }
+
+ @Override
+ protected void setChildLayoutParams(View child) {
+ child.setLayoutParams(new AbsoluteLayout.LayoutParams(0, 0, 0, 0));
+ }
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowActivity.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowActivity.java
index 76333d9b9..3bbcaf328 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowActivity.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowActivity.java
@@ -278,6 +278,14 @@ public class ShadowActivity extends ShadowContextWrapper {
return parent;
}
+ /**
+ * Allow setting of Parent fragmentActivity (for unit testing purposes only)
+ * @param parent Parent fragmentActivity to set on this fragmentActivity
+ */
+ public void setParent(Activity parent){
+ this.parent = parent;
+ }
+
@Implementation
public void onBackPressed() {
finish();
@@ -346,12 +354,20 @@ public class ShadowActivity extends ShadowContextWrapper {
@Implementation
public void setRequestedOrientation(int requestedOrientation) {
- this.requestedOrientation = requestedOrientation;
+ if (getParent() != null){
+ getParent().setRequestedOrientation(requestedOrientation);
+ } else {
+ this.requestedOrientation = requestedOrientation;
+ }
}
@Implementation
public int getRequestedOrientation() {
- return requestedOrientation;
+ if (getParent() != null){
+ return getParent().getRequestedOrientation();
+ } else {
+ return this.requestedOrientation;
+ }
}
@Implementation
@@ -483,6 +499,11 @@ public class ShadowActivity extends ShadowContextWrapper {
}
@Implementation
+ public void startActivity(Intent intent) {
+ startActivityForResult(intent, -1);
+ }
+
+ @Implementation
public void startActivityForResult(Intent intent, int requestCode) {
intentRequestCodeMap.put(intent, requestCode);
startedActivitiesForResults.add(new IntentForResult(intent, requestCode));
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowAlertDialog.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowAlertDialog.java
index 53f20f67f..a23a37873 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowAlertDialog.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowAlertDialog.java
@@ -334,7 +334,7 @@ public class ShadowAlertDialog extends ShadowDialog {
@Implementation(i18nSafe=false)
public AlertDialog.Builder setTitle(CharSequence title) {
- this.title = title.toString();
+ this.title = title == null ? "" : title.toString();
return realBuilder;
}
@@ -352,7 +352,7 @@ public class ShadowAlertDialog extends ShadowDialog {
@Implementation(i18nSafe=false)
public AlertDialog.Builder setMessage(CharSequence message) {
- this.message = message.toString();
+ this.message = message == null ? "" : message.toString();
return realBuilder;
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowApplication.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowApplication.java
index 7b1471e75..057baee8d 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowApplication.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowApplication.java
@@ -137,6 +137,14 @@ public class ShadowApplication extends ShadowContextWrapper {
return resources;
}
+ /**
+ * Reset (set to null) resources instance, so they will be reloaded next time they are
+ * {@link #getResources gotten}
+ */
+ public void resetResources(){
+ resources = null;
+ }
+
@Implementation
@Override
public ContentResolver getContentResolver() {
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowBitmapDrawable.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowBitmapDrawable.java
index c7cc9e774..c6eaaaa9f 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowBitmapDrawable.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowBitmapDrawable.java
@@ -1,15 +1,18 @@
package com.xtremelabs.robolectric.shadows;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
import com.xtremelabs.robolectric.internal.RealObject;
import static android.graphics.Shader.TileMode;
+import static com.xtremelabs.robolectric.Robolectric.newInstanceOf;
import static com.xtremelabs.robolectric.Robolectric.shadowOf;
@SuppressWarnings({"UnusedDeclaration"})
@@ -28,6 +31,10 @@ public class ShadowBitmapDrawable extends ShadowDrawable {
this.bitmap = bitmap;
}
+ public void __constructor__(Resources resources, Bitmap bitmap) {
+ this.bitmap = bitmap;
+ }
+
/**
* Draws the contained bitmap onto the canvas at 0,0 with a default {@code Paint}
*
@@ -41,6 +48,16 @@ public class ShadowBitmapDrawable extends ShadowDrawable {
}
@Implementation
+ public Drawable mutate() {
+ BitmapDrawable real = newInstanceOf(BitmapDrawable.class);
+ ShadowBitmapDrawable shadow = shadowOf(real);
+ shadow.bitmap = this.bitmap;
+ shadow.colorFilter = this.colorFilter;
+ shadow.drawableCreateFromStreamSource = drawableCreateFromStreamSource;
+ return real;
+ }
+
+ @Implementation
public void setColorFilter(android.graphics.ColorFilter colorFilter) {
this.colorFilter = colorFilter;
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowBitmapFactory.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowBitmapFactory.java
index 1fa74cd39..c84b4c280 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowBitmapFactory.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowBitmapFactory.java
@@ -11,7 +11,7 @@ import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
import com.xtremelabs.robolectric.util.Join;
-import java.io.InputStream;
+import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -27,48 +27,77 @@ public class ShadowBitmapFactory {
private static Map<String, Point> widthAndHeightMap = new HashMap<String, Point>();
@Implementation
- public static Bitmap decodeResource(Resources res, int id) {
- Bitmap bitmap = create("resource:" + getResourceName(id));
- shadowOf(bitmap).setLoadedFromResourceId(id);
- return bitmap;
- }
-
- @Implementation
public static Bitmap decodeResource(Resources res, int id, BitmapFactory.Options options) {
Bitmap bitmap = create("resource:" + getResourceName(id), options);
shadowOf(bitmap).setLoadedFromResourceId(id);
return bitmap;
}
+ @Implementation
+ public static Bitmap decodeResource(Resources res, int id) {
+ return decodeResource(res, id, null);
+ }
+
private static String getResourceName(int id) {
return shadowOf(Robolectric.application).getResourceLoader().getNameForId(id);
}
@Implementation
public static Bitmap decodeFile(String pathName) {
- return create("file:" + pathName);
+ return decodeFile(pathName, null);
}
@Implementation
public static Bitmap decodeFile(String pathName, BitmapFactory.Options options) {
+ File file = new File(pathName);
+ if (file.exists()){
+ try {
+ BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
+ String line = bufferedReader.readLine();
+ StringBuilder sb = new StringBuilder();
+ while (line != null){
+ sb.append(line);
+ line = bufferedReader.readLine();
+ }
+ bufferedReader.close();
+
+ return create(sb.toString());
+
+ } catch (FileNotFoundException ignore) {
+ } catch (IOException ignore) {
+ }
+ }
+
return create("file:" + pathName, options);
}
@Implementation
public static Bitmap decodeStream(InputStream is) {
- return decodeStream(is, null, new BitmapFactory.Options());
+ return decodeStream(is, null, null);
}
@Implementation
public static Bitmap decodeStream(InputStream is, Rect outPadding, BitmapFactory.Options opts) {
return create(is.toString().replaceFirst("stream for ", ""), opts);
}
-
+
@Implementation
public static Bitmap decodeByteArray(byte[] data, int offset, int length) {
return decodeByteArray( data, offset, length, new BitmapFactory.Options() );
}
+ /*@Implementation
+ public static Bitmap decodeByteArray(byte[] data, int offset, int length, BitmapFactory.Options options) {
+ if ((offset | length) < 0 || data.length < offset + length) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ String desc = new String(data);
+ if (offset != 0 && length != data.length) {
+ desc += " bytes " + offset + ".." + length;
+ }
+ return create(desc, options);
+ }*/
+
@Implementation
public static Bitmap decodeByteArray(byte[] data, int offset, int length, BitmapFactory.Options opts) {
Checksum checksumEngine = new CRC32();
@@ -77,10 +106,12 @@ public class ShadowBitmapFactory {
}
static Bitmap create(String name) {
- return create(name, new BitmapFactory.Options());
+ return create(name, null);
}
public static Bitmap create(String name, BitmapFactory.Options options) {
+ if (options == null) options = new BitmapFactory.Options();
+
Bitmap bitmap = Robolectric.newInstanceOf(Bitmap.class);
ShadowBitmap shadowBitmap = shadowOf(bitmap);
shadowBitmap.appendDescription("Bitmap for " + name);
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowBluetoothAdapter.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowBluetoothAdapter.java
index 5932e3604..6cad80d72 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowBluetoothAdapter.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowBluetoothAdapter.java
@@ -18,6 +18,7 @@ public class ShadowBluetoothAdapter {
private Set<BluetoothDevice> bondedDevices = new HashSet<BluetoothDevice>();
private boolean isDiscovering;
private String address;
+ private boolean enabled;
@Implementation
public static BluetoothAdapter getDefaultAdapter() {
@@ -51,6 +52,14 @@ public class ShadowBluetoothAdapter {
}
@Implementation
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+ @Implementation
public String getAddress() {
return this.address;
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowCanvas.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowCanvas.java
index ae3405fb2..336c0bd9a 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowCanvas.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowCanvas.java
@@ -85,7 +85,7 @@ public class ShadowCanvas {
int y = (int) (top + translateY);
if (x != 0 || y != 0) {
appendDescription(" at (" + x + "," + y + ")");
- }
+ }
if (scaleX != 1 && scaleY != 1) {
appendDescription(" scaled by (" + scaleX + "," + scaleY + ")");
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowCheckedTextView.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowCheckedTextView.java
index 2fc8141ca..c867cfc79 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowCheckedTextView.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowCheckedTextView.java
@@ -3,16 +3,17 @@ package com.xtremelabs.robolectric.shadows;
import android.widget.CheckedTextView;
import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
+import com.xtremelabs.robolectric.internal.RealObject;
@SuppressWarnings({"UnusedDeclaration"})
@Implements(CheckedTextView.class)
public class ShadowCheckedTextView extends ShadowTextView {
-
+ @RealObject CheckedTextView realCheckedTextView;
private boolean checked;
@Implementation
- public void toggle() {
- checked = !checked;
+ public void setChecked(boolean checked) {
+ this.checked = checked;
}
@Implementation
@@ -20,9 +21,14 @@ public class ShadowCheckedTextView extends ShadowTextView {
return checked;
}
- @Implementation
- public void setChecked(boolean checked) {
- this.checked = checked;
+ @Implementation @Override
+ public boolean performClick() {
+ realCheckedTextView.toggle();
+ return super.performClick();
}
+ @Implementation
+ public void toggle() {
+ realCheckedTextView.setChecked(!realCheckedTextView.isChecked());
+ }
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowClipboardManager.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowClipboardManager.java
index de204fc25..b51ab8cfe 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowClipboardManager.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowClipboardManager.java
@@ -1,6 +1,6 @@
package com.xtremelabs.robolectric.shadows;
-import android.text.ClipboardManager;
+import android.content.ClipboardManager;
import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowConfiguration.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowConfiguration.java
index e94e2e7b2..a26ee1ed5 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowConfiguration.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowConfiguration.java
@@ -1,13 +1,12 @@
package com.xtremelabs.robolectric.shadows;
-import java.util.Locale;
-
import android.content.res.Configuration;
-
import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
import com.xtremelabs.robolectric.internal.RealObject;
+import java.util.Locale;
+
@Implements(Configuration.class)
public class ShadowConfiguration {
@@ -18,11 +17,138 @@ public class ShadowConfiguration {
public int touchscreen;
public int orientation;
+ public void __constructor__(Configuration other) {
+ realConfiguration.setTo(other);
+ }
+
+ @Implementation
+ public void setTo(Configuration o) {
+ // commented out lines are coming in a newer version of Android SDK
+
+ realConfiguration.fontScale = o.fontScale;
+ realConfiguration.mcc = o.mcc;
+ realConfiguration.mnc = o.mnc;
+ if (o.locale != null) {
+ realConfiguration.locale = (Locale) o.locale.clone();
+ // realConfiguration.textLayoutDirection = o.textLayoutDirection;
+ }
+ // realConfiguration.userSetLocale = o.userSetLocale;
+ realConfiguration.touchscreen = o.touchscreen;
+ realConfiguration.keyboard = o.keyboard;
+ realConfiguration.keyboardHidden = o.keyboardHidden;
+ realConfiguration.hardKeyboardHidden = o.hardKeyboardHidden;
+ realConfiguration.navigation = o.navigation;
+ realConfiguration.navigationHidden = o.navigationHidden;
+ realConfiguration.orientation = o.orientation;
+ realConfiguration.screenLayout = o.screenLayout;
+ realConfiguration.uiMode = o.uiMode;
+ realConfiguration.screenWidthDp = o.screenWidthDp;
+ realConfiguration.screenHeightDp = o.screenHeightDp;
+ realConfiguration.smallestScreenWidthDp = o.smallestScreenWidthDp;
+ // realConfiguration.compatScreenWidthDp = o.compatScreenWidthDp;
+ // realConfiguration.compatScreenHeightDp = o.compatScreenHeightDp;
+ // realConfiguration.compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
+ // realConfiguration.seq = o.seq;
+ }
+
+ @Implementation
+ public int compareTo(Configuration that) {
+ int n;
+ float a = realConfiguration.fontScale;
+ float b = that.fontScale;
+ if (a < b) return -1;
+ if (a > b) return 1;
+ n = realConfiguration.mcc - that.mcc;
+ if (n != 0) return n;
+ n = realConfiguration.mnc - that.mnc;
+ if (n != 0) return n;
+ if (realConfiguration.locale == null) {
+ if (that.locale != null) return 1;
+ } else if (that.locale == null) {
+ return -1;
+ } else {
+ n = realConfiguration.locale.getLanguage().compareTo(that.locale.getLanguage());
+ if (n != 0) return n;
+ n = realConfiguration.locale.getCountry().compareTo(that.locale.getCountry());
+ if (n != 0) return n;
+ n = realConfiguration.locale.getVariant().compareTo(that.locale.getVariant());
+ if (n != 0) return n;
+ }
+ n = realConfiguration.touchscreen - that.touchscreen;
+ if (n != 0) return n;
+ n = realConfiguration.keyboard - that.keyboard;
+ if (n != 0) return n;
+ n = realConfiguration.keyboardHidden - that.keyboardHidden;
+ if (n != 0) return n;
+ n = realConfiguration.hardKeyboardHidden - that.hardKeyboardHidden;
+ if (n != 0) return n;
+ n = realConfiguration.navigation - that.navigation;
+ if (n != 0) return n;
+ n = realConfiguration.navigationHidden - that.navigationHidden;
+ if (n != 0) return n;
+ n = realConfiguration.orientation - that.orientation;
+ if (n != 0) return n;
+ n = realConfiguration.screenLayout - that.screenLayout;
+ if (n != 0) return n;
+ n = realConfiguration.uiMode - that.uiMode;
+ if (n != 0) return n;
+ n = realConfiguration.screenWidthDp - that.screenWidthDp;
+ if (n != 0) return n;
+ n = realConfiguration.screenHeightDp - that.screenHeightDp;
+ if (n != 0) return n;
+ n = realConfiguration.smallestScreenWidthDp - that.smallestScreenWidthDp;
+ //if (n != 0) return n;
+ return n;
+ }
+
+ @Implementation
+ public boolean equals(Configuration that) {
+ if (that == null) return false;
+ if (that == realConfiguration) return true;
+ return realConfiguration.compareTo(that) == 0;
+ }
+
+ @Implementation
+ public boolean equals(Object that) {
+ try {
+ return equals((Configuration)that);
+ } catch (ClassCastException e) {
+ }
+ return false;
+ }
+
+ @Implementation
+ public int hashCode() {
+ int result = 17;
+ result = 31 * result + Float.floatToIntBits(realConfiguration.fontScale);
+ result = 31 * result + realConfiguration.mcc;
+ result = 31 * result + realConfiguration.mnc;
+ result = 31 * result + (realConfiguration.locale != null ? realConfiguration.locale.hashCode() : 0);
+ result = 31 * result + touchscreen;
+ result = 31 * result + realConfiguration.keyboard;
+ result = 31 * result + realConfiguration.keyboardHidden;
+ result = 31 * result + realConfiguration.hardKeyboardHidden;
+ result = 31 * result + realConfiguration.navigation;
+ result = 31 * result + realConfiguration.navigationHidden;
+ result = 31 * result + orientation;
+ result = 31 * result + screenLayout;
+ result = 31 * result + realConfiguration.uiMode;
+ result = 31 * result + realConfiguration.screenWidthDp;
+ result = 31 * result + realConfiguration.screenHeightDp;
+ result = 31 * result + realConfiguration.smallestScreenWidthDp;
+ return result;
+ }
+
@Implementation
public void setToDefaults() {
realConfiguration.screenLayout = Configuration.SCREENLAYOUT_LONG_NO |
Configuration.SCREENLAYOUT_SIZE_NORMAL;
}
+
+ @Implementation
+ public String toString() {
+ return realConfiguration.toString();
+ }
public void setLocale( Locale l ) {
realConfiguration.locale = l;
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowContentProviderOperationBuilder.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowContentProviderOperationBuilder.java
index 2f69a8cd9..917039ee6 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowContentProviderOperationBuilder.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowContentProviderOperationBuilder.java
@@ -1,23 +1,22 @@
package com.xtremelabs.robolectric.shadows;
-import java.util.Map;
-
import android.content.ContentProviderOperation;
import android.content.ContentProviderOperation.Builder;
import android.net.Uri;
-
import com.xtremelabs.robolectric.Robolectric;
import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
import com.xtremelabs.robolectric.internal.RealObject;
+import java.util.Map;
+
@Implements(ContentProviderOperation.Builder.class)
public class ShadowContentProviderOperationBuilder {
@RealObject private Builder realBuilder;
private ContentProviderOperation contentProviderOperation;
private ShadowContentProviderOperation shadowContentProviderOperation;
- public void __constructor__() {
+ public ShadowContentProviderOperationBuilder() {
contentProviderOperation = Robolectric.newInstanceOf(ContentProviderOperation.class);
shadowContentProviderOperation = Robolectric.shadowOf(contentProviderOperation);
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowContentResolver.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowContentResolver.java
index 8c5e4bde2..6f685a18b 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowContentResolver.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowContentResolver.java
@@ -6,6 +6,7 @@ import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
+import com.xtremelabs.robolectric.Robolectric;
import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
import com.xtremelabs.robolectric.tester.android.database.TestCursor;
@@ -62,6 +63,16 @@ public class ShadowContentResolver {
@Implementation
public final InputStream openInputStream(final Uri uri) {
+
+ if (uri != null && ContentResolver.SCHEME_ANDROID_RESOURCE.equals(uri.getScheme())) {
+ String path = uri.getPath();
+ // check that path is a numerical resource id
+ if (path != null && path.matches("/[0-9]+")) {
+ int resourceId = Integer.parseInt(path.substring(1));
+ return Robolectric.application.getResources().openRawResource(resourceId);
+ }
+ }
+
return new InputStream() {
@Override
public int read() throws IOException {
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowContext.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowContext.java
index 03da28612..7d648f199 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowContext.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowContext.java
@@ -11,11 +11,8 @@ import com.xtremelabs.robolectric.internal.Implements;
import com.xtremelabs.robolectric.internal.RealObject;
import com.xtremelabs.robolectric.res.ResourceLoader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
+import java.io.*;
+import java.util.UUID;
import static com.xtremelabs.robolectric.Robolectric.shadowOf;
@@ -81,7 +78,7 @@ abstract public class ShadowContext {
if( set == null ){
return getTheme().obtainStyledAttributes( attrs );
}
-
+
ShadowTypedArray styledAttributes = Robolectric.shadowOf(result);
for(int attr : attrs) {
styledAttributes.add(set.getAttributeValue(attr));
@@ -190,6 +187,7 @@ abstract public class ShadowContext {
try {
File tmp = File.createTempFile(name, "robolectric");
if (!tmp.delete()) throw new IOException("could not delete "+tmp);
+ tmp = new File(tmp, UUID.randomUUID().toString());
if (!tmp.mkdirs()) throw new IOException("could not create "+tmp);
tmp.deleteOnExit();
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowContextWrapper.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowContextWrapper.java
index 9724e6b41..54f5332a6 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowContextWrapper.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowContextWrapper.java
@@ -1,24 +1,19 @@
package com.xtremelabs.robolectric.shadows;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.ServiceConnection;
-import android.content.SharedPreferences;
+import android.content.*;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.os.Looper;
+import com.xtremelabs.robolectric.RobolectricConfig;
import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
import com.xtremelabs.robolectric.internal.RealObject;
+import com.xtremelabs.robolectric.res.RobolectricPackageManager;
import com.xtremelabs.robolectric.tester.android.content.TestSharedPreferences;
+import java.io.File;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -122,7 +117,14 @@ public class ShadowContextWrapper extends ShadowContext {
*/
@Implementation
public PackageManager getPackageManager() {
- return realContextWrapper == getApplicationContext() ? packageManager : getApplicationContext().getPackageManager();
+ return realContextWrapper == getApplicationContext() ? requirePackageManager() : getApplicationContext().getPackageManager();
+ }
+
+ private PackageManager requirePackageManager() {
+ if (packageManager == null) {
+ packageManager = new RobolectricPackageManager(realContextWrapper, new RobolectricConfig(new File(".")));
+ }
+ return packageManager;
}
@Implementation
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDateFormat.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDateFormat.java
index 7a5a42ec2..4a00bb35d 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDateFormat.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDateFormat.java
@@ -6,11 +6,18 @@ import android.text.format.DateFormat;
import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
+import java.util.Locale;
+
@Implements(DateFormat.class)
public class ShadowDateFormat {
@Implementation
- public final static java.text.DateFormat getDateFormat(Context context) {
- return java.text.DateFormat.getDateInstance();
+ public static java.text.DateFormat getDateFormat(Context context) {
+ return new java.text.SimpleDateFormat("MMM-DD-yyyy", Locale.ROOT);
+ }
+
+ @Implementation
+ public static java.text.DateFormat getTimeFormat(Context context) {
+ return new java.text.SimpleDateFormat("HH:mm:ss", Locale.ROOT);
}
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDefaultRequestDirector.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDefaultRequestDirector.java
index 2b54e94c9..ac1e8df44 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDefaultRequestDirector.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDefaultRequestDirector.java
@@ -126,6 +126,9 @@ public class ShadowDefaultRequestDirector {
params);
}
+ /**
+ * @deprecated Use {@link Robolectric#getSentHttpRequestInfo(int)} instead.)
+ */
public static HttpRequest getSentHttpRequest(int index) {
return getSentHttpRequestInfo(index).getHttpRequest();
}
@@ -139,6 +142,9 @@ public class ShadowDefaultRequestDirector {
return Robolectric.getFakeHttpLayer().getSentHttpRequestInfo(requestCount - 1);
}
+ /**
+ * @deprecated Use {@link Robolectric#getSentHttpRequest(int)} instead.)
+ */
public static HttpRequestInfo getSentHttpRequestInfo(int index) {
return Robolectric.getFakeHttpLayer().getSentHttpRequestInfo(index);
}
@@ -206,4 +212,4 @@ public class ShadowDefaultRequestDirector {
public HttpParams getHttpParams() {
return httpParams;
}
-} \ No newline at end of file
+}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDialog.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDialog.java
index 0f317a290..ccbcd58bc 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDialog.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDialog.java
@@ -14,7 +14,6 @@ import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
import com.xtremelabs.robolectric.internal.RealObject;
import com.xtremelabs.robolectric.tester.android.view.TestWindow;
-
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
@@ -149,12 +148,11 @@ public class ShadowDialog {
@Implementation
public View findViewById(int viewId) {
- if (inflatedView != null) {
- return inflatedView.findViewById(viewId);
- }
- if (layoutId > 0 && context != null) {
- inflatedView = ShadowLayoutInflater.from(context).inflate(layoutId, null);
- return inflatedView.findViewById(viewId);
+ if (context != null) {
+ if (inflatedView == null && layoutId > 0) {
+ inflatedView = ShadowLayoutInflater.from(context).inflate(layoutId, null);
+ }
+ if (inflatedView != null) return inflatedView.findViewById(viewId);
}
return null;
}
@@ -211,7 +209,6 @@ public class ShadowDialog {
return window;
}
-
@Implementation
public LayoutInflater getLayoutInflater() {
return LayoutInflater.from(realDialog.getContext());
@@ -243,6 +240,12 @@ public class ShadowDialog {
}
}
+ public void clickOnText(String text) {
+ if (!clickOnText(inflatedView, text)) {
+ throw new IllegalArgumentException("Text not found: " + text);
+ }
+ }
+
private boolean clickOnText(View view, String text) {
if (text.equals(shadowOf(view).innerText())) {
view.performClick();
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDialogFragment.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDialogFragment.java
index af245e794..2e99886cf 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDialogFragment.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDialogFragment.java
@@ -38,10 +38,10 @@ public class ShadowDialogFragment extends ShadowFragment {
shadowOf(realDialogFragment).setActivity(activityFromManager);
- realDialogFragment.onAttach(activity);
+ realDialogFragment.onAttach(fragmentActivity);
realDialogFragment.onCreate(null);
dialog = realDialogFragment.onCreateDialog(null);
- view = realDialogFragment.onCreateView(ShadowLayoutInflater.from(activity), null, null);
+ view = realDialogFragment.onCreateView(ShadowLayoutInflater.from(fragmentActivity), null, null);
if (dialog == null) {
dialog = new Dialog(activityFromManager);
dialog.setContentView(view);
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDisplay.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDisplay.java
index fe0914fcb..dabf874cf 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDisplay.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDisplay.java
@@ -57,6 +57,11 @@ public class ShadowDisplay {
}
@Implementation
+ public int getOrientation() {
+ return getRotation();
+ }
+
+ @Implementation
public int getRotation() {
return rotation;
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDownloadManager.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDownloadManager.java
new file mode 100644
index 000000000..4f21db649
--- /dev/null
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowDownloadManager.java
@@ -0,0 +1,223 @@
+package com.xtremelabs.robolectric.shadows;
+
+import android.app.DownloadManager;
+import android.database.Cursor;
+import com.xtremelabs.robolectric.internal.Implementation;
+import com.xtremelabs.robolectric.internal.Implements;
+import com.xtremelabs.robolectric.internal.RealObject;
+import com.xtremelabs.robolectric.tester.android.database.TestCursor;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static com.xtremelabs.robolectric.Robolectric.shadowOf_;
+
+/**
+ * Shadows Androids DownloadManager
+ */
+@Implements(DownloadManager.class)
+public class ShadowDownloadManager {
+
+ private Map<Long, DownloadManager.Request> requestMap = new HashMap<Long, DownloadManager.Request>();
+ private long queueCounter = -1; // First request starts at 0 just like in the real DownloadManager.
+
+ @Implementation
+ public long enqueue(DownloadManager.Request request) {
+ queueCounter++;
+ requestMap.put(queueCounter, request);
+
+ return queueCounter;
+ }
+
+ @Implementation
+ public int remove(long... ids) {
+ int removeCount = 0;
+ for (long id : ids) {
+ if (requestMap.remove(id) != null) {
+ removeCount++;
+ }
+ }
+ return removeCount;
+ }
+
+ @Implementation
+ public Cursor query(DownloadManager.Query query) {
+ ShadowQuery shadow = shadowOf_(query);
+ long[] ids = shadow.getIds();
+
+ ResultCursor result = new ResultCursor();
+ for (long id : ids) {
+ DownloadManager.Request request = requestMap.get(id);
+ if (request != null) {
+ result.requests.add(request);
+ }
+ }
+
+ return result;
+ }
+
+ public DownloadManager.Request getRequest(long id) {
+ return requestMap.get(id);
+ }
+
+ public int getRequestCount() {
+ return requestMap.size();
+ }
+
+ @Implements(DownloadManager.Request.class)
+ public static class ShadowRequest {
+ @RealObject
+ DownloadManager.Request realObject;
+
+ private CharSequence description;
+ private int status;
+
+ @Implementation
+ public DownloadManager.Request setAllowedNetworkTypes(int flags) {
+ return realObject;
+ }
+
+ @Implementation
+ public DownloadManager.Request setMimeType(String mimeType) {
+ return realObject;
+ }
+
+ @Implementation
+ public DownloadManager.Request setTitle(CharSequence title) {
+ return realObject;
+ }
+
+ @Implementation
+ public DownloadManager.Request setDescription(CharSequence description) {
+ this.description = description;
+ return realObject;
+ }
+
+ @Implementation
+ public DownloadManager.Request setAllowedOverRoaming(boolean allowed) {
+ return realObject;
+ }
+
+ @Implementation
+ public DownloadManager.Request setDestinationInExternalPublicDir(String dirType, String subPath) {
+ return realObject;
+ }
+
+ public CharSequence getDescription() {
+ return this.description;
+ }
+
+ public void setStatus(int status) {
+ this.status = status;
+ }
+
+ public int getStatus() {
+ return this.status;
+ }
+ }
+
+ @Implements(DownloadManager.Query.class)
+ public static class ShadowQuery {
+
+ @RealObject
+ private DownloadManager.Query realObject;
+
+ private long[] ids = null;
+
+ @Implementation
+ public DownloadManager.Query setFilterById(long... ids) {
+ this.ids = ids;
+ return realObject;
+ }
+
+ public long[] getIds() {
+ return this.ids;
+ }
+ }
+
+ private class ResultCursor extends TestCursor {
+
+ private static final int COLUMN_INDEX_LOCAL_FILENAME = 0;
+ private static final int COLUMN_INDEX_DESCRIPTION = 1;
+ private static final int COLUMN_INDEX_REASON = 2;
+ private static final int COLUMN_INDEX_STATUS = 3;
+
+ public List<DownloadManager.Request> requests = new ArrayList<DownloadManager.Request>();
+ private int positionIndex;
+ private boolean closed;
+
+ @Override
+ public int getCount() {
+ checkClosed();
+ return requests.size();
+ }
+
+ @Override
+ public boolean moveToFirst() {
+ checkClosed();
+ positionIndex = 0;
+ return !requests.isEmpty();
+ }
+
+ @Override
+ public int getColumnIndex(String columnName) {
+ checkClosed();
+
+ if (DownloadManager.COLUMN_LOCAL_FILENAME.equals(columnName)) {
+ return COLUMN_INDEX_LOCAL_FILENAME;
+ } else if (DownloadManager.COLUMN_DESCRIPTION.equals(columnName)) {
+ return COLUMN_INDEX_DESCRIPTION;
+ } else if (DownloadManager.COLUMN_REASON.equals(columnName)) {
+ return COLUMN_INDEX_REASON;
+ } else if (DownloadManager.COLUMN_STATUS.equals(columnName)) {
+ return COLUMN_INDEX_STATUS;
+ }
+
+ return 0;
+ }
+
+ @Override
+ public void close() {
+ this.closed = true;
+ }
+
+ @Override
+ public boolean isClosed() {
+ return closed;
+ }
+
+ @Override
+ public String getString(int columnIndex) {
+ checkClosed();
+ ShadowRequest request = shadowOf_(requests.get(positionIndex));
+ switch (columnIndex) {
+ case COLUMN_INDEX_LOCAL_FILENAME:
+ return "local file name not implemented";
+ case COLUMN_INDEX_DESCRIPTION:
+ return request.getDescription().toString();
+ case COLUMN_INDEX_REASON:
+ return "reason not implemented";
+ }
+
+ return "Unknown ColumnIndex " + columnIndex;
+ }
+
+ @Override
+ public int getInt(int columnIndex) {
+ checkClosed();
+ ShadowRequest request = shadowOf_(requests.get(positionIndex));
+ if (columnIndex == COLUMN_INDEX_STATUS) {
+ return request.getStatus();
+ }
+ return 0;
+ }
+
+ private void checkClosed() {
+ if (closed) {
+ throw new IllegalStateException("Cursor is already closed.");
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowEnvironment.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowEnvironment.java
index 27d49b7ab..d938b1673 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowEnvironment.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowEnvironment.java
@@ -1,11 +1,11 @@
package com.xtremelabs.robolectric.shadows;
-import java.io.File;
-
import android.os.Environment;
import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
+import java.io.File;
+
@Implements(Environment.class)
public class ShadowEnvironment {
@@ -27,7 +27,7 @@ public class ShadowEnvironment {
ShadowContext.EXTERNAL_CACHE_DIR.mkdirs();
return ShadowContext.EXTERNAL_CACHE_DIR;
}
-
+
@Implementation
public static File getExternalStoragePublicDirectory(String type) {
File f = (type == null) ? ShadowContext.EXTERNAL_FILES_DIR : new File( ShadowContext.EXTERNAL_FILES_DIR, type );
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowFragment.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowFragment.java
index e70f70b78..f39a03052 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowFragment.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowFragment.java
@@ -9,11 +9,16 @@ import android.support.v4.app.FragmentManager;
import android.view.View;
import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
+import com.xtremelabs.robolectric.internal.RealObject;
+
+import java.lang.reflect.Field;
@Implements(Fragment.class)
public class ShadowFragment {
+ @RealObject Fragment realFragment;
+
protected View view;
- protected FragmentActivity activity;
+ protected FragmentActivity fragmentActivity;
private String tag;
private Bundle savedInstanceState;
private int containerViewId;
@@ -21,12 +26,26 @@ public class ShadowFragment {
private Bundle arguments;
private boolean attached;
+ private int fragmentId;
+
+ private Fragment targetFragment;
+ private boolean resumed;
+
public void setView(View view) {
this.view = view;
}
public void setActivity(FragmentActivity activity) {
- this.activity = activity;
+ if (fragmentActivity != null) realFragment.onDetach();
+ fragmentActivity = activity;
+ if (activity != null) realFragment.onAttach(activity);
+ try {
+ Field field = Fragment.class.getDeclaredField("mActivity");
+ field.setAccessible(true);
+ field.set(realFragment, activity);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Unable to set mActivity field");
+ }
}
@Implementation
@@ -36,22 +55,28 @@ public class ShadowFragment {
@Implementation
public FragmentActivity getActivity() {
- return activity;
+ return fragmentActivity;
}
@Implementation
public void startActivity(Intent intent) {
- new FragmentActivity().startActivity(intent);
+ if (fragmentActivity == null) {
+ throw new IllegalStateException("Fragment " + this + " not attached to Activity");
+ }
+ fragmentActivity.startActivity(intent);
}
@Implementation
public void startActivityForResult(Intent intent, int requestCode) {
- activity.startActivityForResult(intent, requestCode);
+ if (fragmentActivity == null) {
+ throw new IllegalStateException("Fragment " + this + " not attached to Activity");
+ }
+ fragmentActivity.startActivityForResult(intent, requestCode);
}
@Implementation
final public FragmentManager getFragmentManager() {
- return activity.getSupportFragmentManager();
+ return fragmentActivity.getSupportFragmentManager();
}
@Implementation
@@ -61,17 +86,14 @@ public class ShadowFragment {
@Implementation
public Resources getResources() {
- if (activity == null) {
+ if (fragmentActivity == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
- return activity.getResources();
+ return fragmentActivity.getResources();
}
@Implementation
public String getString(int id) {
- if (activity == null) {
- throw new IllegalStateException("Fragment " + this + " not attached to Activity");
- }
return getResources().getString(id);
}
@@ -120,4 +142,72 @@ public class ShadowFragment {
public boolean isAttached() {
return attached;
}
+
+ @Implementation
+ public final CharSequence getText(int resId) {
+ return getResources().getText(resId);
+ }
+
+ @Implementation
+ public final String getString(int resId, Object... formatArgs) {
+ return getResources().getString(resId, formatArgs);
+ }
+
+ @Implementation
+ public int getId() {
+ return fragmentId;
+ }
+
+ @Implementation
+ public boolean isAdded() {
+ return fragmentActivity != null;
+ }
+
+ @Implementation
+ public boolean isVisible() {
+ return fragmentActivity != null;
+ }
+
+ @Implementation
+ public Fragment getTargetFragment() {
+ return targetFragment;
+ }
+
+ @Implementation
+ public void setTargetFragment(Fragment targetFragment, int requestCode) {
+ this.targetFragment = targetFragment;
+ }
+
+ @Implementation
+ public void onResume() {
+ this.resumed = true;
+ }
+
+ public void resume() {
+ realFragment.onResume();
+ }
+
+ @Implementation
+ public void onPause() {
+ this.resumed = false;
+ }
+
+ public void pause() {
+ realFragment.onPause();
+ }
+
+ @Implementation
+ public boolean isResumed() {
+ return resumed;
+ }
+
+ public void createView() {
+ final FragmentActivity activity = getActivity();
+ view = realFragment.onCreateView(activity.getLayoutInflater(), null, null);
+ realFragment.onViewCreated(view, null);
+ }
+
+ public void setFragmentId(int fragmentId) {
+ this.fragmentId = fragmentId;
+ }
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowFrameLayout.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowFrameLayout.java
index d96ca345f..0b57a3393 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowFrameLayout.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowFrameLayout.java
@@ -2,10 +2,10 @@ package com.xtremelabs.robolectric.shadows;
import android.content.Context;
import android.util.AttributeSet;
+import android.view.View;
import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import android.widget.FrameLayout;
-
import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
@@ -15,6 +15,7 @@ import com.xtremelabs.robolectric.internal.Implements;
@SuppressWarnings("UnusedDeclaration")
@Implements(FrameLayout.class)
public class ShadowFrameLayout extends ShadowViewGroup {
+ private FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(0, 0);
public void __constructor__(Context context, AttributeSet attributeSet, int defStyle) {
setLayoutParams(new ViewGroup.MarginLayoutParams(0, 0));
@@ -27,5 +28,16 @@ public class ShadowFrameLayout extends ShadowViewGroup {
int height = MeasureSpec.getSize(heightMeasureSpec);
layout(right, top, right + width, top + height);
- }
+ }
+
+ @Implementation
+ @Override
+ public ViewGroup.LayoutParams getLayoutParams() {
+ return layoutParams;
+ }
+
+ @Override
+ protected void setChildLayoutParams(View child) {
+ child.setLayoutParams(new FrameLayout.LayoutParams(0, 0));
+ }
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowImageButton.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowImageButton.java
new file mode 100644
index 000000000..5dce34a47
--- /dev/null
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowImageButton.java
@@ -0,0 +1,15 @@
+package com.xtremelabs.robolectric.shadows;
+
+import android.widget.ImageButton;
+import com.xtremelabs.robolectric.internal.Implements;
+
+@Implements(ImageButton.class)
+public class ShadowImageButton extends ShadowImageView {
+ @Override
+ public void applyAttributes() {
+ super.applyAttributes();
+ if (getBackground() == null) {
+ setBackgroundColor(android.R.color.transparent);
+ }
+ }
+}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowImageView.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowImageView.java
index dfa685b8b..16360ddee 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowImageView.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowImageView.java
@@ -19,7 +19,6 @@ import static com.xtremelabs.robolectric.Robolectric.shadowOf;
@Implements(ImageView.class)
public class ShadowImageView extends ShadowView {
private Drawable imageDrawable;
- private int alpha;
private int resourceId;
private Bitmap imageBitmap;
private ImageView.ScaleType scaleType;
@@ -92,17 +91,12 @@ public class ShadowImageView extends ShadowView {
* @param resourceId Resource id
* @return Boolean
*/
- private boolean isDrawableXml(int resourceId) {
+ protected boolean isDrawableXml(int resourceId) {
return shadowOf(Robolectric.application).getResourceLoader()
.isDrawableXml(resourceId);
}
@Implementation
- public void setAlpha(int alpha) {
- this.alpha = alpha;
- }
-
- @Implementation
public ImageView.ScaleType getScaleType() {
return scaleType;
}
@@ -144,7 +138,9 @@ public class ShadowImageView extends ShadowView {
canvas.scale(shadowOf(matrix).getScaleX(), shadowOf(matrix)
.getScaleY());
}
- imageDrawable.draw(canvas);
+ if (imageDrawable != null) {
+ imageDrawable.draw(canvas);
+ }
}
private void applyImageAttribute() {
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowLinearLayout.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowLinearLayout.java
index 2a4ab572d..bedf86bda 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowLinearLayout.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowLinearLayout.java
@@ -1,13 +1,18 @@
package com.xtremelabs.robolectric.shadows;
+import android.view.View;
import android.widget.LinearLayout;
import com.xtremelabs.robolectric.internal.Implements;
@Implements(LinearLayout.class)
public class ShadowLinearLayout extends ShadowViewGroup {
-
public ShadowLinearLayout() {
setLayoutParams(new LinearLayout.LayoutParams(0, 0));
}
+ @Override
+ protected void setChildLayoutParams(View child) {
+ child.setLayoutParams(new LinearLayout.LayoutParams(0, 0));
+ }
+
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowListActivity.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowListActivity.java
index f57ab6ec4..c2fc1a02c 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowListActivity.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowListActivity.java
@@ -2,7 +2,6 @@ package com.xtremelabs.robolectric.shadows;
import android.app.ListActivity;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
@@ -64,18 +63,15 @@ public class ShadowListActivity extends ShadowActivity {
return listAdapter;
}
+ /**
+ * Copied wholesale from Android ListActivity source.
+ */
private ListView findListView(View parent) {
- if (parent instanceof ListView) {
- return (ListView) parent;
- } else if (parent instanceof ViewGroup) {
- ViewGroup viewGroup = (ViewGroup) parent;
- for (int i = 0; i < viewGroup.getChildCount(); i++) {
- ListView listView = findListView(viewGroup.getChildAt(i));
- if (listView != null) {
- return listView;
- }
- }
+ listView = (ListView)findViewById(android.R.id.list);
+ if (listView == null) {
+ throw new RuntimeException("Your content must have a ListView whose id attribute is 'android.R.id.list'");
}
- return null;
+
+ return listView;
}
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowLocalActivityManager.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowLocalActivityManager.java
new file mode 100644
index 000000000..5a72ce4e6
--- /dev/null
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowLocalActivityManager.java
@@ -0,0 +1,36 @@
+package com.xtremelabs.robolectric.shadows;
+
+import android.app.Activity;
+import android.app.LocalActivityManager;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Window;
+import com.xtremelabs.robolectric.internal.Implementation;
+import com.xtremelabs.robolectric.internal.Implements;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ *
+ */
+@Implements(LocalActivityManager.class)
+public class ShadowLocalActivityManager {
+
+ @Implementation
+ public Window startActivity(String id, Intent intent) {
+ try {
+ final String clazz = intent.getComponent().getClassName();
+ final Class<? extends Activity> aClass = (Class<? extends Activity>) Class.forName(clazz);
+ final Constructor<? extends Activity> ctor = aClass.getConstructor();
+ Activity activity = ctor.newInstance();
+ final Method onCreateMethod = aClass.getDeclaredMethod("onCreate", Bundle.class);
+ onCreateMethod.setAccessible(true);
+ onCreateMethod.invoke(activity, (Bundle) null);
+ return activity.getWindow();
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to create class", e);
+ }
+ }
+
+}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowLocation.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowLocation.java
index 07a48126c..81b5b8a51 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowLocation.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowLocation.java
@@ -341,8 +341,16 @@ public class ShadowLocation {
}
}
+ private static float[] distanceBetween;
+
+ public static void setDistanceBetween(float[] distanceBetween) {
+ ShadowLocation.distanceBetween = distanceBetween;
+ }
+
/**
- * Computes the approximate distance in meters between two
+ * If it is non-null, returns the mock distance last set with
+ * {@link #setDistanceBetween}.
+ * Otherwise computes the approximate distance in meters between two
* locations, and optionally the initial and final bearings of the
* shortest path between them. Distance and bearing are defined using the
* WGS84 ellipsoid.
@@ -362,6 +370,11 @@ public class ShadowLocation {
@Implementation
public static void distanceBetween(double startLatitude, double startLongitude,
double endLatitude, double endLongitude, float[] results) {
+ if (distanceBetween != null && results.length == distanceBetween.length){
+ System.arraycopy(distanceBetween, 0, results, 0, results.length);
+ return;
+ }
+
if (results == null || results.length < 1) {
throw new IllegalArgumentException("results is null or has length < 1");
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowLocationManager.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowLocationManager.java
index 4c4fdf509..088647f69 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowLocationManager.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowLocationManager.java
@@ -30,7 +30,30 @@ public class ShadowLocationManager {
private Criteria lastBestProviderCriteria;
private boolean lastBestProviderEnabled;
private String bestEnabledProvider, bestDisabledProvider;
- private final Map<LocationListener, Set<String>> requestLocationUpdateListenersMap = new LinkedHashMap<LocationListener, Set<String>>();
+
+ /** Location listeners along with metadata on when they should be fired. */
+ private static final class ListenerRegistration {
+ final long minTime;
+ final float minDistance;
+ final LocationListener listener;
+ final String provider;
+ Location lastSeenLocation;
+ long lastSeenTime;
+
+ ListenerRegistration(String provider, long minTime, float minDistance, Location locationAtCreation,
+ LocationListener listener) {
+ this.provider = provider;
+ this.minTime = minTime;
+ this.minDistance = minDistance;
+ this.lastSeenTime = locationAtCreation == null ? 0 : locationAtCreation.getTime();
+ this.lastSeenLocation = locationAtCreation;
+ this.listener = listener;
+ }
+ }
+
+ /** Mapped by provider. */
+ private final Map<String, List<ListenerRegistration>> locationListeners =
+ new HashMap<String, List<ListenerRegistration>>();
@Implementation
public boolean isProviderEnabled(String provider) {
@@ -72,7 +95,7 @@ public class ShadowLocationManager {
providerEntry.enabled = isEnabled;
providerEntry.criteria = criteria;
providersEnabled.put(provider, providerEntry);
- List<LocationListener> locationUpdateListeners = new ArrayList<LocationListener>(requestLocationUpdateListenersMap.keySet());
+ List<LocationListener> locationUpdateListeners = new ArrayList<LocationListener>(getRequestLocationUpdateListeners());
for (LocationListener locationUpdateListener : locationUpdateListeners) {
if (isEnabled) {
locationUpdateListener.onProviderEnabled(provider);
@@ -204,20 +227,24 @@ public class ShadowLocationManager {
@Implementation
public void requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener) {
- addLocationListener(provider, listener);
+ addLocationListener(provider, listener, minTime, minDistance);
}
- private void addLocationListener(String provider, LocationListener listener) {
- if (!requestLocationUpdateListenersMap.containsKey(listener)) {
- requestLocationUpdateListenersMap.put(listener, new HashSet<String>());
+ private void addLocationListener(String provider, LocationListener listener, long minTime, float minDistance) {
+ List<ListenerRegistration> providerListeners = locationListeners.get(provider);
+ if (providerListeners == null) {
+ providerListeners = new ArrayList<ListenerRegistration>();
+ locationListeners.put(provider, providerListeners);
}
- requestLocationUpdateListenersMap.get(listener).add(provider);
+ providerListeners.add(new ListenerRegistration(provider,
+ minTime, minDistance, copyOf(getLastKnownLocation(provider)), listener));
+
}
@Implementation
public void requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener,
Looper looper) {
- addLocationListener(provider, listener);
+ addLocationListener(provider, listener, minTime, minDistance);
}
@Implementation
@@ -246,7 +273,12 @@ public class ShadowLocationManager {
@Implementation
public void removeUpdates(LocationListener listener) {
- requestLocationUpdateListenersMap.remove(listener);
+ for (Map.Entry<String, List<ListenerRegistration>> entry : locationListeners.entrySet()) {
+ List<ListenerRegistration> listenerRegistrations = entry.getValue();
+ for (int i = listenerRegistrations.size() - 1; i >= 0; i--) {
+ if (listenerRegistrations.get(i).listener.equals(listener)) listenerRegistrations.remove(i);
+ }
+ }
}
@Implementation
@@ -350,7 +382,68 @@ public class ShadowLocationManager {
* @return lastRequestedLocationUpdatesLocationListener
*/
public List<LocationListener> getRequestLocationUpdateListeners() {
- return new ArrayList<LocationListener>(requestLocationUpdateListenersMap.keySet());
+ List<LocationListener> all = new ArrayList<LocationListener>();
+ for (Map.Entry<String, List<ListenerRegistration>> entry : locationListeners.entrySet()) {
+ for (ListenerRegistration reg : entry.getValue()) {
+ all.add(reg.listener);
+ }
+ }
+
+ return all;
+ }
+
+ public void simulateLocation(Location location) {
+ setLastKnownLocation(location.getProvider(), location);
+
+ List<ListenerRegistration> providerListeners = locationListeners.get(
+ location.getProvider());
+ if (providerListeners == null) return;
+
+ for (ListenerRegistration listenerReg : providerListeners) {
+ if(listenerReg.lastSeenLocation != null && location != null) {
+ float distanceChange = distanceBetween(location, listenerReg.lastSeenLocation);
+ boolean withinMinDistance = distanceChange < listenerReg.minDistance;
+ boolean exceededMinTime = location.getTime() - listenerReg.lastSeenTime > listenerReg.minTime;
+ if (withinMinDistance && !exceededMinTime) continue;
+ }
+ listenerReg.lastSeenLocation = copyOf(location);
+ listenerReg.lastSeenTime = location == null ? 0 : location.getTime();
+ listenerReg.listener.onLocationChanged(copyOf(location));
+ }
+ }
+
+ private Location copyOf(Location location) {
+ if (location == null) return null;
+ Location copy = new Location(location);
+ copy.setAccuracy(location.getAccuracy());
+ copy.setAltitude(location.getAltitude());
+ copy.setBearing(location.getBearing());
+ copy.setExtras(location.getExtras());
+ copy.setLatitude(location.getLatitude());
+ copy.setLongitude(location.getLongitude());
+ copy.setProvider(location.getProvider());
+ copy.setSpeed(location.getSpeed());
+ copy.setTime(location.getTime());
+ return copy;
+ }
+
+ /**
+ * Returns the distance between the two locations in meters.
+ * Adapted from: http://stackoverflow.com/questions/837872/calculate-distance-in-meters-when-you-know-longitude-and-latitude-in-java
+ */
+ private static float distanceBetween(Location location1, Location location2) {
+ double earthRadius = 3958.75;
+ double latDifference = Math.toRadians(location2.getLatitude() - location1.getLatitude());
+ double lonDifference = Math.toRadians(location2.getLongitude() - location2.getLongitude());
+ double a = Math.sin(latDifference/2) * Math.sin(latDifference/2) +
+ Math.cos(Math.toRadians(location1.getLatitude())) * Math.cos(Math.toRadians(location2.getLatitude())) *
+ Math.sin(lonDifference/2) * Math.sin(lonDifference/2);
+ double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
+ double dist = Math.abs(earthRadius * c);
+
+ int meterConversion = 1609;
+
+ return new Float(dist * meterConversion);
}
public Map<PendingIntent, Criteria> getRequestLocationUdpateCriteriaPendingIntents() {
@@ -362,8 +455,15 @@ public class ShadowLocationManager {
}
public Collection<String> getProvidersForListener(LocationListener listener) {
- Set<String> providers = requestLocationUpdateListenersMap.get(listener);
- return providers == null ? Collections.<String>emptyList() : new ArrayList<String>(providers);
+ Set<String> providers = new HashSet<String>();
+ for (List<ListenerRegistration> listenerRegistrations : locationListeners.values()) {
+ for (ListenerRegistration listenerRegistration : listenerRegistrations) {
+ if (listenerRegistration.listener == listener) {
+ providers.add(listenerRegistration.provider);
+ }
+ }
+ }
+ return providers;
}
final private class LocationProviderEntry implements Map.Entry<Boolean, List<Criteria>> {
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowMeasureSpec.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowMeasureSpec.java
new file mode 100644
index 000000000..8c6956aac
--- /dev/null
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowMeasureSpec.java
@@ -0,0 +1,50 @@
+package com.xtremelabs.robolectric.shadows;
+
+import android.view.View;
+import com.xtremelabs.robolectric.internal.Implementation;
+import com.xtremelabs.robolectric.internal.Implements;
+
+@SuppressWarnings({"UnusedDeclaration"})
+@Implements(View.MeasureSpec.class)
+public class ShadowMeasureSpec {
+ private static final int MODE_SHIFT = 30;
+ private static final int MODE_MASK = 0x3 << MODE_SHIFT;
+ public static final int UNSPECIFIED = 0 << MODE_SHIFT;
+ public static final int EXACTLY = 1 << MODE_SHIFT;
+ public static final int AT_MOST = 2 << MODE_SHIFT;
+
+ @Implementation
+ public static int makeMeasureSpec(int size, int mode) {
+ return size + mode;
+ }
+
+ @Implementation
+ public static int getMode(int measureSpec) {
+ return (measureSpec & MODE_MASK);
+ }
+
+ @Implementation
+ public static int getSize(int measureSpec) {
+ return (measureSpec & ~MODE_MASK);
+ }
+
+ @Implementation
+ public static String toString(int measureSpec) {
+ int mode = getMode(measureSpec);
+ int size = getSize(measureSpec);
+
+ StringBuilder sb = new StringBuilder("MeasureSpec: ");
+
+ if (mode == UNSPECIFIED)
+ sb.append("UNSPECIFIED ");
+ else if (mode == EXACTLY)
+ sb.append("EXACTLY ");
+ else if (mode == AT_MOST)
+ sb.append("AT_MOST ");
+ else
+ sb.append(mode).append(" ");
+
+ sb.append(size);
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowNotificationManager.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowNotificationManager.java
index e06065f9b..9959dfb04 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowNotificationManager.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowNotificationManager.java
@@ -14,8 +14,7 @@ import java.util.Map;
@Implements(NotificationManager.class)
public class ShadowNotificationManager {
- private Map<Integer, Notification> notifications = new HashMap<Integer, Notification>();
- private Map<String, Integer> idForTag = new HashMap<String, Integer>();
+ private Map<Key, Notification> notifications = new HashMap<Key, Notification>();
@Implementation
public void notify(int id, Notification notification)
@@ -25,10 +24,7 @@ public class ShadowNotificationManager {
@Implementation
public void notify(String tag, int id, Notification notification) {
- if (tag != null) {
- idForTag.put(tag, id);
- }
- notifications.put(id, notification);
+ notifications.put(new Key(tag, id), notification);
}
@Implementation
@@ -39,35 +35,53 @@ public class ShadowNotificationManager {
@Implementation
public void cancel(String tag, int id) {
- // I can't make sense of this method signature. I'm guessing that the id is optional and if it's bogus you are supposed to use the tag instead, but that references to both should be gone. PG
- Integer tagId = idForTag.remove(tag);
- if (notifications.containsKey(id)) {
- notifications.remove(id);
- } else {
- notifications.remove(tagId);
+ Key key = new Key(tag, id);
+ if (notifications.containsKey(key)) {
+ notifications.remove(key);
}
}
@Implementation
public void cancelAll() {
notifications.clear();
- idForTag.clear();
}
public int size() {
return notifications.size();
}
- public Notification getNotification(int id) {
- return notifications.get(id);
- }
-
- public Notification getNotification(String tag) {
- Integer id = idForTag.get(tag);
- return notifications.get(id);
+ public Notification getNotification(String tag, int id) {
+ return notifications.get(new Key(tag, id));
}
public List<Notification> getAllNotifications() {
return new ArrayList<Notification>(notifications.values());
}
+
+ private static final class Key {
+ public final String tag;
+ public final int id;
+
+ private Key(String tag, int id) {
+ this.tag = tag;
+ this.id = id;
+ }
+
+ @Override
+ public int hashCode() {
+ int hashCode = 17;
+ hashCode = 37 * hashCode + (tag == null ? 0 : tag.hashCode());
+ hashCode = 37 * hashCode + id;
+ return hashCode;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Key)) return false;
+ Key other = (Key) o;
+ return (this.tag == null ? other.tag == null : this.tag.equals(other.tag))
+ && this.id == other.id;
+
+ }
+ }
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowPointF.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowPointF.java
index 38dd7416f..581b5f631 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowPointF.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowPointF.java
@@ -9,7 +9,7 @@ import com.xtremelabs.robolectric.internal.RealObject;
import static com.xtremelabs.robolectric.Robolectric.shadowOf_;
/**
- * Shadow implementation of {@code Point}
+ * Shadow implementation of {@code PointF}
*/
@SuppressWarnings({"UnusedDeclaration"})
@Implements(PointF.class)
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowPreferenceActivity.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowPreferenceActivity.java
index 44bd0cf59..952632ad5 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowPreferenceActivity.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowPreferenceActivity.java
@@ -1,30 +1,40 @@
package com.xtremelabs.robolectric.shadows;
+import android.os.Bundle;
+import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
-import android.widget.ListView;
import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
@Implements(PreferenceActivity.class)
public class ShadowPreferenceActivity extends ShadowListActivity {
-
private int preferencesResId = -1;
private PreferenceScreen preferenceScreen;
@Implementation
+ public void onCreate(Bundle savedInstanceState) {
+ setContentView(android.R.layout.list_content);
+ }
+
+ @Implementation
public void addPreferencesFromResource(int preferencesResId) {
this.preferencesResId = preferencesResId;
preferenceScreen = getResourceLoader().inflatePreferences(getApplicationContext(), preferencesResId);
}
-
+
public int getPreferencesResId() {
return preferencesResId;
- }
-
+ }
+
@Implementation
public PreferenceScreen getPreferenceScreen() {
return preferenceScreen;
}
+
+ @Implementation
+ public Preference findPreference(CharSequence key) {
+ return preferenceScreen.findPreference(key);
+ }
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowRect.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowRect.java
index 7a34d0d14..37bba4f0e 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowRect.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowRect.java
@@ -5,12 +5,19 @@ import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
import com.xtremelabs.robolectric.internal.RealObject;
+import java.io.PrintWriter;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
import static com.xtremelabs.robolectric.Robolectric.shadowOf_;
@Implements(Rect.class)
public class ShadowRect {
@RealObject Rect realRect;
+ private static final Pattern FLATTENED_PATTERN = Pattern.compile(
+ "(-?\\d+) (-?\\d+) (-?\\d+) (-?\\d+)");
+
public void __constructor__(int left, int top, int right, int bottom) {
realRect.left = left;
realRect.top = top;
@@ -59,6 +66,7 @@ public class ShadowRect {
}
@Implementation
+ @Override
public boolean equals(Object obj) {
if (obj == null) return false;
Object o = shadowOf_(obj);
@@ -72,54 +80,222 @@ public class ShadowRect {
}
@Implementation
+ @Override
public String toString() {
StringBuilder sb = new StringBuilder(32);
- sb.append("Rect(");
+ sb.append("Rect("); sb.append(realRect.left); sb.append(", ");
+ sb.append(realRect.top); sb.append(" - "); sb.append(realRect.right);
+ sb.append(", "); sb.append(realRect.bottom); sb.append(")");
+ return sb.toString();
+ }
+
+ @Implementation
+ public String toShortString() {
+ return toShortString(new StringBuilder(32));
+ }
+
+ public String toShortString(StringBuilder sb) {
+ sb.setLength(0);
+ sb.append('['); sb.append(realRect.left); sb.append(',');
+ sb.append(realRect.top); sb.append("]["); sb.append(realRect.right);
+ sb.append(','); sb.append(realRect.bottom); sb.append(']');
+ return sb.toString();
+ }
+
+ @Implementation
+ public String flattenToString() {
+ StringBuilder sb = new StringBuilder(32);
+ // WARNING: Do not change the format of this string, it must be
+ // preserved because Rects are saved in this flattened format.
sb.append(realRect.left);
- sb.append(", ");
+ sb.append(' ');
sb.append(realRect.top);
- sb.append(" - ");
+ sb.append(' ');
sb.append(realRect.right);
- sb.append(", ");
+ sb.append(' ');
sb.append(realRect.bottom);
- sb.append(")");
return sb.toString();
}
+
+ @Implementation
+ public static Rect unflattenFromString(String str) {
+ Matcher matcher = FLATTENED_PATTERN.matcher(str);
+ if (!matcher.matches()) {
+ return null;
+ }
+ return new Rect(Integer.parseInt(matcher.group(1)),
+ Integer.parseInt(matcher.group(2)),
+ Integer.parseInt(matcher.group(3)),
+ Integer.parseInt(matcher.group(4)));
+ }
+
+ public void printShortString(PrintWriter pw) {
+ pw.print('['); pw.print(realRect.left); pw.print(',');
+ pw.print(realRect.top); pw.print("]["); pw.print(realRect.right);
+ pw.print(','); pw.print(realRect.bottom); pw.print(']');
+ }
@Implementation
+ public final boolean isEmpty() {
+ return realRect.left >= realRect.right || realRect.top >= realRect.bottom;
+ }
+
+ @Implementation
+ public final float exactCenterX() {
+ return (realRect.left + realRect.right) * 0.5f;
+ }
+
+ @Implementation
+ public final float exactCenterY() {
+ return (realRect.top + realRect.bottom) * 0.5f;
+ }
+
+ @Implementation
+ public void setEmpty() {
+ realRect.left = realRect.right = realRect.top = realRect.bottom = 0;
+ }
+
+ @Implementation
+ public void offset(int dx, int dy) {
+ realRect.left += dx;
+ realRect.top += dy;
+ realRect.right += dx;
+ realRect.bottom += dy;
+ }
+
+ @Implementation
+ public void offsetTo(int newLeft, int newTop) {
+ realRect.right += newLeft - realRect.left;
+ realRect.bottom += newTop - realRect.top;
+ realRect.left = newLeft;
+ realRect.top = newTop;
+ }
+
+ @Implementation
+ public void inset(int dx, int dy) {
+ realRect.left += dx;
+ realRect.top += dy;
+ realRect.right -= dx;
+ realRect.bottom -= dy;
+ }
+
+ @Implementation
public boolean contains(int x, int y) {
- return x > realRect.left && x < realRect.right
- && y >= realRect.top && y <= realRect.bottom;
- }
+ return x > realRect.left && x < realRect.right
+ && y >= realRect.top && y <= realRect.bottom;
+ }
@Implementation
public boolean contains(Rect r) {
- return equals(r)
- || (contains(r.left, r.top) && contains(r.right, r.top)
- && contains(r.left, r.bottom) && contains(r.right, r.bottom));
+ return equals(r)
+ || (contains(r.left, r.top) && contains(r.right, r.top)
+ && contains(r.left, r.bottom) && contains(r.right, r.bottom));
}
-
+
@Implementation
- public static boolean intersects(Rect a, Rect b) {
- return a.left < b.right && b.left < a.right
- && a.top < b.bottom && b.top < a.bottom;
+ public static boolean intersects(Rect a, Rect b) {
+ return a.left < b.right && b.left < a.right
+ && a.top < b.bottom && b.top < a.bottom;
}
-
+
@Implementation
public boolean intersect(Rect r) {
- return intersects(realRect, r);
+ return intersects(realRect, r);
}
-
+
@Implementation
public boolean intersect(int left, int top, int right, int bottom) {
- return intersect(new Rect(left, top, right, bottom));
+ return intersect(new Rect(left, top, right, bottom));
+ }
+
+ @Implementation
+ public boolean contains(int left, int top, int right, int bottom) {
+ // check for empty first
+ return realRect.left < realRect.right && realRect.top < realRect.bottom
+ // now check for containment
+ && realRect.left <= left && realRect.top <= top
+ && realRect.right >= right && realRect.bottom >= bottom;
+ }
+
+ @Implementation
+ public boolean setIntersect(Rect a, Rect b) {
+ if (a.left < b.right && b.left < a.right
+ && a.top < b.bottom && b.top < a.bottom) {
+ realRect.left = Math.max(a.left, b.left);
+ realRect.top = Math.max(a.top, b.top);
+ realRect.right = Math.min(a.right, b.right);
+ realRect.bottom = Math.min(a.bottom, b.bottom);
+ return true;
+ }
+ return false;
+ }
+
+ @Implementation
+ public boolean intersects(int left, int top, int right, int bottom) {
+ return realRect.left < right && left < realRect.right
+ && realRect.top < bottom && top < realRect.bottom;
+ }
+
+ @Implementation
+ public void union(int left, int top, int right, int bottom) {
+ if ((left < right) && (top < bottom)) {
+ if ((realRect.left < realRect.right) && (realRect.top < realRect.bottom)) {
+ if (realRect.left > left)
+ realRect.left = left;
+ if (realRect.top > top)
+ realRect.top = top;
+ if (realRect.right < right)
+ realRect.right = right;
+ if (realRect.bottom < bottom)
+ realRect.bottom = bottom;
+ } else {
+ realRect.left = left;
+ realRect.top = top;
+ realRect.right = right;
+ realRect.bottom = bottom;
+ }
+ }
+ }
+
+ @Implementation
+ public void union(Rect r) {
+ union(r.left, r.top, r.right, r.bottom);
}
@Implementation
- public void offset(int dx, int dy) {
- realRect.left += dx;
- realRect.right += dx;
- realRect.top += dy;
- realRect.bottom += dy;
+ public void union(int x, int y) {
+ if (x < realRect.left) {
+ realRect.left = x;
+ } else if (x > realRect.right) {
+ realRect.right = x;
+ }
+ if (y < realRect.top) {
+ realRect.top = y;
+ } else if (y > realRect.bottom) {
+ realRect.bottom = y;
+ }
+ }
+
+ @Implementation
+ public void sort() {
+ if (realRect.left > realRect.right) {
+ int temp = realRect.left;
+ realRect.left = realRect.right;
+ realRect.right = temp;
+ }
+ if (realRect.top > realRect.bottom) {
+ int temp = realRect.top;
+ realRect.top = realRect.bottom;
+ realRect.bottom = temp;
+ }
+ }
+
+ public void scale(float scale) {
+ if (scale != 1.0f) {
+ realRect.left = (int) (realRect.left * scale + 0.5f);
+ realRect.top = (int) (realRect.top * scale + 0.5f);
+ realRect.right = (int) (realRect.right * scale + 0.5f);
+ realRect.bottom = (int) (realRect.bottom * scale + 0.5f);
+ }
}
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowRectF.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowRectF.java
new file mode 100644
index 000000000..4a37affaa
--- /dev/null
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowRectF.java
@@ -0,0 +1,261 @@
+package com.xtremelabs.robolectric.shadows;
+
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.util.FloatMath;
+import com.xtremelabs.robolectric.internal.Implementation;
+import com.xtremelabs.robolectric.internal.Implements;
+import com.xtremelabs.robolectric.internal.RealObject;
+
+/**
+ * Shadow implementation of {@code RectF}
+ *
+ * (lifted from Android RectF.)
+ */
+@SuppressWarnings({"UnusedDeclaration"})
+@Implements(RectF.class)
+public class ShadowRectF {
+ @RealObject private RectF realRectF;
+
+ public void __constructor__(float left, float top, float right, float bottom) {
+ realRectF.left = left;
+ realRectF.top = top;
+ realRectF.right = right;
+ realRectF.bottom = bottom;
+ }
+
+ public void __constructor__(RectF r) {
+ realRectF.left = r.left;
+ realRectF.top = r.top;
+ realRectF.right = r.right;
+ realRectF.bottom = r.bottom;
+ }
+
+ public void __constructor__(Rect r) {
+ realRectF.left = r.left;
+ realRectF.top = r.top;
+ realRectF.right = r.right;
+ realRectF.bottom = r.bottom;
+ }
+
+ @Implementation
+ public String toString() {
+ return "RectF(" + realRectF.left + ", " + realRectF.top + ", "
+ + realRectF.right + ", " + realRectF.bottom + ")";
+ }
+
+ @Implementation
+ public final boolean isEmpty() {
+ return realRectF.left >= realRectF.right || realRectF.top >= realRectF.bottom;
+ }
+
+ @Implementation
+ public final float width() {
+ return realRectF.right - realRectF.left;
+ }
+
+ @Implementation
+ public final float height() {
+ return realRectF.bottom - realRectF.top;
+ }
+
+ @Implementation
+ public final float centerX() {
+ return (realRectF.left + realRectF.right) * 0.5f;
+ }
+
+ @Implementation
+ public final float centerY() {
+ return (realRectF.top + realRectF.bottom) * 0.5f;
+ }
+
+ @Implementation
+ public void setEmpty() {
+ realRectF.left = realRectF.right = realRectF.top = realRectF.bottom = 0;
+ }
+
+ @Implementation
+ public void set(float left, float top, float right, float bottom) {
+ realRectF.left = left;
+ realRectF.top = top;
+ realRectF.right = right;
+ realRectF.bottom = bottom;
+ }
+
+ @Implementation
+ public void set(RectF src) {
+ realRectF.left = src.left;
+ realRectF.top = src.top;
+ realRectF.right = src.right;
+ realRectF.bottom = src.bottom;
+ }
+
+ @Implementation
+ public void set(Rect src) {
+ realRectF.left = src.left;
+ realRectF.top = src.top;
+ realRectF.right = src.right;
+ realRectF.bottom = src.bottom;
+ }
+
+ @Implementation
+ public void offset(float dx, float dy) {
+ realRectF.left += dx;
+ realRectF.top += dy;
+ realRectF.right += dx;
+ realRectF.bottom += dy;
+ }
+
+ @Implementation
+ public void offsetTo(float newLeft, float newTop) {
+ realRectF.right += newLeft - realRectF.left;
+ realRectF.bottom += newTop - realRectF.top;
+ realRectF.left = newLeft;
+ realRectF.top = newTop;
+ }
+
+ @Implementation
+ public void inset(float dx, float dy) {
+ realRectF.left += dx;
+ realRectF.top += dy;
+ realRectF.right -= dx;
+ realRectF.bottom -= dy;
+ }
+
+ @Implementation
+ public boolean contains(float x, float y) {
+ return realRectF.left < realRectF.right && realRectF.top < realRectF.bottom // check for empty first
+ && x >= realRectF.left && x < realRectF.right && y >= realRectF.top && y < realRectF.bottom;
+ }
+
+ @Implementation
+ public boolean contains(float left, float top, float right, float bottom) {
+ return realRectF.left < realRectF.right && realRectF.top < realRectF.bottom
+ && realRectF.left <= left && realRectF.top <= top
+ && realRectF.right >= right && realRectF.bottom >= bottom;
+ }
+
+ @Implementation
+ public boolean contains(RectF r) {
+ return realRectF.left < realRectF.right && realRectF.top < realRectF.bottom
+ && realRectF.left <= r.left && realRectF.top <= r.top
+ && realRectF.right >= r.right && realRectF.bottom >= r.bottom;
+ }
+
+ @Implementation
+ public boolean intersect(float left, float top, float right, float bottom) {
+ if (realRectF.left < right && left < realRectF.right
+ && realRectF.top < bottom && top < realRectF.bottom) {
+ if (realRectF.left < left) {
+ realRectF.left = left;
+ }
+ if (realRectF.top < top) {
+ realRectF.top = top;
+ }
+ if (realRectF.right > right) {
+ realRectF.right = right;
+ }
+ if (realRectF.bottom > bottom) {
+ realRectF.bottom = bottom;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Implementation
+ public boolean intersect(RectF r) {
+ return intersect(r.left, r.top, r.right, r.bottom);
+ }
+
+ @Implementation
+ public boolean setIntersect(RectF a, RectF b) {
+ if (a.left < b.right && b.left < a.right
+ && a.top < b.bottom && b.top < a.bottom) {
+ realRectF.left = Math.max(a.left, b.left);
+ realRectF.top = Math.max(a.top, b.top);
+ realRectF.right = Math.min(a.right, b.right);
+ realRectF.bottom = Math.min(a.bottom, b.bottom);
+ return true;
+ }
+ return false;
+ }
+
+ @Implementation
+ public boolean intersects(float left, float top, float right, float bottom) {
+ return realRectF.left < right && left < realRectF.right
+ && realRectF.top < bottom && top < realRectF.bottom;
+ }
+
+ @Implementation
+ public static boolean intersects(RectF a, RectF b) {
+ return a.left < b.right && b.left < a.right
+ && a.top < b.bottom && b.top < a.bottom;
+ }
+
+ @Implementation
+ public void round(Rect dst) {
+ dst.set(Math.round(realRectF.left), Math.round(realRectF.top),
+ Math.round(realRectF.right), Math.round(realRectF.bottom));
+ }
+
+ @Implementation
+ public void roundOut(Rect dst) {
+ dst.set((int) FloatMath.floor(realRectF.left), (int) FloatMath.floor(realRectF.top),
+ (int) FloatMath.ceil(realRectF.right), (int) FloatMath.ceil(realRectF.bottom));
+ }
+
+ @Implementation
+ public void union(float left, float top, float right, float bottom) {
+ if ((left < right) && (top < bottom)) {
+ if ((realRectF.left < realRectF.right) && (realRectF.top < realRectF.bottom)) {
+ if (realRectF.left > left)
+ realRectF.left = left;
+ if (realRectF.top > top)
+ realRectF.top = top;
+ if (realRectF.right < right)
+ realRectF.right = right;
+ if (realRectF.bottom < bottom)
+ realRectF.bottom = bottom;
+ } else {
+ realRectF.left = left;
+ realRectF.top = top;
+ realRectF.right = right;
+ realRectF.bottom = bottom;
+ }
+ }
+ }
+
+ @Implementation
+ public void union(RectF r) {
+ union(r.left, r.top, r.right, r.bottom);
+ }
+
+ @Implementation
+ public void union(float x, float y) {
+ if (x < realRectF.left) {
+ realRectF.left = x;
+ } else if (x > realRectF.right) {
+ realRectF.right = x;
+ }
+ if (y < realRectF.top) {
+ realRectF.top = y;
+ } else if (y > realRectF.bottom) {
+ realRectF.bottom = y;
+ }
+ }
+
+ @Implementation
+ public void sort() {
+ if (realRectF.left > realRectF.right) {
+ float temp = realRectF.left;
+ realRectF.left = realRectF.right;
+ realRectF.right = temp;
+ }
+ if (realRectF.top > realRectF.bottom) {
+ float temp = realRectF.top;
+ realRectF.top = realRectF.bottom;
+ realRectF.bottom = temp;
+ }
+ }
+}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowResources.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowResources.java
index 5e75d45f6..82f9e87db 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowResources.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowResources.java
@@ -1,6 +1,7 @@
package com.xtremelabs.robolectric.shadows;
import android.content.res.AssetManager;
+import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -18,17 +19,17 @@ import com.xtremelabs.robolectric.internal.Implements;
import com.xtremelabs.robolectric.internal.RealObject;
import com.xtremelabs.robolectric.res.ResourceExtractor;
import com.xtremelabs.robolectric.res.ResourceLoader;
-
import java.io.InputStream;
import java.util.Locale;
+import static com.xtremelabs.robolectric.Robolectric.getShadowApplication;
import static com.xtremelabs.robolectric.Robolectric.newInstanceOf;
import static com.xtremelabs.robolectric.Robolectric.shadowOf;
/**
* Shadow of {@code Resources} that simulates the loading of resources
*
- * @see com.xtremelabs.robolectric.RobolectricTestRunner#RobolectricTestRunner(Class, String, String)
+ * @see com.xtremelabs.robolectric.RobolectricTestRunner#RobolectricTestRunner(Class)
*/
@SuppressWarnings({"UnusedDeclaration"})
@Implements(Resources.class)
@@ -38,6 +39,8 @@ public class ShadowResources {
private DisplayMetrics displayMetrics;
private Display display;
+ private static Resources system = null;
+
static Resources bind(Resources resources, ResourceLoader resourceLoader) {
ShadowResources shadowResources = shadowOf(resources);
if (shadowResources.resourceLoader != null) throw new RuntimeException("ResourceLoader already set!");
@@ -49,6 +52,21 @@ public class ShadowResources {
Resources realResources;
private ResourceLoader resourceLoader;
+ public ShadowResources() {
+ Configuration configuration = new Configuration();
+ configuration.setToDefaults();
+ setConfiguration(configuration);
+ }
+
+ /**
+ * Non-Android accessor that sets the value to be returned by {@link #getConfiguration()}
+ *
+ * @param configuration Configuration instance to set on this Resources obj
+ */
+ public void setConfiguration(Configuration configuration) {
+ this.configuration = configuration;
+ }
+
@Implementation
public int getIdentifier(String name, String defType, String defPackage) {
Integer index = 0;
@@ -68,6 +86,11 @@ public class ShadowResources {
}
@Implementation
+ public ColorStateList getColorStateList(int id) {
+ return new ColorStateList(null, null);
+ }
+
+ @Implementation
public Configuration getConfiguration() {
if (configuration == null) {
configuration = new Configuration();
@@ -221,11 +244,17 @@ public class ShadowResources {
@Implementation
public final android.content.res.Resources.Theme newTheme() {
- return newInstanceOf(Resources.Theme.class);
+ return inject(realResources, newInstanceOf(Resources.Theme.class));
}
@Implements(Resources.Theme.class)
- public static class ShadowTheme {
+ public static class ShadowTheme implements UsesResources {
+ protected Resources resources;
+
+ public void injectResources(Resources resources) {
+ this.resources = resources;
+ }
+
@Implementation
public TypedArray obtainStyledAttributes(int[] attrs) {
return obtainStyledAttributes(0, attrs);
@@ -238,8 +267,41 @@ public class ShadowResources {
@Implementation
public TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
- return newInstanceOf(TypedArray.class);
+ return inject(resources, newInstanceOf(TypedArray.class));
}
}
+ @Implementation
+ public static Resources getSystem() {
+ if (system == null) {
+ try {
+ initSystemResources();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ return system;
+ }
+
+ public static <T> T inject(Resources resources, T instance) {
+ Object shadow = Robolectric.shadowOf_(instance);
+ if (shadow instanceof UsesResources) {
+ ((UsesResources) shadow).injectResources(resources);
+ }
+ return instance;
+ }
+
+
+ /**
+ * Creates system resource loader from a copy of the application resource loader. Sets
+ * a flag to exclude local resources on initialization.
+ */
+ private static void initSystemResources() throws Exception {
+ final ResourceLoader appResourceLoader = getShadowApplication().getResourceLoader();
+ final ResourceLoader systemResourceLoader = new ResourceLoader(appResourceLoader);
+ systemResourceLoader.setSystem(true);
+ system = ShadowResources.bind(new Resources(null, null, null), systemResourceLoader);
+ }
+
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowSQLiteCloseable.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowSQLiteCloseable.java
index 52a0df5bd..9992b1078 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowSQLiteCloseable.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowSQLiteCloseable.java
@@ -13,8 +13,8 @@ import com.xtremelabs.robolectric.internal.Implements;
@Implements(SQLiteClosable.class)
public class ShadowSQLiteCloseable {
- @Implementation
- public void close() {
- }
-
-}
+ @Implementation
+ public void close() {
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowSensorManager.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowSensorManager.java
index 99bba883a..6ce7b9ddb 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowSensorManager.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowSensorManager.java
@@ -4,14 +4,13 @@ import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
-import android.os.Handler;
-
import com.xtremelabs.robolectric.Robolectric;
import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
import java.util.ArrayList;
-import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
@Implements(SensorManager.class)
@@ -20,7 +19,23 @@ public class ShadowSensorManager {
private ArrayList<SensorEventListener> listeners = new ArrayList<SensorEventListener>();
public boolean forceListenersToFail = false;
-
+
+ private final Map<Integer, Sensor> sensorMap = new HashMap<Integer, Sensor>();
+
+ /**
+ * Provide a Sensor for the indicated sensor type.
+ * @param sensorType from Sensor constants
+ * @param sensor Sensor instance
+ */
+ public void addSensor(int sensorType, Sensor sensor) {
+ sensorMap.put(sensorType, sensor);
+ }
+
+ @Implementation
+ public Sensor getDefaultSensor(int type) {
+ return sensorMap.get(type);
+ }
+
@Implementation
public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate) {
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowService.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowService.java
index 74a9cc1ca..b428d35bd 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowService.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowService.java
@@ -63,6 +63,9 @@ public class ShadowService extends ShadowContextWrapper {
public void stopForeground(boolean removeNotification) {
foregroundStopped = true;
notificationShouldRemoved = removeNotification;
+ if (removeNotification) {
+ lastForegroundNotification = null;
+ }
}
public Notification getLastForegroundNotification() {
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowSpannableStringBuilder.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowSpannableStringBuilder.java
index 2a28c9e6f..dc9532ada 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowSpannableStringBuilder.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowSpannableStringBuilder.java
@@ -27,8 +27,13 @@ public class ShadowSpannableStringBuilder implements CharSequence {
}
@Implementation
- public Editable replace(int st, int en, CharSequence text) {
- builder.replace(st, en, text.toString());
+ public SpannableStringBuilder replace(int start, int end, CharSequence tb) {
+ return replace(start, end, tb, 0, tb.length());
+ }
+
+ @Implementation
+ public SpannableStringBuilder replace(int start, int end, CharSequence tb, int tbStart, int tbEnd) {
+ builder.replace(start, end, tb.subSequence(tbStart, tbEnd).toString());
return realSpannableStringBuilder;
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowSpannedString.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowSpannedString.java
new file mode 100644
index 000000000..f18e69600
--- /dev/null
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowSpannedString.java
@@ -0,0 +1,29 @@
+package com.xtremelabs.robolectric.shadows;
+
+import android.text.SpannedString;
+import com.xtremelabs.robolectric.internal.Implementation;
+import com.xtremelabs.robolectric.internal.Implements;
+
+@Implements(SpannedString.class)
+public class ShadowSpannedString {
+
+ private CharSequence charSequence;
+
+ public void __constructor__(CharSequence charSequence) {
+ this.charSequence = charSequence;
+ }
+
+ @Override @Implementation
+ public String toString() {
+ return charSequence.toString();
+ }
+
+ @Implementation
+ public static SpannedString valueOf(CharSequence charSequence) {
+ if (charSequence instanceof SpannedString) {
+ return (SpannedString) charSequence;
+ }
+ return new SpannedString(charSequence);
+ }
+
+}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowTextUtils.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowTextUtils.java
index cd74ae54b..cb5e1f85a 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowTextUtils.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowTextUtils.java
@@ -1,5 +1,6 @@
package com.xtremelabs.robolectric.shadows;
+import android.text.TextPaint;
import android.text.TextUtils;
import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
@@ -54,11 +55,18 @@ public class ShadowTextUtils {
@Implementation
public static String[] split(String text, String expression) {
- if(text.length() == 0) {
- return new String[]{};
- }
-
- return text.split(expression);
+ if(text.length() == 0) {
+ return new String[]{};
+ }
+
+ return text.split(expression);
+ }
+
+ @Implementation
+ public static CharSequence ellipsize(CharSequence text,
+ TextPaint p,
+ float avail, TextUtils.TruncateAt where) {
+ return text;
}
@Implementation
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowTextView.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowTextView.java
index 3260fe0c3..afb28685d 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowTextView.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowTextView.java
@@ -58,6 +58,7 @@ public class ShadowTextView extends ShadowView {
@Override
public void applyAttributes() {
super.applyAttributes();
+ applyHintAttribute();
applyTextAttribute();
applyTextColorAttribute();
applyHintAttribute();
@@ -256,12 +257,23 @@ public class ShadowTextView extends ShadowView {
if (compoundDrawablesImpl == null) {
return new Drawable[]{null, null, null, null};
}
- return new Drawable[]{
- compoundDrawablesImpl.leftDrawable,
- compoundDrawablesImpl.topDrawable,
- compoundDrawablesImpl.rightDrawable,
- compoundDrawablesImpl.bottomDrawable
- };
+
+ if(compoundDrawablesImpl.left == 0 && compoundDrawablesImpl.right == 0 &&
+ compoundDrawablesImpl.top == 0 && compoundDrawablesImpl.bottom == 0) {
+ return new Drawable[]{
+ compoundDrawablesImpl.leftDrawable,
+ compoundDrawablesImpl.topDrawable,
+ compoundDrawablesImpl.rightDrawable,
+ compoundDrawablesImpl.bottomDrawable
+ };
+ } else {
+ return new Drawable[]{
+ buildDrawable(compoundDrawablesImpl.left),
+ buildDrawable(compoundDrawablesImpl.top),
+ buildDrawable(compoundDrawablesImpl.right),
+ buildDrawable(compoundDrawablesImpl.bottom)
+ };
+ }
}
@Implementation
@@ -314,7 +326,6 @@ public class ShadowTextView extends ShadowView {
this.gravity = gravity;
}
-
@Implementation
public int getImeOptions() {
return imeOptions;
@@ -555,6 +566,11 @@ public class ShadowTextView extends ShadowView {
}
public static class CompoundDrawables {
+ public int left;
+ public int top;
+ public int right;
+ public int bottom;
+
public Drawable leftDrawable;
public Drawable topDrawable;
public Drawable rightDrawable;
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowTypedArray.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowTypedArray.java
index 2781ac0c7..74054be26 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowTypedArray.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowTypedArray.java
@@ -2,7 +2,6 @@ package com.xtremelabs.robolectric.shadows;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import com.xtremelabs.robolectric.Robolectric;
import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
@@ -11,12 +10,17 @@ import java.util.List;
@SuppressWarnings({"UnusedDeclaration"})
@Implements(TypedArray.class)
-public class ShadowTypedArray {
+public class ShadowTypedArray implements UsesResources {
+ private Resources resources;
private List<Object> values = new ArrayList<Object>();
+ public void injectResources(Resources resources) {
+ this.resources = resources;
+ }
+
@Implementation
public Resources getResources() {
- return Robolectric.application.getResources();
+ return resources;
}
public void add(Object attributeValue) {
@@ -27,4 +31,24 @@ public class ShadowTypedArray {
public java.lang.String getString(int index) {
return (String) values.get(index);
}
+
+ @Implementation
+ public int getInt(int index, int defValue) {
+ return defValue;
+ }
+
+ @Implementation
+ public int getInteger(int index, int defValue) {
+ return defValue;
+ }
+
+ @Implementation
+ public int getResourceId(int index, int defValue) {
+ return defValue;
+ }
+
+ @Implementation
+ public float getDimension(int index, float defValue) {
+ return defValue;
+ }
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowView.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowView.java
index cd3972a96..9b1f828fb 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowView.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowView.java
@@ -3,9 +3,12 @@ package com.xtremelabs.robolectric.shadows;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.Point;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
import android.util.AttributeSet;
import android.view.*;
import android.view.View.MeasureSpec;
@@ -14,7 +17,7 @@ import com.xtremelabs.robolectric.Robolectric;
import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
import com.xtremelabs.robolectric.internal.RealObject;
-
+import com.xtremelabs.robolectric.util.ReflectionUtil;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -34,6 +37,9 @@ import static com.xtremelabs.robolectric.Robolectric.shadowOf;
@SuppressWarnings({"UnusedDeclaration"})
@Implements(View.class)
public class ShadowView {
+ // This is dumb, we should have a Robolectric-wide way of warning about weird states. todo [xw]
+ public static boolean strict = false;
+
@RealObject
protected View realView;
@@ -41,6 +47,7 @@ public class ShadowView {
ShadowView parent;
protected Context context;
private boolean selected;
+ private boolean pressed;
private View.OnClickListener onClickListener;
private View.OnLongClickListener onLongClickListener;
private Object tag;
@@ -83,6 +90,7 @@ public class ShadowView {
private float translationX = 0.0f;
private float translationY = 0.0f;
private float alpha = 1.0f;
+ private boolean attachedToWindow;
public void __constructor__(Context context) {
__constructor__(context, null);
@@ -248,6 +256,40 @@ public class ShadowView {
return context.getResources();
}
+ /**
+ * Build drawable, either LayerDrawable or BitmapDrawable.
+ *
+ * @param resourceId Resource id
+ * @return Drawable
+ */
+ protected Drawable buildDrawable(int resourceId) {
+ if (isDrawableXml(resourceId)) {
+ int[] resourceIds = shadowOf(Robolectric.application)
+ .getResourceLoader().getDrawableIds(resourceId);
+
+ Drawable[] drawables = new Drawable[resourceIds.length];
+
+ for (int i = 0; i < resourceIds.length; i++) {
+ drawables[i] = buildDrawable(resourceIds[i]);
+ }
+
+ return new LayerDrawable(drawables);
+ } else {
+ return new BitmapDrawable(BitmapFactory.decodeResource(getResources(), resourceId));
+ }
+ }
+
+ /**
+ * Does the resource id point to xml resource.
+ *
+ * @param resourceId Resource id
+ * @return Boolean
+ */
+ protected boolean isDrawableXml(int resourceId) {
+ return shadowOf(Robolectric.application).getResourceLoader()
+ .isDrawableXml(resourceId);
+ }
+
@Implementation
public void setBackgroundResource(int backgroundResourceId) {
this.backgroundResourceId = backgroundResourceId;
@@ -309,6 +351,16 @@ public class ShadowView {
}
@Implementation
+ public void setPressed(boolean pressed) {
+ this.pressed = pressed;
+ }
+
+ @Implementation
+ public boolean isPressed() {
+ return this.pressed;
+ }
+
+ @Implementation
public boolean isEnabled() {
return this.enabled;
}
@@ -420,14 +472,28 @@ public class ShadowView {
throw new RuntimeException(e);
}
}
-
+
+ @Implementation
+ public void draw(android.graphics.Canvas canvas) {
+ if (background != null) {
+ shadowOf(canvas).appendDescription("background:");
+ background.draw(canvas);
+ }
+ }
+
@Implementation
public final void layout(int l, int t, int r, int b) {
- left = l;
- top = t;
- right = r;
- bottom = b;
-// todo: realView.onLayout();
+ if (l != left || r != right || t != top || b != bottom) {
+ left = l;
+ top = t;
+ right = r;
+ bottom = b;
+
+ realView.invalidate();
+ ReflectionUtil.invoke(realView, "onLayout",
+ new Class<?>[]{Boolean.TYPE, Integer.TYPE, Integer.TYPE, Integer.TYPE, Integer.TYPE},
+ true, l, t, r, b);
+ }
}
@Implementation
@@ -1045,4 +1111,42 @@ public class ShadowView {
public TouchDelegate getTouchDelegate() {
return touchDelegate;
}
+
+ @Implementation
+ public void onAttachedToWindow() {
+ if (strict && attachedToWindow) throw new IllegalStateException("already attached!");
+ attachedToWindow = true;
+ }
+
+ @Implementation
+ public void onDetachedFromWindow() {
+ if (strict && !attachedToWindow) throw new IllegalStateException("not attached!");
+ attachedToWindow = false;
+ }
+
+ public boolean isAttachedToWindow() {
+ return attachedToWindow;
+ }
+
+ public void callOnAttachedToWindow() {
+ invokeReflectively("onAttachedToWindow");
+ }
+
+ public void callOnDetachedFromWindow() {
+ invokeReflectively("onDetachedFromWindow");
+ }
+
+ private void invokeReflectively(String methodName) {
+ try {
+ Method method = View.class.getDeclaredMethod(methodName);
+ method.setAccessible(true);
+ method.invoke(realView);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowViewAnimator.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowViewAnimator.java
index 52a56d3b8..d52db9fd8 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowViewAnimator.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowViewAnimator.java
@@ -2,41 +2,43 @@ package com.xtremelabs.robolectric.shadows;
import android.view.View;
import android.widget.ViewAnimator;
-
import com.xtremelabs.robolectric.internal.Implementation;
import com.xtremelabs.robolectric.internal.Implements;
+/**
+ * Shadow of {@link android.widget.ViewAnimator}
+ */
@Implements(ViewAnimator.class)
-public class ShadowViewAnimator extends ShadowFrameLayout {
- private int mWhichChild = 0;
+public class ShadowViewAnimator extends ShadowViewGroup {
- @Implementation
- public void showNext() {
- setDisplayedChild(mWhichChild + 1);
- }
+ private int currentChild = 0;
@Implementation
- public void showPrevious() {
- setDisplayedChild(mWhichChild - 1);
+ public int getDisplayedChild() {
+ return currentChild;
}
@Implementation
public void setDisplayedChild(int whichChild) {
- mWhichChild = whichChild;
- if (whichChild >= getChildCount()) {
- mWhichChild = 0;
- } else if (whichChild < 0) {
- mWhichChild = getChildCount() - 1;
+ currentChild = whichChild;
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ View child = getChildAt(i);
+ child.setVisibility(i == whichChild ? View.VISIBLE : View.GONE);
}
}
@Implementation
- public int getDisplayedChild() {
- return mWhichChild;
+ public View getCurrentView() {
+ return getChildAt(getDisplayedChild());
}
@Implementation
- public View getCurrentView() {
- return getChildAt(mWhichChild);
+ public void showNext() {
+ setDisplayedChild((getDisplayedChild() + 1) % getChildCount());
+ }
+
+ @Implementation
+ public void showPrevious() {
+ setDisplayedChild(getDisplayedChild() == 0 ? getChildCount() - 1 : getDisplayedChild() - 1);
}
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowViewGroup.java b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowViewGroup.java
index 93669fecc..35d3294f2 100644
--- a/src/main/java/com/xtremelabs/robolectric/shadows/ShadowViewGroup.java
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/ShadowViewGroup.java
@@ -71,6 +71,7 @@ public class ShadowViewGroup extends ShadowView {
children.add(index, child);
}
shadowOf(child).parent = this;
+ addedChild(child);
}
@Implementation
@@ -90,6 +91,15 @@ public class ShadowViewGroup extends ShadowView {
}
@Implementation
+ public void removeView(View child) {
+ // Android's ViewGroup ignores the child when it is null. Do the same here.
+ if (child == null) return;
+ shadowOf(child).parent = null;
+ children.remove(child);
+ removedChild(child);
+ }
+
+ @Implementation
public int indexOfChild(View child) {
int count = getChildCount();
for (int i = 0; i < count; i++) {
@@ -107,21 +117,23 @@ public class ShadowViewGroup extends ShadowView {
@Implementation
public View getChildAt(int index) {
- if( index >= children.size() ){ return null; }
- return children.get(index);
+ return isValidIndex(index) ? children.get(index) : null;
}
@Implementation
public void removeAllViews() {
for (View child : children) {
shadowOf(child).parent = null;
+ removedChild(child);
}
children.clear();
}
@Implementation
public void removeViewAt(int position) {
- shadowOf(children.remove(position)).parent = null;
+ View child = children.remove(position);
+ shadowOf(child).parent = null;
+ removedChild(child);
}
@Override
@@ -200,15 +212,31 @@ public class ShadowViewGroup extends ShadowView {
public AnimationListener getLayoutAnimationListener() {
return animListener;
}
-
+
+ @Override
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ for (int i = 0; i < getChildCount(); i++) {
+ shadowOf(getChildAt(i)).callOnAttachedToWindow();
+ }
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ for (int i = 0; i < getChildCount(); i++) {
+ shadowOf(getChildAt(i)).callOnDetachedFromWindow();
+ }
+ super.onDetachedFromWindow();
+ }
+
@Implementation
public void setLayoutAnimation(LayoutAnimationController layoutAnim) {
- this.layoutAnim = layoutAnim;
+ this.layoutAnim = layoutAnim;
}
-
+
@Implementation
public LayoutAnimationController getLayoutAnimation() {
- return layoutAnim;
+ return layoutAnim;
}
@Implementation
@@ -219,4 +247,21 @@ public class ShadowViewGroup extends ShadowView {
public boolean getDisallowInterceptTouchEvent() {
return disallowInterceptTouchEvent;
}
+
+ protected void addedChild(View child) {
+ if (isAttachedToWindow()) shadowOf(child).callOnAttachedToWindow();
+ setChildLayoutParams(child);
+ }
+
+ protected void removedChild(View child) {
+ if (isAttachedToWindow()) shadowOf(child).callOnDetachedFromWindow();
+ }
+
+ protected void setChildLayoutParams(View child) {
+ shadowOf(child).setLayoutParams(new ViewGroup.LayoutParams(0, 0));
+ }
+
+ private boolean isValidIndex(int i) {
+ return i >= 0 && i < children.size();
+ }
}
diff --git a/src/main/java/com/xtremelabs/robolectric/shadows/UsesResources.java b/src/main/java/com/xtremelabs/robolectric/shadows/UsesResources.java
new file mode 100644
index 000000000..f44383287
--- /dev/null
+++ b/src/main/java/com/xtremelabs/robolectric/shadows/UsesResources.java
@@ -0,0 +1,10 @@
+package com.xtremelabs.robolectric.shadows;
+
+import android.content.res.Resources;
+
+/**
+ * Indicates that this shadow class would like to have a Resources instance injected at creation.
+ */
+public interface UsesResources {
+ void injectResources(Resources resources);
+}
diff --git a/src/main/java/com/xtremelabs/robolectric/tester/android/content/TestSharedPreferences.java b/src/main/java/com/xtremelabs/robolectric/tester/android/content/TestSharedPreferences.java
index 21f2e3ade..ef0e7a9f4 100644
--- a/src/main/java/com/xtremelabs/robolectric/tester/android/content/TestSharedPreferences.java
+++ b/src/main/java/com/xtremelabs/robolectric/tester/android/content/TestSharedPreferences.java
@@ -2,7 +2,11 @@ package com.xtremelabs.robolectric.tester.android.content;
import android.content.SharedPreferences;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
public class TestSharedPreferences implements SharedPreferences {
@@ -172,14 +176,16 @@ public class TestSharedPreferences implements SharedPreferences {
commit();
}
- @Override
- public Editor putStringSet(String key, Set<String> values) {
- return this;
- }
+ @Override
+ public Editor putStringSet(String key, Set<String> strings) {
+ editsThatNeedCommit.put(key, strings);
+ editsThatNeedRemove.remove(key);
+ return this;
+ }
}
- @Override
- public Set<String> getStringSet(String key, Set<String> defValues) {
- return null;
- }
+ @Override
+ public Set<String> getStringSet(String key, Set<String> strings) {
+ return (Set<String>) getValue(key, strings);
+ }
}
diff --git a/src/main/java/com/xtremelabs/robolectric/tester/android/content/pm/StubPackageManager.java b/src/main/java/com/xtremelabs/robolectric/tester/android/content/pm/StubPackageManager.java
index 7f4928285..884191910 100644
--- a/src/main/java/com/xtremelabs/robolectric/tester/android/content/pm/StubPackageManager.java
+++ b/src/main/java/com/xtremelabs/robolectric/tester/android/content/pm/StubPackageManager.java
@@ -3,17 +3,7 @@ package com.xtremelabs.robolectric.tester.android.content.pm;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.FeatureInfo;
-import android.content.pm.InstrumentationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PermissionGroupInfo;
-import android.content.pm.PermissionInfo;
-import android.content.pm.ProviderInfo;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
+import android.content.pm.*;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
@@ -291,8 +281,8 @@ public class StubPackageManager extends PackageManager {
}
@Override public void verifyPendingInstall(int id, int verificationCode) {
- }
+ }
@Override public void setInstallerPackageName(String targetPackage, String installerPackageName) {
- }
+ }
}
diff --git a/src/main/java/com/xtremelabs/robolectric/tester/android/database/TestCursor.java b/src/main/java/com/xtremelabs/robolectric/tester/android/database/TestCursor.java
index 84a3d85b1..b1af0daf0 100644
--- a/src/main/java/com/xtremelabs/robolectric/tester/android/database/TestCursor.java
+++ b/src/main/java/com/xtremelabs/robolectric/tester/android/database/TestCursor.java
@@ -199,10 +199,10 @@ public class TestCursor implements Cursor {
throw new UnsupportedOperationException();
}
- @Override
+ @Override
public int getType(int columnIndex) {
throw new UnsupportedOperationException();
- }
+ }
/**
* Mimics ContentResolver.query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
diff --git a/src/main/java/com/xtremelabs/robolectric/tester/android/util/TestAttributeSet.java b/src/main/java/com/xtremelabs/robolectric/tester/android/util/TestAttributeSet.java
index e59ab4ef1..cd617d33b 100644
--- a/src/main/java/com/xtremelabs/robolectric/tester/android/util/TestAttributeSet.java
+++ b/src/main/java/com/xtremelabs/robolectric/tester/android/util/TestAttributeSet.java
@@ -72,10 +72,12 @@ public class TestAttributeSet implements AttributeSet {
public int getAttributeIntValue(String namespace, String attribute, int defaultValue) {
String value = getAttributeValueInMap(namespace, attribute);
- if (attrResourceLoader.hasAttributeFor(viewClass, "xxx", attribute)) {
- value = attrResourceLoader.convertValueToEnum(viewClass, "xxx", attribute, value);
+ if (attrResourceLoader.hasAttributeFor(viewClass, namespace, attribute)) {
+ value = attrResourceLoader.convertValueToEnum(viewClass, namespace, attribute, value);
}
+ if (value != null && value.startsWith("0x")) value = value.substring(2);
+
return (value != null) ? Integer.valueOf(value) : defaultValue;
}
@@ -123,11 +125,6 @@ public class TestAttributeSet implements AttributeSet {
@Override
public float getAttributeFloatValue(String namespace, String attribute, float defaultValue) {
String value = getAttributeValueInMap(namespace, attribute);
-
- if (attrResourceLoader.hasAttributeFor(viewClass, "xxx", attribute)) {
- value = attrResourceLoader.convertValueToEnum(viewClass, "xxx", attribute, value);
- }
-
return (value != null) ? Float.valueOf(value) : defaultValue;
}
@@ -141,8 +138,7 @@ public class TestAttributeSet implements AttributeSet {
throw new UnsupportedOperationException();
}
- @Override
- public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) {
+ @Override public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) {
String value = getAttributeValueInMap(namespace, attribute);
Integer resourceId = defaultValue;
if (value != null) {
@@ -155,7 +151,9 @@ public class TestAttributeSet implements AttributeSet {
public int getAttributeResourceValue(int resourceId, int defaultValue) {
String attrName = resourceExtractor.getResourceName(resourceId);
String value = getAttributeValueInMap(null, attrName);
- return (value == null) ? defaultValue : resourceExtractor.getResourceId(value);
+ Integer extracted = null;
+ if (value != null) extracted = resourceExtractor.getResourceId(value);
+ return (extracted == null) ? defaultValue : extracted;
}
@Override
@@ -188,9 +186,17 @@ public class TestAttributeSet implements AttributeSet {
throw new UnsupportedOperationException();
}
- @Override
- public int getStyleAttribute() {
- throw new UnsupportedOperationException();
+ @Override public int getStyleAttribute() {
+ String value = attributes.get("style");
+ if (value == null) {
+ // Per Android specifications, return 0 if there is no style.
+ return 0;
+ }
+ if (resourceExtractor != null) {
+ Integer i = resourceExtractor.getResourceId(value);
+ if (i != null) return i;
+ }
+ return 0;
}
public void validateStrictI18n() {
diff --git a/src/main/java/com/xtremelabs/robolectric/tester/android/view/TestMenuItem.java b/src/main/java/com/xtremelabs/robolectric/tester/android/view/TestMenuItem.java
index 4afc9fb78..d1ad2daaa 100644
--- a/src/main/java/com/xtremelabs/robolectric/tester/android/view/TestMenuItem.java
+++ b/src/main/java/com/xtremelabs/robolectric/tester/android/view/TestMenuItem.java
@@ -1,11 +1,9 @@
package com.xtremelabs.robolectric.tester.android.view;
-import com.xtremelabs.robolectric.Robolectric;
-
-import android.app.Application;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.view.*;
+import com.xtremelabs.robolectric.Robolectric;
public class TestMenuItem implements MenuItem {
diff --git a/src/main/java/com/xtremelabs/robolectric/tester/android/view/TestWindow.java b/src/main/java/com/xtremelabs/robolectric/tester/android/view/TestWindow.java
index d222fe7e9..fa1b1a067 100644
--- a/src/main/java/com/xtremelabs/robolectric/tester/android/view/TestWindow.java
+++ b/src/main/java/com/xtremelabs/robolectric/tester/android/view/TestWindow.java
@@ -1,21 +1,17 @@
package com.xtremelabs.robolectric.tester.android.view;
+import android.R;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
-import android.view.InputQueue;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.SurfaceHolder;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowManager;
+import android.view.*;
+import android.widget.FrameLayout;
import com.xtremelabs.robolectric.Robolectric;
+import static com.xtremelabs.robolectric.Robolectric.shadowOf;
+
public class TestWindow extends Window {
public int flags;
public int requestedFeatureId;
@@ -23,6 +19,7 @@ public class TestWindow extends Window {
public int featureDrawableResourceResId;
public int softInputMode;
private TestWindowManager windowManager;
+ private View contentView;
public TestWindow(Context context) {
super(context);
@@ -58,15 +55,21 @@ public class TestWindow extends Window {
}
@Override public void setContentView(int layoutResID) {
+ setContentView(getLayoutInflater().inflate(layoutResID, null));
}
@Override public void setContentView(View view) {
+ if (contentView != null) shadowOf(contentView).callOnDetachedFromWindow();
+ contentView = view;
+ if (contentView != null) shadowOf(contentView).callOnAttachedToWindow();
}
@Override public void setContentView(View view, ViewGroup.LayoutParams params) {
+ setContentView(view);
}
@Override public void addContentView(View view, ViewGroup.LayoutParams params) {
+ setContentView(view);
}
@Override public View getCurrentFocus() {
@@ -74,7 +77,7 @@ public class TestWindow extends Window {
}
@Override public LayoutInflater getLayoutInflater() {
- return null;
+ return LayoutInflater.from(Robolectric.application);
}
@Override public void setTitle(CharSequence title) {
@@ -92,6 +95,10 @@ public class TestWindow extends Window {
@Override public void togglePanel(int featureId, KeyEvent event) {
}
+ @Override
+ public void invalidatePanelMenu(int i) {
+ }
+
@Override public boolean performPanelShortcut(int featureId, int keyCode, KeyEvent event, int flags) {
return false;
}
@@ -145,14 +152,35 @@ public class TestWindow extends Window {
return false;
}
+ @Override
+ public boolean superDispatchGenericMotionEvent(MotionEvent motionEvent) {
+ return false;
+ }
+
@Override public View getDecorView() {
- return new View(Robolectric.application);
+ final FrameLayout decorView = new FrameLayout(Robolectric.application);
+
+ // On a typical Android device you can call:
+ // myWindow.getDecorView().findViewById(android.R.content)
+ final FrameLayout contentWrapper = new FrameLayout(Robolectric.application);
+ contentWrapper.setId(R.id.content);
+
+ decorView.addView(contentWrapper);
+ if (contentView != null) {
+ contentWrapper.addView(contentView);
+ }
+ return decorView;
}
@Override public View peekDecorView() {
return null;
}
+ @Override
+ public View findViewById(int id) {
+ return getDecorView().findViewById(id);
+ }
+
@Override public Bundle saveHierarchyState() {
return null;
}
@@ -184,14 +212,7 @@ public class TestWindow extends Window {
this.softInputMode = softInputMode;
}
- @Override public void invalidatePanelMenu(int featureId) {
- }
-
@Override public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
return false;
}
-
- @Override public boolean superDispatchGenericMotionEvent(MotionEvent event) {
- return false;
- }
}
diff --git a/src/main/java/com/xtremelabs/robolectric/tester/org/apache/http/FakeHttpLayer.java b/src/main/java/com/xtremelabs/robolectric/tester/org/apache/http/FakeHttpLayer.java
index 67e5441dc..257e4e749 100644
--- a/src/main/java/com/xtremelabs/robolectric/tester/org/apache/http/FakeHttpLayer.java
+++ b/src/main/java/com/xtremelabs/robolectric/tester/org/apache/http/FakeHttpLayer.java
@@ -26,6 +26,7 @@ public class FakeHttpLayer {
HttpResponse defaultHttpResponse;
private HttpResponse defaultResponse;
private boolean interceptHttpRequests = true;
+ private boolean logHttpRequests = false;
public HttpRequestInfo getLastSentHttpRequestInfo() {
List<HttpRequestInfo> requestInfos = Robolectric.getFakeHttpLayer().getSentHttpRequestInfos();
@@ -101,12 +102,20 @@ public class FakeHttpLayer {
}
}
+ System.err.println("Unexpected HTTP call " + httpRequest.getRequestLine());
+
return defaultHttpResponse;
}
public HttpResponse emulateRequest(HttpHost httpHost, HttpRequest httpRequest, HttpContext httpContext, RequestDirector requestDirector) throws HttpException, IOException {
+ if (logHttpRequests) {
+ System.out.println(" <-- " + httpRequest.getRequestLine());
+ }
HttpResponse httpResponse = findResponse(httpRequest);
-
+ if (logHttpRequests) {
+ System.out.println(" --> " + (httpResponse == null ? null : httpResponse.getStatusLine().getStatusCode()));
+ }
+
if (httpResponse == null) {
throw new RuntimeException("Unexpected call to execute, no pending responses are available. See Robolectric.addPendingResponse(). Request was: " +
httpRequest.getRequestLine().getMethod() + " " + httpRequest.getRequestLine().getUri());
@@ -124,7 +133,6 @@ public class FakeHttpLayer {
addHttpResponse(httpResponse);
return httpResponse;
}
-
public boolean hasPendingResponses() {
return !pendingHttpResponses.isEmpty();
}
@@ -171,6 +179,18 @@ public class FakeHttpLayer {
return httpRequestInfos.get(index);
}
+ public HttpRequestInfo getNextSentHttpRequestInfo() {
+ return httpRequestInfos.size() > 0 ? httpRequestInfos.remove(0) : null;
+ }
+
+ public void logHttpRequests() {
+ logHttpRequests = true;
+ }
+
+ public void silence() {
+ logHttpRequests = false;
+ }
+
public List<HttpRequestInfo> getSentHttpRequestInfos() {
return new ArrayList<HttpRequestInfo>(httpRequestInfos);
}
diff --git a/src/main/java/com/xtremelabs/robolectric/tester/org/apache/http/HttpEntityStub.java b/src/main/java/com/xtremelabs/robolectric/tester/org/apache/http/HttpEntityStub.java
index 3d3c05c6d..cb861377a 100644
--- a/src/main/java/com/xtremelabs/robolectric/tester/org/apache/http/HttpEntityStub.java
+++ b/src/main/java/com/xtremelabs/robolectric/tester/org/apache/http/HttpEntityStub.java
@@ -12,7 +12,7 @@ import java.io.OutputStream;
public class HttpEntityStub implements HttpEntity {
@Override public boolean isRepeatable() {
- throw new UnsupportedOperationException();
+ return true;
}
@Override public boolean isChunked() {
diff --git a/src/main/java/com/xtremelabs/robolectric/util/ReflectionUtil.java b/src/main/java/com/xtremelabs/robolectric/util/ReflectionUtil.java
new file mode 100644
index 000000000..ca71ecf61
--- /dev/null
+++ b/src/main/java/com/xtremelabs/robolectric/util/ReflectionUtil.java
@@ -0,0 +1,20 @@
+package com.xtremelabs.robolectric.util;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class ReflectionUtil {
+ public static Object invoke(Object object, String methodName, Class<?>[] argTypes, Object... args) {
+ try {
+ Method onLayout = object.getClass().getDeclaredMethod(methodName, argTypes);
+ onLayout.setAccessible(true);
+ return onLayout.invoke(object, args);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/main/java/com/xtremelabs/robolectric/util/Transcript.java b/src/main/java/com/xtremelabs/robolectric/util/Transcript.java
index ef21ae551..0745fb49c 100644
--- a/src/main/java/com/xtremelabs/robolectric/util/Transcript.java
+++ b/src/main/java/com/xtremelabs/robolectric/util/Transcript.java
@@ -17,11 +17,36 @@ public class Transcript {
assertEquals("Expected no events but got " + events + ".", 0, events.size());
}
+ /**
+ * Assert that the transcript contains the expected events, exactly. All events are cleared
+ * from the transcript.
+ *
+ * @param expectedEvents
+ */
public void assertEventsSoFar(String... expectedEvents) {
assertEquals(Arrays.asList(expectedEvents), events);
events.clear();
}
+ /**
+ * Assert that the transcript contains the expected events in order, but possibly ignoring
+ * some actual events. For example, if the transcript contains {A, B, C, D, E}, asserting
+ * on {A, C, E} would pass, {A, D, B} would fail, {E} would pass, and {F} would fail. Events
+ * up to and including the last expected event are cleared from the transcript.
+ *
+ * @param expectedEvents
+ */
+ public void assertEventsInclude(String... expectedEvents) {
+ List<String> original = new ArrayList<String>(events);
+ for (String expectedEvent : expectedEvents) {
+ int index = events.indexOf(expectedEvent);
+ if (index == -1) {
+ assertEquals(Arrays.asList(expectedEvents), original);
+ }
+ events.subList(0, index + 1).clear();
+ }
+ }
+
public void clear() {
events.clear();
}
diff --git a/src/test/java/com/xtremelabs/robolectric/R.java b/src/test/java/com/xtremelabs/robolectric/R.java
index 7f328ad03..e5bcfd28d 100644
--- a/src/test/java/com/xtremelabs/robolectric/R.java
+++ b/src/test/java/com/xtremelabs/robolectric/R.java
@@ -54,6 +54,15 @@ public final class R {
public static final int fragment = nextId++;
public static final int dynamic_fragment_container = nextId++;
public static final int content_view = nextId++;
+
+ public static final int portrait = nextId++;
+ public static final int landscape = nextId++;
+ public static final int tacos = nextId++;
+ public static final int burritos = nextId++;
+ public static int lam_container = nextId++;
+ public static int lam_inner_contents = nextId++;
+ public static int my_fragment = nextId++;
+ public static int my_landscape_fragment = nextId++;
}
public static final class string {
@@ -87,6 +96,7 @@ public final class R {
public static final int clear = nextId++;
public static final int color_with_alpha = nextId++;
public static final int android_namespaced_black = nextId++;
+ public static final int android_namespaced_transparent = nextId++;
public static final int android_red = nextId++;
}
@@ -115,6 +125,7 @@ public final class R {
public static final int media = nextId++;
public static final int inner_merge = nextId++;
public static final int included_linear_layout = nextId++;
+ public static final int edit_text = nextId++;
public static final int with_invalid_onclick = nextId++;
public static final int text_views = nextId++;
public static final int text_views_hints = nextId++;
@@ -122,6 +133,9 @@ public final class R {
public static final int tab_activity = nextId++;
public static final int different_screen_sizes = nextId++;
public static final int fragment_activity = nextId++;
+ public static final int fragment_contents = nextId++;
+ public static final int lam_outer = nextId++;
+ public static final int lam_inner = nextId++;
}
public static final class raw {
@@ -129,6 +143,10 @@ public final class R {
public static final int raw_no_ext = nextId++;
}
+ public static final class attr {
+ public static final int isSugary = nextId++;
+ }
+
public static final class menu {
public static final int test = nextId++;
public static final int test_withchilds = nextId++;
@@ -160,12 +178,20 @@ public final class R {
public static final int test_integer1 = nextId++;
public static final int test_integer2 = nextId++;
public static final int test_large_hex = nextId++;
+ public static final int meaning_of_life = nextId++;
+ public static final int loneliest_number = nextId++;
+ public static final int there_can_be_only = nextId++;
+ public static final int hex_int = nextId++;
}
-
+
public static final class bool {
public static final int false_bool_value = nextId++;
public static final int true_bool_value = nextId++;
public static final int zero_is_false = nextId++;
public static final int integers_are_true = nextId++;
}
+
+ public static final class style {
+ public static int FancyStyle = nextId++;
+ }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/RobolectricConfigTest.java b/src/test/java/com/xtremelabs/robolectric/RobolectricConfigTest.java
index 2639cb607..d2e6059de 100644
--- a/src/test/java/com/xtremelabs/robolectric/RobolectricConfigTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/RobolectricConfigTest.java
@@ -1,14 +1,18 @@
package com.xtremelabs.robolectric;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.util.List;
import static android.content.pm.ApplicationInfo.*;
+import static com.xtremelabs.robolectric.RobolectricConfig.fromBaseDirWithLibraries;
import static com.xtremelabs.robolectric.util.TestUtil.newConfig;
+import static com.xtremelabs.robolectric.util.TestUtil.resourcesBaseDir;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -63,6 +67,19 @@ public class RobolectricConfigTest {
public void shouldReturnPackageNameWhenNoProcessIsSpecifiedInTheManifest() {
assertEquals("com.xtremelabs.robolectric", newConfig("TestAndroidManifestWithNoProcess.xml").getProcessName());
}
+
+ @Test public void shouldLoadAllResourcesForLibraries() {
+ // This intentionally loads from the non standard resources/project.properties
+ RobolectricConfig config = fromBaseDirWithLibraries(resourcesBaseDir());
+
+ List<File> resourceFileDirs = config.getResourcePath();
+ assertEquals("there should be 5 resource locations", 5, resourceFileDirs.size());
+ assertEquals("./src/test/resources/res", resourceFileDirs.get(0).getPath());
+ assertEquals("./src/test/resources/../lib1/res", resourceFileDirs.get(1).getPath());
+ assertEquals("./src/test/resources/../lib2/res", resourceFileDirs.get(2).getPath());
+ assertEquals("./src/test/resources/../lib3/res", resourceFileDirs.get(3).getPath());
+ assertEquals("./src/test/resources/../lib4/res", resourceFileDirs.get(4).getPath());
+ }
@Test
public void shouldReadFlagsFromAndroidManifest() throws Exception {
diff --git a/src/test/java/com/xtremelabs/robolectric/matchers/ViewVisibilityMatcherTest.java b/src/test/java/com/xtremelabs/robolectric/matchers/ViewVisibilityMatcherTest.java
new file mode 100644
index 000000000..208728fa9
--- /dev/null
+++ b/src/test/java/com/xtremelabs/robolectric/matchers/ViewVisibilityMatcherTest.java
@@ -0,0 +1,73 @@
+package com.xtremelabs.robolectric.matchers;
+
+import android.view.View;
+import com.xtremelabs.robolectric.TestRunners;
+import org.hamcrest.Matcher;
+import org.hamcrest.StringDescription;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static com.xtremelabs.robolectric.matchers.ViewVisibilityMatcher.*;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+@RunWith(TestRunners.WithDefaults.class)
+public class ViewVisibilityMatcherTest {
+
+ private View visibleView;
+ private View invisibleView;
+ private View goneView;
+
+ @Before public void setUp() throws Exception {
+ visibleView = new View(null);
+ visibleView.setVisibility(View.VISIBLE);
+ invisibleView = new View(null);
+ invisibleView.setVisibility(View.INVISIBLE);
+ goneView = new View(null);
+ goneView.setVisibility(View.GONE);
+ }
+
+ @Test
+ public void visibleMatch() throws Exception {
+ assertThat(visibleView, isVisible());
+ assertThat(invisibleView, not(isVisible()));
+ assertThat(goneView, not(isVisible()));
+ assertThat(null, not(isVisible()));
+ }
+
+ @Test
+ public void invisibleMatch() throws Exception {
+ assertThat(visibleView, not(isInvisible()));
+ assertThat(invisibleView, isInvisible());
+ assertThat(goneView, not(isInvisible()));
+ assertThat(null, not(isInvisible()));
+ }
+
+ @Test
+ public void goneMatch() throws Exception {
+ assertThat(visibleView, not(isGone()));
+ assertThat(invisibleView, not(isGone()));
+ assertThat(goneView, isGone());
+ assertThat(null, not(isGone()));
+ }
+
+ @Test
+ public void descriptionShouldIndicateExpectedAndActual() {
+ Matcher<View> goneMatcher = isGone();
+ goneMatcher.matches(visibleView);
+ StringDescription description = new StringDescription();
+ goneMatcher.describeTo(description);
+ assertEquals("'Visible' to be 'Gone'", description.toString());
+ }
+
+ @Test
+ public void descriptionShouldIndicateNullView() {
+ Matcher<View> goneMatcher = isGone();
+ goneMatcher.matches(null);
+ StringDescription description = new StringDescription();
+ goneMatcher.describeTo(description);
+ assertEquals("View to be non-null.", description.toString());
+ }
+}
diff --git a/src/test/java/com/xtremelabs/robolectric/res/AttrResourceLoaderTest.java b/src/test/java/com/xtremelabs/robolectric/res/AttrResourceLoaderTest.java
index c1b91e75e..73d4a044d 100644
--- a/src/test/java/com/xtremelabs/robolectric/res/AttrResourceLoaderTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/res/AttrResourceLoaderTest.java
@@ -14,20 +14,30 @@ import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
public class AttrResourceLoaderTest {
+ public static final String SYSTEM_NAMESPACE = "http://schemas.android.com/apk/res/android";
private AttrResourceLoader attrResourceLoader;
@Before
public void setUp() throws Exception {
+ attrResourceLoader = makeResourceLoader();
+ new DocumentLoader(attrResourceLoader).loadResourceXmlDir(resourceFile("res", "values"));
+ new DocumentLoader(attrResourceLoader).loadSystemResourceXmlDir(getSystemResourceDir("values"));
+ }
+
+ private AttrResourceLoader makeResourceLoader() throws Exception {
ResourceExtractor resourceExtractor = new ResourceExtractor();
resourceExtractor.addLocalRClass(R.class);
resourceExtractor.addSystemRClass(android.R.class);
- attrResourceLoader = new AttrResourceLoader(resourceExtractor);
- new DocumentLoader(attrResourceLoader).loadResourceXmlDir(resourceFile("res", "values"));
- new DocumentLoader(attrResourceLoader).loadSystemResourceXmlDir(getSystemResourceDir("values"));
+ return new AttrResourceLoader(resourceExtractor);
}
@Test
- public void testAttributesAreResolved() throws Exception {
+ public void testUnknownAttributesAreUnknown() throws Exception {
+ assertThat(attrResourceLoader.hasAttributeFor(CustomView.class, "xxx", "otherItemType"), equalTo(false));
+ }
+
+ @Test
+ public void testInlineEnumAttributesAreResolved() throws Exception {
assertThat(attrResourceLoader.convertValueToEnum(CustomView.class, "xxx", "itemType", "integer"), equalTo("0"));
assertThat(attrResourceLoader.hasAttributeFor(CustomView.class, "xxx", "itemType"), equalTo(true));
@@ -38,8 +48,32 @@ public class AttrResourceLoaderTest {
@Test
public void testAttributesAreResolvedForSystemAttrs() throws Exception {
String expected = "" + ImageView.ScaleType.FIT_CENTER.ordinal();
- assertThat(attrResourceLoader.convertValueToEnum(ImageView.class, "android", "scaleType", "fitCenter"), equalTo(expected));
- assertThat(attrResourceLoader.hasAttributeFor(ImageView.class, "android", "scaleType"), equalTo(true));
+ assertThat(attrResourceLoader.convertValueToEnum(ImageView.class, SYSTEM_NAMESPACE, "scaleType", "fitCenter"), equalTo(expected));
+ assertThat(attrResourceLoader.hasAttributeFor(ImageView.class, SYSTEM_NAMESPACE, "scaleType"), equalTo(true));
+ }
+
+ @Test
+ public void testGlobalEnumAttributesAreResolved() throws Exception {
+ assertThat(attrResourceLoader.convertValueToEnum(CustomView.class, "xxx", "keycode", "KEYCODE_SOFT_RIGHT"), equalTo("2"));
+ assertThat(attrResourceLoader.hasAttributeFor(CustomView.class, "xxx", "keycode"), equalTo(true));
+
+ assertThat(attrResourceLoader.convertValueToEnum(CustomView.class, "xxx", "keycode", "KEYCODE_HOME"), equalTo("3"));
+ }
+
+ @Test
+ public void testInlineFlagAttributesAreResolved() throws Exception {
+ assertThat(attrResourceLoader.convertValueToEnum(CustomView.class, "xxx", "scrollbars", "horizontal"), equalTo("0x00000100"));
+ assertThat(attrResourceLoader.hasAttributeFor(CustomView.class, "xxx", "scrollbars"), equalTo(true));
+
+ assertThat(attrResourceLoader.convertValueToEnum(CustomView.class, "xxx", "scrollbars", "vertical"), equalTo("0x00000200"));
+ }
+
+ @Test
+ public void testGlobalFlagAttributesAreResolved() throws Exception {
+ assertThat(attrResourceLoader.convertValueToEnum(CustomView.class, "xxx", "gravity", "center"), equalTo("0x11"));
+ assertThat(attrResourceLoader.hasAttributeFor(CustomView.class, "xxx", "gravity"), equalTo(true));
+
+ assertThat(attrResourceLoader.convertValueToEnum(CustomView.class, "xxx", "gravity", "fill_vertical"), equalTo("0x70"));
}
@Test
@@ -47,6 +81,20 @@ public class AttrResourceLoaderTest {
assertThat(attrResourceLoader.convertValueToEnum(SubCustomView.class, "xxx", "itemType", "integer"), equalTo("0"));
assertThat(attrResourceLoader.hasAttributeFor(SubCustomView.class, "xxx", "itemType"), equalTo(true));
}
+
+ @Test
+ public void systemResourcesArePrefixedAndroid() throws Exception {
+ attrResourceLoader = makeResourceLoader();
+ new DocumentLoader(attrResourceLoader).loadSystemResourceXmlDir(resourceFile("res", "values"));
+
+ assertThat(attrResourceLoader.convertValueToEnum(CustomView.class, SYSTEM_NAMESPACE,
+ "gravity", "center"), equalTo("0x11"));
+ assertThat(attrResourceLoader.hasAttributeFor(CustomView.class, SYSTEM_NAMESPACE,
+ "gravity"), equalTo(true));
+
+ assertThat(attrResourceLoader.convertValueToEnum(CustomView.class, SYSTEM_NAMESPACE,
+ "gravity", "fill_vertical"), equalTo("0x70"));
+ }
private class SubCustomView extends CustomView {
public SubCustomView(Context context, AttributeSet attrs) {
diff --git a/src/test/java/com/xtremelabs/robolectric/res/ColorResourceLoaderTest.java b/src/test/java/com/xtremelabs/robolectric/res/ColorResourceLoaderTest.java
index 60f183212..d3d893df5 100644
--- a/src/test/java/com/xtremelabs/robolectric/res/ColorResourceLoaderTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/res/ColorResourceLoaderTest.java
@@ -59,6 +59,11 @@ public class ColorResourceLoaderTest {
}
@Test
+ public void shouldReturnAndroidTransparent() throws Exception {
+ assertThat(colorResourceLoader.getValue(android.R.color.transparent), equalTo(Color.TRANSPARENT));
+ }
+
+ @Test
public void shouldSupportCarrierDefinedColors() throws Exception {
assertThat(colorResourceLoader.getValue(android.R.color.background_dark), equalTo(0xFF000000));
}
@@ -66,6 +71,7 @@ public class ColorResourceLoaderTest {
@Test
public void shouldParseAndroidColorReferences() throws Exception {
assertThat(colorResourceLoader.getValue(R.color.android_namespaced_black), equalTo(Color.BLACK));
+ assertThat(colorResourceLoader.getValue(R.color.android_namespaced_transparent), equalTo(Color.TRANSPARENT));
}
@Test
diff --git a/src/test/java/com/xtremelabs/robolectric/res/DrawableResourceLoaderTest.java b/src/test/java/com/xtremelabs/robolectric/res/DrawableResourceLoaderTest.java
index 031a6c427..fdb9d5bfb 100644
--- a/src/test/java/com/xtremelabs/robolectric/res/DrawableResourceLoaderTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/res/DrawableResourceLoaderTest.java
@@ -34,7 +34,7 @@ public class DrawableResourceLoaderTest {
extractor.addLocalRClass(R.class);
extractor.addSystemRClass(android.R.class);
- resourceLoader = new DrawableResourceLoader(extractor, resourceFile("res"));
+ resourceLoader = new DrawableResourceLoader(extractor);
DocumentLoader documentLoader = new DocumentLoader(resourceLoader);
documentLoader.loadResourceXmlDir(resourceFile("res", "drawable"));
diff --git a/src/test/java/com/xtremelabs/robolectric/res/IntegerResourceLoaderTest.java b/src/test/java/com/xtremelabs/robolectric/res/IntegerResourceLoaderTest.java
index 5c683e3d7..04785b361 100644
--- a/src/test/java/com/xtremelabs/robolectric/res/IntegerResourceLoaderTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/res/IntegerResourceLoaderTest.java
@@ -1,13 +1,12 @@
package com.xtremelabs.robolectric.res;
-import static com.xtremelabs.robolectric.util.TestUtil.resourceFile;
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
+import com.xtremelabs.robolectric.R;
import org.junit.Before;
import org.junit.Test;
-import com.xtremelabs.robolectric.R;
+import static com.xtremelabs.robolectric.util.TestUtil.resourceFile;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
public class IntegerResourceLoaderTest {
@@ -30,6 +29,17 @@ public class IntegerResourceLoaderTest {
assertThat( resourceLoader.getValue( R.integer.test_integer1 ), equalTo( 2000 ) );
assertThat( resourceLoader.getValue( R.integer.test_integer2 ), equalTo( 9 ) );
assertThat( resourceLoader.getValue( R.integer.test_large_hex), equalTo( 0xFFFF0000 ) );
+ assertThat(resourceLoader.getValue(R.integer.meaning_of_life), equalTo(42));
+ assertThat(resourceLoader.getValue(R.integer.loneliest_number), equalTo(1));
}
+ @Test
+ public void testHexValuesAreResolved() throws Exception {
+ assertThat(resourceLoader.getValue(R.integer.hex_int), equalTo((int)Long.parseLong("FFFF0000", 16)));
+ }
+
+ @Test
+ public void shouldResolveStringReferences() throws Exception {
+ assertThat(resourceLoader.getValue(R.integer.there_can_be_only), equalTo(1));
+ }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/res/PreferenceLoaderTest.java b/src/test/java/com/xtremelabs/robolectric/res/PreferenceLoaderTest.java
index 06b9e073a..e49dc155f 100644
--- a/src/test/java/com/xtremelabs/robolectric/res/PreferenceLoaderTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/res/PreferenceLoaderTest.java
@@ -20,39 +20,38 @@ import com.xtremelabs.robolectric.R;
import com.xtremelabs.robolectric.Robolectric;
import com.xtremelabs.robolectric.util.I18nException;
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertThat;
@RunWith(TestRunners.WithDefaults.class)
public class PreferenceLoaderTest {
- private PreferenceLoader prefLoader;
-
+ private PreferenceLoader prefLoader;
+
@Before
public void setUp() throws Exception {
Robolectric.bindDefaultShadowClasses();
-
+
ResourceExtractor resourceExtractor = new ResourceExtractor();
resourceExtractor.addLocalRClass(R.class);
StringResourceLoader stringResourceLoader = new StringResourceLoader(resourceExtractor);
new DocumentLoader(stringResourceLoader).loadResourceXmlDir(resourceFile("res", "values"));
prefLoader = new PreferenceLoader(resourceExtractor);
- new DocumentLoader(prefLoader).loadResourceXmlDir(resourceFile("res", "xml"));
+ new DocumentLoader(prefLoader).loadResourceXmlDir(resourceFile("res", "xml"));
}
-
+
@Test
public void shouldCreateCorrectClasses() {
- PreferenceScreen screen = prefLoader.inflatePreferences(new Activity(), "xml/preferences");
- assertThatScreenMatchesExpected(screen);
+ PreferenceScreen screen = prefLoader.inflatePreferences(new Activity(), "xml/preferences");
+ assertThatScreenMatchesExpected(screen);
}
-
+
@Test
public void shouldLoadByResourceId() {
- PreferenceScreen screen = prefLoader.inflatePreferences(new Activity(), R.xml.preferences);
- assertThatScreenMatchesExpected(screen);
+ PreferenceScreen screen = prefLoader.inflatePreferences(new Activity(), R.xml.preferences);
+ assertThatScreenMatchesExpected(screen);
}
-
- @Test(expected=I18nException.class)
+
+ @Test(expected=I18nException.class)
public void shouldThrowI18nExceptionOnPrefsWithBareStrings() throws Exception {
ResourceExtractor resourceExtractor = new ResourceExtractor();
resourceExtractor.addLocalRClass(R.class);
@@ -60,21 +59,28 @@ public class PreferenceLoaderTest {
new DocumentLoader(stringResourceLoader).loadResourceXmlDir(resourceFile("res", "values"));
prefLoader = new PreferenceLoader(resourceExtractor);
prefLoader.setStrictI18n(true);
- new DocumentLoader(prefLoader).loadResourceXmlDir(resourceFile("res", "xml"));
+ new DocumentLoader(prefLoader).loadResourceXmlDir(resourceFile("res", "xml"));
prefLoader.inflatePreferences(Robolectric.application, R.xml.preferences);
}
-
+
protected void assertThatScreenMatchesExpected(PreferenceScreen screen) {
- assertThat(screen.getPreferenceCount(), equalTo(6));
-
- assertThat(screen.getPreference(0), instanceOf(PreferenceCategory.class));
- assertThat(((PreferenceCategory)screen.getPreference(0)).getPreference(0), instanceOf(Preference.class));
-
- assertThat(screen.getPreference(1), instanceOf(CheckBoxPreference.class));
- assertThat(screen.getPreference(2), instanceOf(EditTextPreference.class));
- assertThat(screen.getPreference(3), instanceOf(ListPreference.class));
- assertThat(screen.getPreference(4), instanceOf(Preference.class));
- assertThat(screen.getPreference(5), instanceOf(RingtonePreference.class));
+ assertThat(screen.getPreferenceCount(), equalTo(7));
+
+ assertThat(screen.getPreference(0), instanceOf(PreferenceCategory.class));
+ assertThat(((PreferenceCategory)screen.getPreference(0)).getPreference(0), instanceOf(Preference.class));
+
+ PreferenceScreen innerScreen = (PreferenceScreen) screen.getPreference(1);
+ assertThat(innerScreen, instanceOf(PreferenceScreen.class));
+ assertThat(innerScreen.getKey().toString(), is("screen"));
+ assertThat(innerScreen.getTitle().toString(), is("Screen Test"));
+ assertThat(innerScreen.getSummary(), nullValue());
+ assertThat(innerScreen.getPreference(0), instanceOf(Preference.class));
+
+ assertThat(screen.getPreference(2), instanceOf(CheckBoxPreference.class));
+ assertThat(screen.getPreference(3), instanceOf(EditTextPreference.class));
+ assertThat(screen.getPreference(4), instanceOf(ListPreference.class));
+ assertThat(screen.getPreference(5), instanceOf(Preference.class));
+ assertThat(screen.getPreference(6), instanceOf(RingtonePreference.class));
}
}
diff --git a/src/test/java/com/xtremelabs/robolectric/res/RawResourceLoaderTest.java b/src/test/java/com/xtremelabs/robolectric/res/RawResourceLoaderTest.java
index d1662afa8..ffbb7b588 100644
--- a/src/test/java/com/xtremelabs/robolectric/res/RawResourceLoaderTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/res/RawResourceLoaderTest.java
@@ -2,17 +2,12 @@ package com.xtremelabs.robolectric.res;
import com.xtremelabs.robolectric.R;
import com.xtremelabs.robolectric.TestRunners;
+import com.xtremelabs.robolectric.util.TestUtil;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.BufferedReader;
-import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StringWriter;
-import java.io.Writer;
import static com.xtremelabs.robolectric.util.TestUtil.resourceFile;
import static org.junit.Assert.assertEquals;
@@ -31,27 +26,12 @@ public class RawResourceLoaderTest {
@Test
public void shouldReturnRawResourcesWithExtensions() throws Exception {
InputStream is = rawResourceLoader.getValue(R.raw.raw_resource);
- assertEquals("raw txt file contents", readString(is));
+ assertEquals("raw txt file contents", TestUtil.readString(is));
}
@Test
public void shouldReturnRawResourcesWithoutExtensions() throws Exception {
InputStream is = rawResourceLoader.getValue(R.raw.raw_no_ext);
- assertEquals("no ext file contents", readString(is));
- }
-
- private static String readString(InputStream is) throws IOException {
- Writer writer = new StringWriter();
- char[] buffer = new char[1024];
- try {
- Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
- int n;
- while ((n = reader.read(buffer)) != -1) {
- writer.write(buffer, 0, n);
- }
- } finally {
- is.close();
- }
- return writer.toString();
+ assertEquals("no ext file contents", TestUtil.readString(is));
}
}
diff --git a/src/test/java/com/xtremelabs/robolectric/res/ResourceLoaderTest.java b/src/test/java/com/xtremelabs/robolectric/res/ResourceLoaderTest.java
index dcb155d37..9302f21e9 100644
--- a/src/test/java/com/xtremelabs/robolectric/res/ResourceLoaderTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/res/ResourceLoaderTest.java
@@ -49,14 +49,14 @@ public class ResourceLoaderTest {
ViewGroup vg = new FrameLayout(Robolectric.application);
resourceLoader.inflateView(Robolectric.application, R.layout.text_views, vg);
}
-
+
@Test(expected=I18nException.class)
public void shouldThrowExceptionOnI18nStrictModeInflateMenu() throws Exception {
ResourceLoader resourceLoader = new ResourceLoader(DEFAULT_SDK_VERSION, R.class, resourceFile("res"), resourceFile("menu"));
resourceLoader.setStrictI18n(true);
resourceLoader.inflateMenu(Robolectric.application, R.menu.test, null);
}
-
+
@Test(expected=I18nException.class)
public void shouldThrowExceptionOnI18nStrictModeInflatePreferences() throws Exception {
ResourceLoader resourceLoader = new ResourceLoader(DEFAULT_SDK_VERSION, R.class, resourceFile("res"), resourceFile("xml"));
diff --git a/src/test/java/com/xtremelabs/robolectric/res/TestAttributeSetTest.java b/src/test/java/com/xtremelabs/robolectric/res/TestAttributeSetTest.java
index 73391c271..5afa7c49f 100644
--- a/src/test/java/com/xtremelabs/robolectric/res/TestAttributeSetTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/res/TestAttributeSetTest.java
@@ -113,7 +113,7 @@ public class TestAttributeSetTest {
}
@Test
- public void getAttributeValue_shouldReturnValueFromAttribute() throws Exception {
+ public void getAttributeValue_byName_shouldReturnValueFromAttribute() throws Exception {
attributes.put("isSugary", "oh heck yeah");
TestAttributeSet testAttributeSet = new TestAttributeSet(attributes, null, null, null, false);
@@ -121,6 +121,14 @@ public class TestAttributeSetTest {
}
@Test
+ public void getAttributeValue_byId_shouldReturnValueFromAttribute() throws Exception {
+ attributes.put("isSugary", "oh heck yeah");
+
+ TestAttributeSet testAttributeSet = new TestAttributeSet(attributes, resourceExtractor, null, null, false);
+ assertThat(testAttributeSet.getAttributeValue(R.attr.isSugary), equalTo("oh heck yeah"));
+ }
+
+ @Test
public void getAttributeIntValue_shouldReturnValueFromAttribute() throws Exception {
attributes.put("sugarinessPercent", "100");
@@ -152,4 +160,66 @@ public class TestAttributeSetTest {
int nonExistantResource = 12345;
assertThat(testAttributeSet.getAttributeValue(nonExistantResource), nullValue());
}
+
+ @Test
+ public void getAttributeIntValue_shouldReturnValueFromAttributeWhenNotInAttributeSet() throws Exception {
+ AttrResourceLoader resourceLoader = new AttrResourceLoader(resourceExtractor);
+ TestAttributeSet testAttributeSet = new TestAttributeSet(attributes, null, resourceLoader, null, false);
+ assertThat(testAttributeSet.getAttributeIntValue("some namespace", "sugarinessPercent", 42), equalTo(42));
+ }
+
+ @Test
+ public void getAttributeIntValue_shouldReturnEnumValuesForEnumAttributesWhenNotInAttributeSet() throws Exception {
+ AttrResourceLoader resourceLoader = new AttrResourceLoader(resourceExtractor);
+ TestAttributeSet testAttributeSet = new TestAttributeSet(attributes, null, resourceLoader, null, false);
+ assertThat(testAttributeSet.getAttributeIntValue("some namespace", "itemType", 24), equalTo(24));
+ }
+
+ @Test
+ public void getAttributeFloatValue_shouldGetFloatValuesFromAttributes() throws Exception {
+ attributes.put("sugaryScale", "1234.456");
+
+ TestAttributeSet testAttributeSet = new TestAttributeSet(attributes, null, null, null, false);
+ assertThat(testAttributeSet.getAttributeFloatValue("some namespace", "sugaryScale", 78.9f), equalTo(1234.456f));
+ }
+
+ @Test
+ public void getAttributeFloatValue_withNamespace_shouldGetFloatValuesFromAttributes() throws Exception {
+ attributes.put("xxx:sugaryScale", "1234.456");
+
+ TestAttributeSet testAttributeSet = new TestAttributeSet(attributes, null, null, null, false);
+ assertThat(testAttributeSet.getAttributeFloatValue("some namespace", "sugaryScale", 78.9f), equalTo(1234.456f));
+ }
+
+ @Test
+ public void getAttributeFloatValue_shouldReturnDefaultFloatValueWhenNotInAttributeSet() throws Exception {
+ TestAttributeSet testAttributeSet = new TestAttributeSet(attributes, null, null, null, false);
+ assertThat(testAttributeSet.getAttributeFloatValue("some namespace", "sugaryScale", 78.9f), equalTo(78.9f));
+ }
+
+ @Test
+ public void getStyleAttribute_doesNotThrowException() throws Exception {
+ TestAttributeSet testAttributeSet = new TestAttributeSet(attributes, null, null, null, false);
+ testAttributeSet.getStyleAttribute();
+ }
+
+ @Test
+ public void getStyleAttribute_returnsZeroWhenNoStyle() throws Exception {
+ TestAttributeSet testAttributeSet = new TestAttributeSet(attributes, null, null, null, false);
+ assertThat(testAttributeSet.getStyleAttribute(), equalTo(0));
+ }
+
+ @Test
+ public void getStyleAttribute_returnsCorrectValue() throws Exception {
+ attributes.put("style", "@style/FancyStyle");
+ TestAttributeSet testAttributeSet = new TestAttributeSet(attributes, resourceExtractor, null, null, false);
+ assertThat(testAttributeSet.getStyleAttribute(), equalTo(R.style.FancyStyle));
+ }
+
+ @Test
+ public void getStyleAttribute_doesNotThrowException_whenStyleIsBogus() throws Exception {
+ attributes.put("style", "@style/bogus_style");
+ TestAttributeSet testAttributeSet = new TestAttributeSet(attributes, resourceExtractor, null, null, false);
+ assertThat(testAttributeSet.getStyleAttribute(), equalTo(0));
+ }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/res/ViewLoaderTest.java b/src/test/java/com/xtremelabs/robolectric/res/ViewLoaderTest.java
index 8f8a361b3..8efb96b06 100644
--- a/src/test/java/com/xtremelabs/robolectric/res/ViewLoaderTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/res/ViewLoaderTest.java
@@ -1,8 +1,11 @@
package com.xtremelabs.robolectric.res;
import android.app.Activity;
-import android.content.Context;
+import android.content.pm.ActivityInfo;
import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
@@ -30,7 +33,7 @@ import static org.junit.Assert.*;
@RunWith(TestRunners.WithDefaults.class)
public class ViewLoaderTest {
private ViewLoader viewLoader;
- private Context context;
+ private FragmentActivity context;
@Before
public void setUp() throws Exception {
@@ -50,7 +53,7 @@ public class ViewLoaderTest {
new DocumentLoader(viewLoader).loadResourceXmlDir(resourceFile("res", "layout-land"));
new DocumentLoader(viewLoader).loadSystemResourceXmlDir(getSystemResourceDir("layout"));
- context = new Activity();
+ context = new FragmentActivity();
}
@Test
@@ -262,6 +265,37 @@ public class ViewLoaderTest {
}
@Test
+ public void testFragment() throws Exception {
+ View v = viewLoader.inflateView(context, "layout/fragment");
+ TestUtil.assertInstanceOf(TextView.class, v);
+ final FragmentManager fragmentManager = context.getSupportFragmentManager();
+ Fragment fragment = fragmentManager.findFragmentById(R.id.my_fragment);
+ assertNotNull(fragment);
+ }
+
+ @Test
+ public void testMultiOrientation() throws Exception {
+ // Default screen orientation should be portrait.
+ ViewGroup view = (ViewGroup) viewLoader.inflateView(context, "layout/multi_orientation");
+ TestUtil.assertInstanceOf(LinearLayout.class, view);
+ assertEquals(view.getId(), R.id.portrait);
+ assertSame(context, view.getContext());
+
+ // Confirm explicit "orientation = portrait" works.
+ context.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ view = (ViewGroup) viewLoader.inflateView(context, "layout/multi_orientation");
+ TestUtil.assertInstanceOf(LinearLayout.class, view);
+ assertEquals(view.getId(), R.id.portrait);
+ assertSame(context, view.getContext());
+
+ // Confirm explicit "orientation = landscape" works.
+ context.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ view = (ViewGroup) viewLoader.inflateView(context, "layout/multi_orientation");
+ assertEquals(view.getId(), R.id.landscape);
+ TestUtil.assertInstanceOf(LinearLayout.class, view);
+ }
+
+ @Test
public void testViewEnabled() throws Exception {
View mediaView = viewLoader.inflateView(context, "layout/main");
assertThat(mediaView.findViewById(R.id.time).isEnabled(), equalTo(false));
@@ -340,7 +374,7 @@ public class ViewLoaderTest {
viewLoader.inflateView(context,"layout/text_views");
}
- public static class ClickActivity extends Activity {
+ public static class ClickActivity extends FragmentActivity {
public boolean clicked = false;
@Override protected void onCreate(Bundle savedInstanceState) {
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/AbsoluteLayoutTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/AbsoluteLayoutTest.java
new file mode 100644
index 000000000..a8cba2555
--- /dev/null
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/AbsoluteLayoutTest.java
@@ -0,0 +1,20 @@
+package com.xtremelabs.robolectric.shadows;
+
+import android.view.ViewGroup;
+import android.widget.AbsoluteLayout;
+import com.xtremelabs.robolectric.TestRunners;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+@RunWith(TestRunners.WithDefaults.class)
+public class AbsoluteLayoutTest {
+ @Test
+ public void getLayoutParams_shouldReturnAbsoluteLayoutParams() throws Exception {
+ ViewGroup.LayoutParams layoutParams = new AbsoluteLayout(null).getLayoutParams();
+
+ assertThat(layoutParams, instanceOf(AbsoluteLayout.LayoutParams.class));
+ }
+}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/ActivityTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/ActivityTest.java
index eb6018197..ec3cece5b 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/ActivityTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/ActivityTest.java
@@ -60,6 +60,21 @@ public class ActivityTest {
}
@Test
+ public void startActivity_shouldDelegateToStartActivityForResult() {
+ final Transcript transcript = new Transcript();
+ Activity activity = new Activity() {
+ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ transcript.add("onActivityResult called with requestCode " + requestCode + ", resultCode " + resultCode + ", intent data " + data.getData());
+ }
+ };
+ activity.startActivity(new Intent().setType("image/*"));
+
+ shadowOf(activity).receiveResult(new Intent().setType("image/*"), Activity.RESULT_OK,
+ new Intent().setData(Uri.parse("content:foo")));
+ transcript.assertEventsSoFar("onActivityResult called with requestCode -1, resultCode -1, intent data content:foo");
+ }
+
+ @Test
public void startActivityForResultAndReceiveResult_shouldSendResponsesBackToActivity() throws Exception {
final Transcript transcript = new Transcript();
Activity activity = new Activity() {
@@ -340,7 +355,7 @@ public class ActivityTest {
int id = activity.getResources().getIdentifier("just_alot_of_crap", "string", "com.xtremelabs.robolectric");
assertTrue(id == 0);
}
-
+
@Test
public void setDefaultKeyMode_shouldSetKeyMode() {
int[] modes = {
@@ -628,6 +643,32 @@ public class ActivityTest {
shadowOf(activity).callOnStart();
}
+ @Test
+ public void getAndSetParentActivity_shouldWorkForTestingPurposes() throws Exception {
+ Activity parentActivity = new Activity(){};
+ Activity activity = new Activity(){};
+ shadowOf(activity).setParent(parentActivity);
+ assertSame(parentActivity, activity.getParent());
+ }
+
+ @Test
+ public void getAndSetRequestedOrientation_shouldRemember() throws Exception {
+ Activity activity = new Activity(){};
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ assertEquals(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, activity.getRequestedOrientation());
+ }
+
+ @Test
+ public void getAndSetRequestedOrientation_shouldDelegateToParentIfPresent() throws Exception {
+ Activity parentActivity = new Activity(){};
+ Activity activity = new Activity(){};
+ shadowOf(activity).setParent(parentActivity);
+ parentActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ assertEquals(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, activity.getRequestedOrientation());
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
+ assertEquals(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE, parentActivity.getRequestedOrientation());
+ }
+
private static class MyActivity extends Activity {
@Override protected void onDestroy() {
super.onDestroy();
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/AlertDialogTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/AlertDialogTest.java
index b1443c71b..7a962b374 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/AlertDialogTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/AlertDialogTest.java
@@ -47,6 +47,16 @@ public class AlertDialogTest {
}
@Test
+ public void nullTitleAndMessageAreOkay() throws Exception {
+ AlertDialog.Builder builder = new AlertDialog.Builder(new ContextWrapper(null)) //
+ .setTitle(null) //
+ .setMessage(null);
+ ShadowAlertDialog shadowAlertDialog = shadowOf(builder.create());
+ assertThat(shadowAlertDialog.getTitle().toString(), equalTo(""));
+ assertThat(shadowAlertDialog.getMessage(), equalTo(""));
+ }
+
+ @Test
public void getLatestAlertDialog_shouldReturnARealAlertDialog() throws Exception {
assertThat(ShadowAlertDialog.getLatestAlertDialog(), nullValue());
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/ApplicationTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/ApplicationTest.java
index 7a71f1a5b..20fae2753 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/ApplicationTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/ApplicationTest.java
@@ -8,6 +8,7 @@ import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Resources;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
@@ -29,9 +30,7 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
+import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -288,6 +287,10 @@ public class ApplicationTest {
}
@Override
+ public void dumpAsync(FileDescriptor fileDescriptor, String[] strings) throws RemoteException {
+ }
+
+ @Override
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
return false;
}
@@ -300,9 +303,19 @@ public class ApplicationTest {
public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
return false;
}
+ }
- @Override
- public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
- }
+ @Test
+ public void shouldRememberResourcesAfterLazilyLoading() throws Exception {
+ Application application = new ApplicationResolver(newConfig("TestAndroidManifestWithPackageName.xml")).resolveApplication();
+ assertSame(application.getResources(), application.getResources());
+ }
+
+ @Test
+ public void shouldBeAbleToResetResources() throws Exception {
+ Application application = new ApplicationResolver(newConfig("TestAndroidManifestWithPackageName.xml")).resolveApplication();
+ Resources res = application.getResources();
+ shadowOf(application).resetResources();
+ assertFalse(res == application.getResources());
}
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/BitmapDrawableTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/BitmapDrawableTest.java
index 36a3652c3..ee9712300 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/BitmapDrawableTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/BitmapDrawableTest.java
@@ -1,6 +1,7 @@
package com.xtremelabs.robolectric.shadows;
import android.content.res.Resources;
+import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
@@ -20,6 +21,8 @@ import java.io.InputStream;
import static com.xtremelabs.robolectric.Robolectric.shadowOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
@RunWith(TestRunners.WithDefaults.class)
public class BitmapDrawableTest {
@@ -31,12 +34,31 @@ public class BitmapDrawableTest {
}
@Test
+ public void constructors_shouldSetBitmap() throws Exception {
+ Bitmap bitmap = Robolectric.newInstanceOf(Bitmap.class);
+ BitmapDrawable drawable = new BitmapDrawable(bitmap);
+ assertEquals(bitmap, drawable.getBitmap());
+
+ drawable = new BitmapDrawable(resources, bitmap);
+ assertEquals(bitmap, drawable.getBitmap());
+ }
+
+ @Test
public void getBitmap_shouldReturnBitmapUsedToDraw() throws Exception {
BitmapDrawable drawable = (BitmapDrawable) resources.getDrawable(R.drawable.an_image);
assertEquals("Bitmap for resource:drawable/an_image", shadowOf(drawable.getBitmap()).getDescription());
}
@Test
+ public void mutate_createsDeepCopy() throws Exception {
+ BitmapDrawable original = (BitmapDrawable) resources.getDrawable(R.drawable.an_image);
+ Drawable mutated = original.mutate();
+ assertNotSame(original, mutated);
+ assertTrue(mutated instanceof BitmapDrawable);
+ assertEquals(original, mutated);
+ }
+
+ @Test
public void draw_shouldCopyDescriptionToCanvas() throws Exception {
BitmapDrawable drawable = (BitmapDrawable) resources.getDrawable(R.drawable.an_image);
Canvas canvas = new Canvas();
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/BitmapFactoryTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/BitmapFactoryTest.java
index 354aa4065..2bb90661e 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/BitmapFactoryTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/BitmapFactoryTest.java
@@ -10,6 +10,9 @@ import com.xtremelabs.robolectric.TestRunners;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
import java.io.InputStream;
import static com.xtremelabs.robolectric.Robolectric.shadowOf;
@@ -39,6 +42,28 @@ public class BitmapFactoryTest {
}
@Test
+ public void decodeFile_ifFileExists_shouldSetDescriptionToContentsOfFile() throws Exception {
+ File tempFile = File.createTempFile("temp-image", ".jpg");
+ writeTo(tempFile, "image bytes", " more image bytes");
+
+ Bitmap bitmap = BitmapFactory.decodeFile(tempFile.getPath());
+ assertEquals("Bitmap for image bytes more image bytes", shadowOf(bitmap).getDescription());
+ assertEquals(100, bitmap.getWidth());
+ assertEquals(100, bitmap.getHeight());
+ }
+
+ @Test
+ public void decodeFile_ifFileExists_shouldSetDescriptionToContentsOfFile_UsingOptions() throws Exception {
+ File tempFile = File.createTempFile("temp-image", ".jpg");
+ writeTo(tempFile, "image bytes", " more image bytes");
+
+ Bitmap bitmap = BitmapFactory.decodeFile(tempFile.getPath(), new BitmapFactory.Options());
+ assertEquals("Bitmap for image bytes more image bytes", shadowOf(bitmap).getDescription());
+ assertEquals(100, bitmap.getWidth());
+ assertEquals(100, bitmap.getHeight());
+ }
+
+ @Test
public void decodeStream_shouldSetDescription() throws Exception {
InputStream inputStream = Robolectric.application.getContentResolver().openInputStream(Uri.parse("content:/path"));
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
@@ -105,6 +130,28 @@ public class BitmapFactoryTest {
}
@Test
+ public void decodeByteArray_shouldGetWidthAndHeightFromHints() throws Exception {
+ String data = "arbitrary bytes";
+ ShadowBitmapFactory.provideWidthAndHeightHints(Uri.parse(data), 123, 456);
+
+ byte[] bytes = data.getBytes();
+ Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
+ assertEquals("Bitmap for " + data, shadowOf(bitmap).getDescription());
+ assertEquals(123, bitmap.getWidth());
+ assertEquals(456, bitmap.getHeight());
+ }
+
+ @Test
+ public void decodeByteArray_shouldIncludeOffsets() throws Exception {
+ String data = "arbitrary bytes";
+ ShadowBitmapFactory.provideWidthAndHeightHints(Uri.parse(data), 123, 456);
+
+ byte[] bytes = data.getBytes();
+ Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 1, bytes.length - 2);
+ assertEquals("Bitmap for " + data + " bytes 1..13", shadowOf(bitmap).getDescription());
+ }
+
+ @Test
public void decodeStream_shouldGetWidthAndHeightFromHints() throws Exception {
ShadowBitmapFactory.provideWidthAndHeightHints(Uri.parse("content:/path"), 123, 456);
@@ -117,46 +164,56 @@ public class BitmapFactoryTest {
@Test
public void decodeByteArray_shouldSetDataChecksum() throws Exception {
- byte[] data = { 23, 100, 23, 52, 23, 18, 76, 43 };
-
- Bitmap bitmap = ShadowBitmapFactory.decodeByteArray(data, 0, data.length);
- assertThat( bitmap, notNullValue() );
- assertThat( shadowOf(bitmap).getDescription(), equalTo( "Bitmap for byte array, checksum:80429753 offset: 0 length: 8" ) );
- assertThat( bitmap.getWidth(), equalTo(100) );
- assertThat( bitmap.getHeight(), equalTo(100) );
-
+ byte[] data = { 23, 100, 23, 52, 23, 18, 76, 43 };
+
+ Bitmap bitmap = ShadowBitmapFactory.decodeByteArray(data, 0, data.length);
+ assertThat( bitmap, notNullValue() );
+ assertThat( shadowOf(bitmap).getDescription(), equalTo( "Bitmap for byte array, checksum:80429753 offset: 0 length: 8" ) );
+ assertThat( bitmap.getWidth(), equalTo(100) );
+ assertThat( bitmap.getHeight(), equalTo(100) );
+
}
@Test
public void decodeByteArray_withOptionsShouldSetDataChecksum() throws Exception {
- byte[] data = { 23, 100, 23, 52, 23, 18, 76, 43 };
-
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inSampleSize = 4;
- Bitmap bitmap = ShadowBitmapFactory.decodeByteArray(data, 0, data.length, options);
- assertThat( shadowOf(bitmap).getDescription(), equalTo( "Bitmap for byte array, checksum:80429753 offset: 0 length: 8 with options inSampleSize=4" ) );
- assertThat( bitmap.getWidth(), equalTo(25) );
- assertThat( bitmap.getHeight(), equalTo(25) );
+ byte[] data = { 23, 100, 23, 52, 23, 18, 76, 43 };
+
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inSampleSize = 4;
+ Bitmap bitmap = ShadowBitmapFactory.decodeByteArray(data, 0, data.length, options);
+ assertThat( shadowOf(bitmap).getDescription(), equalTo( "Bitmap for byte array, checksum:80429753 offset: 0 length: 8 with options inSampleSize=4" ) );
+ assertThat( bitmap.getWidth(), equalTo(25) );
+ assertThat( bitmap.getHeight(), equalTo(25) );
}
@Test
public void decodeWithDifferentSampleSize() {
- String name = "test";
- BitmapFactory.Options options = new BitmapFactory.Options();
-
- options.inSampleSize = 0;
- Bitmap bm = ShadowBitmapFactory.create(name, options);
- assertThat( bm.getWidth(), equalTo(100) );
- assertThat( bm.getHeight(), equalTo(100) );
-
- options.inSampleSize = 2;
- bm = ShadowBitmapFactory.create(name, options);
- assertThat( bm.getWidth(), equalTo(50) );
- assertThat( bm.getHeight(), equalTo(50) );
-
- options.inSampleSize = 101;
- bm = ShadowBitmapFactory.create(name, options);
- assertThat( bm.getWidth(), equalTo(1) );
- assertThat( bm.getHeight(), equalTo(1) );
+ String name = "test";
+ BitmapFactory.Options options = new BitmapFactory.Options();
+
+ options.inSampleSize = 0;
+ Bitmap bm = ShadowBitmapFactory.create(name, options);
+ assertThat( bm.getWidth(), equalTo(100) );
+ assertThat( bm.getHeight(), equalTo(100) );
+
+ options.inSampleSize = 2;
+ bm = ShadowBitmapFactory.create(name, options);
+ assertThat( bm.getWidth(), equalTo(50) );
+ assertThat( bm.getHeight(), equalTo(50) );
+
+ options.inSampleSize = 101;
+ bm = ShadowBitmapFactory.create(name, options);
+ assertThat( bm.getWidth(), equalTo(1) );
+ assertThat( bm.getHeight(), equalTo(1) );
+ }
+
+ //////////////////
+
+ private void writeTo(File tempFile, String... strings) throws IOException {
+ FileWriter fileWriter = new FileWriter(tempFile);
+ for (String s : strings) {
+ fileWriter.write(s);
+ }
+ fileWriter.close();
}
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/BluetoothAdapterTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/BluetoothAdapterTest.java
index da87ac3b2..0c2a223a4 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/BluetoothAdapterTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/BluetoothAdapterTest.java
@@ -1,15 +1,40 @@
package com.xtremelabs.robolectric.shadows;
+
import android.bluetooth.BluetoothAdapter;
+import com.xtremelabs.robolectric.Robolectric;
import com.xtremelabs.robolectric.TestRunners;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static com.xtremelabs.robolectric.Robolectric.shadowOf;
-import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
@RunWith(TestRunners.WithDefaults.class)
public class BluetoothAdapterTest {
+ private BluetoothAdapter bluetoothAdapter;
+ private ShadowBluetoothAdapter shadowBluetoothAdapter;
+
+ @Before
+ public void setUp() throws Exception {
+ bluetoothAdapter = Robolectric.newInstanceOf(BluetoothAdapter.class);
+ shadowBluetoothAdapter = shadowOf(bluetoothAdapter);
+ }
+
+ @Test
+ public void testAdapterDefaultsDisabled() {
+ assertFalse(bluetoothAdapter.isEnabled());
+ }
+
+ @Test
+ public void testAdapterCanBeEnabled() {
+ shadowBluetoothAdapter.setEnabled(true);
+ assertTrue(bluetoothAdapter.isEnabled());
+ }
+
@Test
public void canGetAndSetAddress() throws Exception {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/CheckedTextViewTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/CheckedTextViewTest.java
index f8b5fc6d9..af7640adf 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/CheckedTextViewTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/CheckedTextViewTest.java
@@ -38,4 +38,12 @@ public class CheckedTextViewTest {
assertTrue(checkedTextView.isChecked());
}
+ @Test public void toggle_shouldChangeCheckedness() throws Exception {
+ CheckedTextView view = new CheckedTextView(null);
+ assertFalse(view.isChecked());
+ view.toggle();
+ assertTrue(view.isChecked());
+ view.performClick();
+ assertFalse(view.isChecked());
+ }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/ClipboardManagerTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/ClipboardManagerTest.java
index ec5bfed89..bdeeefdac 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/ClipboardManagerTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/ClipboardManagerTest.java
@@ -1,7 +1,7 @@
package com.xtremelabs.robolectric.shadows;
+import android.content.ClipboardManager;
import android.content.Context;
-import android.text.ClipboardManager;
import com.xtremelabs.robolectric.Robolectric;
import com.xtremelabs.robolectric.TestRunners;
import org.junit.Before;
@@ -9,9 +9,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
@RunWith(TestRunners.WithDefaults.class)
public class ClipboardManagerTest {
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/ConfigurationTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/ConfigurationTest.java
index 41ffe4947..d89e5d7ce 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/ConfigurationTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/ConfigurationTest.java
@@ -39,6 +39,13 @@ public class ConfigurationTest {
shConfiguration.setLocale( Locale.FRANCE);
assertThat( configuration.locale, equalTo( Locale.FRANCE ) );
-}
+ }
+
+ @Test
+ public void testConstructCopy() {
+ configuration.setToDefaults();
+ Configuration clone = new Configuration(configuration);
+ assertThat( configuration, equalTo( clone ) );
+ }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/ContextTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/ContextTest.java
index 6ecb79e71..a9c821336 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/ContextTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/ContextTest.java
@@ -6,26 +6,17 @@ import android.content.res.TypedArray;
import com.xtremelabs.robolectric.R;
import com.xtremelabs.robolectric.TestRunners;
import com.xtremelabs.robolectric.tester.android.util.TestAttributeSet;
-import org.hamcrest.CoreMatchers;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.IOException;
+import java.io.*;
import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
@RunWith(TestRunners.WithDefaults.class)
public class ContextTest {
@@ -111,7 +102,8 @@ public class ContextTest {
assertNotNull(context.getCacheDir());
File cacheTest = new File(context.getCacheDir(), "__test__");
- assertThat(cacheTest.getPath(), CoreMatchers.containsString("android-cache"));
+ assertThat(cacheTest.getAbsolutePath(), startsWith(System.getProperty("java.io.tmpdir")));
+ assertThat(cacheTest.getAbsolutePath(), endsWith("android-cache" + File.separator + "__test__"));
FileOutputStream fos = null;
try {
@@ -129,7 +121,8 @@ public class ContextTest {
assertNotNull(context.getExternalCacheDir());
File cacheTest = new File(context.getExternalCacheDir(), "__test__");
- assertThat(cacheTest.getPath(), containsString("android-external-cache"));
+ assertThat(cacheTest.getAbsolutePath(), startsWith(System.getProperty("java.io.tmpdir")));
+ assertThat(cacheTest.getAbsolutePath(), endsWith("android-external-cache" + File.separator + "__test__"));
FileOutputStream fos = null;
try {
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/ContextWrapperTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/ContextWrapperTest.java
index 8c2663629..e90241846 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/ContextWrapperTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/ContextWrapperTest.java
@@ -1,6 +1,7 @@
package com.xtremelabs.robolectric.shadows;
import android.app.Activity;
+import android.app.Application;
import android.appwidget.AppWidgetProvider;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -196,4 +197,9 @@ public class ContextWrapperTest {
}
return larryIntentFilter;
}
+
+ @Test
+ public void packageManagerShouldNotBeNullWhenWrappingAnApplication() {
+ assertThat(new Application().getPackageManager(), notNullValue());
+ }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/DateFormatTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/DateFormatTest.java
new file mode 100644
index 000000000..cf3790a37
--- /dev/null
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/DateFormatTest.java
@@ -0,0 +1,38 @@
+package com.xtremelabs.robolectric.shadows;
+
+import android.text.format.DateFormat;
+import com.xtremelabs.robolectric.TestRunners;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(TestRunners.WithDefaults.class)
+public class DateFormatTest {
+
+ @Test
+ public void getTimeFormat_returnsATimeFormat() {
+ Calendar cal = Calendar.getInstance();
+ cal.clear();
+ cal.set(Calendar.HOUR, 7);
+ cal.set(Calendar.MINUTE, 48);
+ cal.set(Calendar.SECOND, 3);
+ Date date = cal.getTime();
+ assertEquals("07:48:03", DateFormat.getTimeFormat(null).format(date));
+ }
+
+ @Test
+ public void getDateFormat_returnsADateFormat() {
+ Calendar cal = Calendar.getInstance();
+ cal.clear();
+ cal.set(Calendar.DATE, 12);
+ cal.set(Calendar.MONTH, Calendar.JANUARY);
+ cal.set(Calendar.YEAR, 1970);
+ Date date = cal.getTime();
+ assertEquals("Jan-12-1970", DateFormat.getDateFormat(null).format(date));
+ }
+
+}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/DefaultRequestDirectorTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/DefaultRequestDirectorTest.java
index f7a0daf38..0c99f547c 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/DefaultRequestDirectorTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/DefaultRequestDirectorTest.java
@@ -268,6 +268,26 @@ public class DefaultRequestDirectorTest {
}
@Test
+ public void getNextSentHttpRequestInfo_shouldRemoveHttpRequestInfos() throws Exception {
+ Robolectric.addPendingHttpResponse(200, "a happy response body");
+ HttpGet httpGet = new HttpGet("http://example.com");
+ requestDirector.execute(null, httpGet, null);
+
+ assertSame(Robolectric.getNextSentHttpRequestInfo().getHttpRequest(), httpGet);
+ assertNull(Robolectric.getNextSentHttpRequestInfo());
+ }
+
+ @Test
+ public void getNextSentHttpRequest_shouldRemoveHttpRequests() throws Exception {
+ Robolectric.addPendingHttpResponse(200, "a happy response body");
+ HttpGet httpGet = new HttpGet("http://example.com");
+ requestDirector.execute(null, httpGet, null);
+
+ assertSame(Robolectric.getNextSentHttpRequest(), httpGet);
+ assertNull(Robolectric.getNextSentHttpRequest());
+ }
+
+ @Test
public void shouldSupportBasicResponseHandlerHandleResponse() throws Exception {
Robolectric.addPendingHttpResponse(200, "OK", new BasicHeader("Content-Type", "text/plain"));
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/DialogTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/DialogTest.java
index 31a17e36d..7934981ef 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/DialogTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/DialogTest.java
@@ -1,8 +1,10 @@
package com.xtremelabs.robolectric.shadows;
+import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
+import android.view.View;
import android.widget.TextView;
import com.xtremelabs.robolectric.R;
import com.xtremelabs.robolectric.Robolectric;
@@ -17,6 +19,7 @@ import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
@RunWith(TestRunners.WithDefaults.class)
@@ -40,6 +43,18 @@ public class DialogTest {
}
@Test
+ public void setContentViewWithViewAllowsFindById() throws Exception {
+ final int viewId = 1234;
+ Activity context = new Activity();
+ final Dialog dialog = new Dialog(context);
+ final View view = new View(context);
+ view.setId(viewId);
+ dialog.setContentView(view);
+
+ assertSame(view, dialog.findViewById(viewId));
+ }
+
+ @Test
public void shouldGetLayoutInflater() {
Dialog dialog = new Dialog(Robolectric.application);
assertNotNull(dialog.getLayoutInflater());
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/DisplayTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/DisplayTest.java
index 32fb52a9b..e89e5c35a 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/DisplayTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/DisplayTest.java
@@ -7,6 +7,8 @@ import com.xtremelabs.robolectric.TestRunners;
import org.junit.Test;
import org.junit.runner.RunWith;
+import static com.xtremelabs.robolectric.Robolectric.newInstanceOf;
+import static com.xtremelabs.robolectric.Robolectric.shadowOf;
import static org.junit.Assert.assertEquals;
@RunWith(TestRunners.WithDefaults.class)
@@ -14,8 +16,8 @@ public class DisplayTest {
@Test
public void shouldProvideDisplayMetrics() throws Exception {
- Display display = Robolectric.newInstanceOf(Display.class);
- ShadowDisplay shadow = Robolectric.shadowOf(display);
+ Display display = newInstanceOf(Display.class);
+ ShadowDisplay shadow = shadowOf(display);
shadow.setDensity(1.5f);
shadow.setDensityDpi(DisplayMetrics.DENSITY_MEDIUM);
@@ -38,4 +40,16 @@ public class DisplayTest {
assertEquals(184.0f, metrics.ydpi, 0.05);
}
+ /**
+ * The {@link android.view.Display#getOrientation()} method is deprecated, but for
+ * testing purposes, return the value gotten from {@link android.view.Display#getRotation()}
+ */
+ @Test
+ public void deprecatedGetOrientation_returnsGetRotation() {
+ Display display = newInstanceOf(Display.class);
+ int testValue = 33;
+ shadowOf(display).setRotation(testValue);
+ assertEquals(testValue, display.getOrientation());
+ }
+
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/EditTextTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/EditTextTest.java
index 16ef9108e..e63567258 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/EditTextTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/EditTextTest.java
@@ -1,7 +1,11 @@
package com.xtremelabs.robolectric.shadows;
+import android.app.Activity;
+import android.content.Context;
import android.util.AttributeSet;
+import android.view.LayoutInflater;
import android.widget.EditText;
+import com.xtremelabs.robolectric.R;
import com.xtremelabs.robolectric.Robolectric;
import com.xtremelabs.robolectric.TestRunners;
import org.junit.Test;
@@ -100,4 +104,12 @@ public class EditTextTest {
when(attrs.getAttributeIntValue("android", "maxLength", Integer.MAX_VALUE)).thenReturn(Integer.MAX_VALUE);
return attrs;
}
+
+ @Test
+ public void shouldGetHintFromXml() {
+ Context context = new Activity();
+ LayoutInflater inflater = LayoutInflater.from(context);
+ EditText editText = (EditText) inflater.inflate(R.layout.edit_text, null);
+ assertThat(editText.getHint().toString(), equalTo("Hello, Hint"));
+ }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/FrameLayoutTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/FrameLayoutTest.java
index 8fe210458..00bf216a6 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/FrameLayoutTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/FrameLayoutTest.java
@@ -30,4 +30,11 @@ public class FrameLayoutTest {
ViewGroup.LayoutParams layoutParams = frameLayout.getLayoutParams();
assertThat(layoutParams, instanceOf(ViewGroup.MarginLayoutParams.class));
}
+
+ @Test
+ public void getLayoutParams_shouldReturnFrameLayoutParams() throws Exception {
+ ViewGroup.LayoutParams layoutParams = new FrameLayout(null).getLayoutParams();
+
+ assertThat(layoutParams, instanceOf(FrameLayout.LayoutParams.class));
+ }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/HtmlTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/HtmlTest.java
index 4bf3f08a0..d4853c252 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/HtmlTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/HtmlTest.java
@@ -4,6 +4,7 @@ package com.xtremelabs.robolectric.shadows;
import android.app.Activity;
import android.content.Context;
import android.text.Html;
+import android.text.Spanned;
import android.widget.EditText;
import android.widget.TextView;
import com.xtremelabs.robolectric.TestRunners;
@@ -12,6 +13,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
@RunWith(TestRunners.WithDefaults.class)
@@ -41,4 +43,10 @@ public class HtmlTest {
public void shouldThrowNullPointerExceptionWhenNullStringEncountered() throws Exception {
Html.fromHtml(null);
}
+
+ public void fromHtml_shouldJustReturnArgByDefault() {
+ String text = "<b>foo</b>";
+ Spanned spanned = Html.fromHtml(text);
+ assertEquals(text, spanned.toString());
+ }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/ImageButtonTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/ImageButtonTest.java
new file mode 100644
index 000000000..81e9ada7e
--- /dev/null
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/ImageButtonTest.java
@@ -0,0 +1,20 @@
+package com.xtremelabs.robolectric.shadows;
+
+import android.widget.ImageButton;
+import com.xtremelabs.robolectric.Robolectric;
+import com.xtremelabs.robolectric.TestRunners;
+import com.xtremelabs.robolectric.tester.android.util.TestAttributeSet;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+@RunWith(TestRunners.WithDefaults.class)
+public class ImageButtonTest {
+ @Test
+ public void testBackground() throws Exception {
+ ImageButton button = new ImageButton(Robolectric.application, new TestAttributeSet());
+ assertThat(button.getBackground(), notNullValue());
+ }
+}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/ImageViewTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/ImageViewTest.java
index 9b4e28241..eb60d8ed8 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/ImageViewTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/ImageViewTest.java
@@ -15,6 +15,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import static com.xtremelabs.robolectric.Robolectric.application;
import static com.xtremelabs.robolectric.Robolectric.shadowOf;
import static com.xtremelabs.robolectric.Robolectric.visualize;
import static org.hamcrest.CoreMatchers.equalTo;
@@ -68,6 +69,11 @@ public class ImageViewTest {
}
@Test
+ public void visualizeWithEmpty() throws Exception {
+ assertEquals("", Robolectric.visualize(new ImageView(application)));
+ }
+
+ @Test
public void testSetImageResource_drawable() {
imageView.setImageResource(R.drawable.l0_red);
assertTrue("Drawable", imageView.getDrawable() instanceof Drawable);
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/IntentTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/IntentTest.java
index 3436d0336..9657666e8 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/IntentTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/IntentTest.java
@@ -295,7 +295,7 @@ public class IntentTest {
String category = "category";
intentB.addCategory(category);
intentB.setPackage("com.foobar.app");
- ComponentName cn = new ComponentName("com.foobar.app", "activity");
+ ComponentName cn = new ComponentName("com.foobar.app", "fragmentActivity");
intentB.setComponent(cn);
intentB.putExtra("FOO", 23);
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/ListActivityTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/ListActivityTest.java
index c31ddabc4..46c6f641e 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/ListActivityTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/ListActivityTest.java
@@ -2,10 +2,12 @@ package com.xtremelabs.robolectric.shadows;
import android.app.ListActivity;
import android.view.View;
+import android.widget.FrameLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import com.xtremelabs.robolectric.Robolectric;
import com.xtremelabs.robolectric.TestRunners;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -18,9 +20,24 @@ import static org.hamcrest.MatcherAssert.assertThat;
@RunWith(TestRunners.WithDefaults.class)
public class ListActivityTest {
+ private ListActivity listActivity;
+ private FrameLayout content;
+ private ListView listView;
+
+ @Before
+ public void setUp() throws Exception {
+ listView = new ListView(listActivity);
+ listView.setId(android.R.id.list);
+
+ content = new FrameLayout(listActivity);
+ content.addView(listView);
+
+ listActivity = new ListActivity();
+ listActivity.setContentView(content);
+ }
+
@Test
public void shouldSupportSettingAndGettingListAdapter(){
- ListActivity listActivity = new ListActivity();
ListAdapter adapter = new CountingAdapter(5);
listActivity.setListAdapter(adapter);
@@ -29,6 +46,8 @@ public class ListActivityTest {
@Test
public void shouldSupportOnItemClick() throws Exception {
+ listActivity.setContentView(null);
+
final boolean[] clicked = new boolean[1];
ListActivity listActivity = new ListActivity() {
@Override
@@ -36,7 +55,7 @@ public class ListActivityTest {
clicked[0] = true;
}
};
- listActivity.setContentView(new ListView(null));
+ listActivity.setContentView(content);
listActivity.setListAdapter(new CountingAdapter(5));
Robolectric.shadowOf(listActivity.getListView()).performItemClick(0);
assertTrue(clicked[0]);
@@ -44,11 +63,14 @@ public class ListActivityTest {
@Test
public void shouldSetAdapterOnListView() throws Exception {
- ListActivity listActivity = new ListActivity();
ListAdapter adapter = new CountingAdapter(5);
- final ListView listView = new ListView(null);
- listActivity.setContentView(listView);
listActivity.setListAdapter(adapter);
assertThat(listView.getAdapter(), sameInstance(adapter));
}
+
+ @Test(expected = RuntimeException.class)
+ public void whenNoViewWithListIdExists_shouldRaiseException(){
+ ListActivity listActivity = new ListActivity();
+ listActivity.setListAdapter(new CountingAdapter(5));
+ }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/LocalActivityManagerTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/LocalActivityManagerTest.java
new file mode 100644
index 000000000..716392d90
--- /dev/null
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/LocalActivityManagerTest.java
@@ -0,0 +1,31 @@
+package com.xtremelabs.robolectric.shadows;
+
+import android.app.Activity;
+import android.os.Bundle;
+import com.xtremelabs.robolectric.R;
+import com.xtremelabs.robolectric.TestRunners;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertNotNull;
+
+@RunWith(TestRunners.WithDefaults.class)
+public class LocalActivityManagerTest {
+ @Test
+ public void testInflation() throws Exception {
+ OuterActivity activity = new OuterActivity();
+ activity.onCreate(null);
+ // Make sure the container lookup works.
+ assertNotNull(activity.findViewById(R.id.lam_container));
+ // And make sure the view inside the LocalActivityManager-created view works too.
+ assertNotNull(activity.findViewById(R.id.lam_inner_contents));
+ }
+
+ private class OuterActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.lam_outer);
+ }
+ }
+}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/LocationTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/LocationTest.java
index 4a72dcd56..3a61c37aa 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/LocationTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/LocationTest.java
@@ -3,13 +3,13 @@ package com.xtremelabs.robolectric.shadows;
import android.location.Location;
import android.location.LocationManager;
import com.xtremelabs.robolectric.TestRunners;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.*;
+import static org.junit.Assert.assertArrayEquals;
@RunWith(TestRunners.WithDefaults.class)
public class LocationTest {
@@ -18,6 +18,8 @@ public class LocationTest {
@Before
public void setUp() throws Exception {
+ ShadowLocation.setDistanceBetween(null);
+
location = new Location(LocationManager.GPS_PROVIDER);
location.setTime(1);
location.setLatitude(2);
@@ -28,6 +30,11 @@ public class LocationTest {
location.setAltitude(3.0d);
}
+ @After
+ public void tearDown() {
+ ShadowLocation.setDistanceBetween(null);
+ }
+
@Test
public void test_copyConstructor() throws Exception {
Location copiedLocation = new Location(location);
@@ -118,4 +125,44 @@ public class LocationTest {
assertEquals(location, l);
}
+
+ @Test
+ public void testDistanceBetween_preventNPE() {
+ Location.distanceBetween(1.0, 1.0, 1.0, 1.0, new float[2]);
+ }
+
+ @Test
+ public void testDistanceBetween_shouldBeMockable() {
+ float[] expectedDistance = {2.2f, 5.2f};
+ ShadowLocation.setDistanceBetween(expectedDistance);
+ float[] actualDistance = new float[2];
+ Location.distanceBetween(1.0, 1.0, 1.0, 1.0, actualDistance);
+ assertArrayEquals(expectedDistance, actualDistance, 0f);
+ }
+
+ @Test
+ public void testDistanceBetweenMocking_requiresArraysOfEqualLength() {
+ float[] expectedDistance = {2.2f, 5.2f};
+ ShadowLocation.setDistanceBetween(expectedDistance);
+ float[] actualDistance = new float[1];
+ Location.distanceBetween(1.0, 1.0, 1.0, 1.0, actualDistance);
+ assertArrayEquals(new float[]{0.0f}, actualDistance, 0f);
+ }
+
+ @Test
+ public void gettersAndSetters_shouldWork() {
+ Location l = new Location("gps");
+ l.setLatitude(1.0);
+ l.setLongitude(2.0);
+ l.setAltitude(3.0);
+ l.setAccuracy(4.0f);
+ l.setBearing(5.0f);
+ l.setSpeed(6.0f);
+ assertEquals(1.0, l.getLatitude(), 0.0);
+ assertEquals(2.0, l.getLongitude(), 0.0);
+ assertEquals(3.0, l.getAltitude(), 0.0);
+ assertEquals(4.0f, l.getAccuracy(), 0.0);
+ assertEquals(5.0f, l.getBearing(), 0.0);
+ assertEquals(6.0f, l.getSpeed(), 0.0);
+ }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/NotificationManagerTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/NotificationManagerTest.java
index fe14f3666..163a13012 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/NotificationManagerTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/NotificationManagerTest.java
@@ -27,11 +27,11 @@ public class NotificationManagerTest {
public void testNotify() throws Exception {
notificationManager.notify(1, notification1);
assertEquals(1, shadowOf(notificationManager).size());
- assertEquals(notification1, shadowOf(notificationManager).getNotification(1));
+ assertEquals(notification1, shadowOf(notificationManager).getNotification(null, 1));
notificationManager.notify(31, notification2);
assertEquals(2, shadowOf(notificationManager).size());
- assertEquals(notification2, shadowOf(notificationManager).getNotification(31));
+ assertEquals(notification2, shadowOf(notificationManager).getNotification(null, 31));
}
@Test
@@ -40,28 +40,28 @@ public class NotificationManagerTest {
notificationManager.notify(1, notification2);
assertEquals(1, shadowOf(notificationManager).size());
- assertEquals(notification2, shadowOf(notificationManager).getNotification(1));
+ assertEquals(notification2, shadowOf(notificationManager).getNotification(null, 1));
}
@Test
public void testNotifyWithTag() throws Exception {
notificationManager.notify("a tag", 1, notification1);
assertEquals(1, shadowOf(notificationManager).size());
- assertEquals(notification1, shadowOf(notificationManager).getNotification("a tag"));
+ assertEquals(notification1, shadowOf(notificationManager).getNotification("a tag", 1));
}
@Test
public void notifyWithTag_shouldReturnNullForNullTag() throws Exception {
notificationManager.notify("a tag", 1, notification1);
assertEquals(1, shadowOf(notificationManager).size());
- assertNull(shadowOf(notificationManager).getNotification(null));
+ assertNull(shadowOf(notificationManager).getNotification(null, 1));
}
@Test
public void notifyWithTag_shouldReturnNullForUnknownTag() throws Exception {
notificationManager.notify("a tag", 1, notification1);
assertEquals(1, shadowOf(notificationManager).size());
- assertNull(shadowOf(notificationManager).getNotification("unknown tag"));
+ assertNull(shadowOf(notificationManager).getNotification("unknown tag", 1));
}
@Test
@@ -70,7 +70,7 @@ public class NotificationManagerTest {
notificationManager.cancel(1);
assertEquals(0, shadowOf(notificationManager).size());
- assertNull(shadowOf(notificationManager).getNotification(1));
+ assertNull(shadowOf(notificationManager).getNotification(null, 1));
}
@Test
@@ -79,8 +79,8 @@ public class NotificationManagerTest {
notificationManager.cancel("a tag", 1);
assertEquals(0, shadowOf(notificationManager).size());
- assertNull(shadowOf(notificationManager).getNotification(1));
- assertNull(shadowOf(notificationManager).getNotification("a tag"));
+ assertNull(shadowOf(notificationManager).getNotification(null, 1));
+ assertNull(shadowOf(notificationManager).getNotification("a tag", 1));
}
@Test
@@ -90,7 +90,7 @@ public class NotificationManagerTest {
notificationManager.cancelAll();
assertEquals(0, shadowOf(notificationManager).size());
- assertNull(shadowOf(notificationManager).getNotification(1));
- assertNull(shadowOf(notificationManager).getNotification(31));
+ assertNull(shadowOf(notificationManager).getNotification(null, 1));
+ assertNull(shadowOf(notificationManager).getNotification(null, 31));
}
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/PreferenceActivityTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/PreferenceActivityTest.java
index 0ee0f37d5..274fd3f6b 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/PreferenceActivityTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/PreferenceActivityTest.java
@@ -4,6 +4,7 @@ import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import com.xtremelabs.robolectric.TestRunners;
@@ -13,52 +14,64 @@ import org.junit.runner.RunWith;
import android.app.Activity;
import android.preference.PreferenceActivity;
-import android.widget.ListView;
-
import com.xtremelabs.robolectric.R;
import com.xtremelabs.robolectric.Robolectric;
@RunWith(TestRunners.WithDefaults.class)
public class PreferenceActivityTest {
- private TestPreferenceActivity activity;
- private ShadowPreferenceActivity shadow;
-
+ private TestPreferenceActivity activity;
+ private ShadowPreferenceActivity shadow;
+
@Before
public void setUp() throws Exception {
- activity = new TestPreferenceActivity();
- shadow = Robolectric.shadowOf(activity);
+ activity = new TestPreferenceActivity();
+ shadow = Robolectric.shadowOf(activity);
+ }
+
+ @Test
+ public void shouldInitializeListViewInOnCreate() {
+ shadow.callOnCreate(null);
+ assertThat(activity.getListView(), notNullValue());
+ }
+
+ @Test
+ public void shouldInheritFromListActivity() {
+ assertThat(shadow, instanceOf(ShadowListActivity.class));
+ }
+
+ @Test
+ public void shouldNotInitializePreferenceScreen() {
+ assertThat(activity.getPreferenceScreen(), nullValue());
+ }
+
+ @Test
+ public void shouldRecordPreferencesResourceId() {
+ assertThat(shadow.getPreferencesResId(), equalTo(-1));
+ activity.addPreferencesFromResource(R.xml.preferences);
+ assertThat(shadow.getPreferencesResId(), equalTo(R.xml.preferences));
+ }
+
+ @Test
+ public void shouldLoadPreferenceScreen() {
+ activity.addPreferencesFromResource(R.xml.preferences);
+ assertThat(activity.getPreferenceScreen().getPreferenceCount(), equalTo(7));
}
-
+
@Test
- public void shouldGetListView() {
- shadow.setListView( new ListView( new Activity() ) );
- assertThat( activity.getListView(), notNullValue() );
+ public void shouldFindPreferences() {
+ activity.addPreferencesFromResource(R.xml.preferences);
+ assertNotNull(activity.findPreference("category"));
+ assertNotNull(activity.findPreference("inside_category"));
+ assertNotNull(activity.findPreference("screen"));
+ assertNotNull(activity.findPreference("inside_screen"));
+ assertNotNull(activity.findPreference("checkbox"));
+ assertNotNull(activity.findPreference("edit_text"));
+ assertNotNull(activity.findPreference("list"));
+ assertNotNull(activity.findPreference("preference"));
+ assertNotNull(activity.findPreference("ringtone"));
+ }
+
+ private static class TestPreferenceActivity extends PreferenceActivity {
}
-
- @Test
- public void shouldInheritFromListActivity() {
- assertThat(shadow, instanceOf(ShadowListActivity.class));
- }
-
- @Test
- public void shouldNotInitializePreferenceScreen() {
- assertThat(activity.getPreferenceScreen(), nullValue());
- }
-
- @Test
- public void shouldRecordPreferencesResourceId() {
- assertThat(shadow.getPreferencesResId(), equalTo(-1));
- activity.addPreferencesFromResource(R.xml.preferences);
- assertThat(shadow.getPreferencesResId(), equalTo(R.xml.preferences));
- }
-
- @Test
- public void shouldLoadPreferenceScreen() {
- activity.addPreferencesFromResource(R.xml.preferences);
- assertThat( activity.getPreferenceScreen().getPreferenceCount(), equalTo(6));
- }
-
- private static class TestPreferenceActivity extends PreferenceActivity {
- }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/ResolveInfoTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/ResolveInfoTest.java
index 7dc976cc3..3e581ba2d 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/ResolveInfoTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/ResolveInfoTest.java
@@ -20,7 +20,7 @@ public class ResolveInfoTest {
@Before
public void setup() {
- mResolveInfo = ShadowResolveInfo.newResolveInfo("name", "package", "activity");
+ mResolveInfo = ShadowResolveInfo.newResolveInfo("name", "package", "fragmentActivity");
mShadowInfo = Robolectric.shadowOf(mResolveInfo);
}
@@ -35,6 +35,6 @@ public class ResolveInfoTest {
assertThat(mResolveInfo.loadLabel(null).toString(), equalTo("name"));
assertThat(mResolveInfo.activityInfo.packageName, equalTo("package"));
assertThat(mResolveInfo.activityInfo.applicationInfo.packageName, equalTo("package"));
- assertThat(mResolveInfo.activityInfo.name, equalTo("activity"));
+ assertThat(mResolveInfo.activityInfo.name, equalTo("fragmentActivity"));
}
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/ResourcesTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/ResourcesTest.java
index 2455477dc..29601baee 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/ResourcesTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/ResourcesTest.java
@@ -1,6 +1,7 @@
package com.xtremelabs.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.XmlResourceParser;
@@ -19,12 +20,8 @@ import org.junit.runner.RunWith;
import org.xmlpull.v1.XmlPullParser;
import static com.xtremelabs.robolectric.Robolectric.shadowOf;
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.instanceOf;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
@RunWith(TestRunners.WithDefaults.class)
@@ -36,9 +33,9 @@ public class ResourcesTest {
@Before
public void setup() {
resources = new Activity().getResources();
- shadowApp = shadowOf( Robolectric.application );
+ shadowApp = shadowOf( Robolectric.application );
}
-
+
@Test(expected = Resources.NotFoundException.class)
public void getStringArray_shouldThrowExceptionIfNotFound() throws Exception {
resources.getStringArray(-1);
@@ -61,6 +58,16 @@ public class ResourcesTest {
assertThat(resources.newTheme(), notNullValue());
}
+ @Test
+ public void testGetAndSetConfiguration_SameInstance() throws Exception {
+ Activity activity = new Activity();
+ Resources resources = activity.getResources();
+ assertSame(resources.getConfiguration(), resources.getConfiguration());
+ Configuration diffConfig = new Configuration();
+ shadowOf(resources).setConfiguration(diffConfig);
+ assertSame(diffConfig, resources.getConfiguration());
+ }
+
/**
* a missing R.class will result in an BitmapDrawable getting returned
* by default
@@ -70,7 +77,7 @@ public class ResourcesTest {
shadowApp.getResourceLoader().setLocalRClass( null );
assertThat( resources.getDrawable( TestR.anim.test_anim_1 ), instanceOf( BitmapDrawable.class ) );
}
-
+
/**
* given an R.anim.id value, will return an AnimationDrawable
*/
@@ -84,7 +91,7 @@ public class ResourcesTest {
@Values( qualifiers="fr" )
public void testGetValuesResFromSpecifiecQualifiers(){
String hello=resources.getString( R.string.hello );
- assertThat( hello, equalTo( "Bonjour" ) );
+ assertThat( hello, equalTo("Bonjour") );
}
/**
@@ -93,7 +100,25 @@ public class ResourcesTest {
@Test
public void testGetColorDrawable() {
shadowApp.getResourceLoader().setLocalRClass( TestR.class );
- assertThat( resources.getDrawable( TestR.color.test_color_1 ), instanceOf( ColorDrawable.class ) );
+ assertThat( resources.getDrawable( TestR.color.test_color_1 ), instanceOf( ColorDrawable.class ) );
+ }
+
+ /**
+ * given an R.color.id value, will return a Color
+ */
+ @Test
+ public void testGetColor() {
+ shadowApp.getResourceLoader().setLocalRClass( TestR.class );
+ assertThat( resources.getColor( TestR.color.test_color_1 ), not( 0 ) );
+ }
+
+ /**
+ * given an R.color.id value, will return a ColorStateList
+ */
+ @Test
+ public void testGetColorStateList() {
+ shadowApp.getResourceLoader().setLocalRClass( TestR.class );
+ assertThat( resources.getColorStateList( TestR.color.test_color_1 ), instanceOf( ColorStateList.class ) );
}
/**
@@ -101,16 +126,16 @@ public class ResourcesTest {
*/
@Test
public void testGetBitmapDrawable() {
- shadowApp.getResourceLoader().setLocalRClass( TestR.class );
- assertThat( resources.getDrawable( TestR.drawable.test_drawable_1 ), instanceOf( BitmapDrawable.class ) );
+ shadowApp.getResourceLoader().setLocalRClass( TestR.class );
+ assertThat( resources.getDrawable( TestR.drawable.test_drawable_1 ), instanceOf( BitmapDrawable.class ) );
}
-
+
/**
* given an R.drawable.id value, will return a NinePatchDrawable for .9.png file
*/
@Test
public void testGetNinePatchDrawable() {
- assertThat(resources.getDrawable(R.drawable.nine_patch_drawable ), instanceOf(NinePatchDrawable.class ) );
+ assertThat(resources.getDrawable(R.drawable.nine_patch_drawable ), instanceOf(NinePatchDrawable.class ) );
}
/**
@@ -118,8 +143,8 @@ public class ResourcesTest {
*/
@Test
public void testGetBitmapDrawableForUnknownId() {
- shadowApp.getResourceLoader().setLocalRClass( TestR.class );
- assertThat(resources.getDrawable( Integer.MAX_VALUE ), instanceOf( BitmapDrawable.class ));
+ shadowApp.getResourceLoader().setLocalRClass( TestR.class );
+ assertThat(resources.getDrawable( Integer.MAX_VALUE ), instanceOf( BitmapDrawable.class ));
}
@Test
public void testDensity() {
@@ -139,6 +164,40 @@ public class ResourcesTest {
assertThat(activity.getResources().getDisplayMetrics().heightPixels, equalTo(800));
assertThat(activity.getResources().getDisplayMetrics().widthPixels, equalTo(480));
}
+
+ @Test
+ public void getSystemShouldReturnSystemResources() throws Exception {
+ assertThat(Resources.getSystem(), instanceOf(Resources.class));
+ }
+
+ @Test
+ public void multipleCallsToGetSystemShouldReturnSameInstance() throws Exception {
+ assertThat(Resources.getSystem(), equalTo(Resources.getSystem()));
+ }
+
+ @Test
+ public void applicationResourcesShouldHaveBothSystemAndLocalValues() throws Exception {
+ Activity activity = new Activity();
+ assertThat(activity.getResources().getString(android.R.string.copy), equalTo("Copy"));
+ assertThat(activity.getResources().getString(R.string.copy), equalTo("Local Copy"));
+ }
+
+ @Test
+ public void systemResourcesShouldHaveSystemValuesOnly() throws Exception {
+ assertThat(Resources.getSystem().getString(android.R.string.copy), equalTo("Copy"));
+ assertThat(Resources.getSystem().getString(R.string.copy), nullValue());
+ }
+
+ @Test
+ public void systemResourcesShouldReturnCorrectSystemId() throws Exception {
+ assertThat(Resources.getSystem().getIdentifier("copy", "android:string", null),
+ equalTo(android.R.string.copy));
+ }
+
+ @Test
+ public void systemResourcesShouldReturnZeroForLocalId() throws Exception {
+ assertThat(Resources.getSystem().getIdentifier("copy", "string", null), equalTo(0));
+ }
@Test
public void testGetXml() throws Exception {
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/SensorManagerTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/SensorManagerTest.java
index bac93e993..a608d0753 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/SensorManagerTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/SensorManagerTest.java
@@ -68,6 +68,13 @@ public class SensorManagerTest {
assertTrue(shadow.createSensorEvent() instanceof SensorEvent);
}
+ @Test
+ public void getSensor_shouldBeConfigurable() {
+ Sensor sensor = Robolectric.newInstanceOf(Sensor.class);
+ shadowOf(sensorManager).addSensor(Sensor.TYPE_ACCELEROMETER, sensor);
+ assertSame(sensor, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER));
+ }
+
private class TestSensorEventListener implements SensorEventListener {
@Override
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/ShadowEditTextTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/ShadowEditTextTest.java
index 915364309..17b5f4521 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/ShadowEditTextTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/ShadowEditTextTest.java
@@ -4,6 +4,7 @@ import android.widget.EditText;
import com.xtremelabs.robolectric.Robolectric;
import com.xtremelabs.robolectric.TestRunners;
import com.xtremelabs.robolectric.tester.android.util.TestAttributeSet;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -14,13 +15,25 @@ import static org.junit.Assert.assertThat;
@RunWith(TestRunners.WithDefaults.class)
public class ShadowEditTextTest {
- @Test
- public void shouldRespectMaxLength() throws Exception {
+ private EditText editText;
+
+ @Before
+ public void setup() {
HashMap<String, String> hash = new HashMap<String, String>();
hash.put("android:maxLength", "5");
TestAttributeSet attributeSet = new TestAttributeSet(hash);
- EditText editText = new EditText(Robolectric.application, attributeSet);
+ editText = new EditText(Robolectric.application, attributeSet);
+ }
+
+ @Test
+ public void shouldRespectMaxLength() throws Exception {
editText.setText("0123456678");
assertThat(editText.getText().toString(), equalTo("01234"));
}
+
+ @Test
+ public void shouldAcceptNullStrings() {
+ editText.setText(null);
+ assertThat(editText.getText().toString(), equalTo(""));
+ }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/SpannableStringBuilderTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/SpannableStringBuilderTest.java
index 889e752b5..d925a4232 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/SpannableStringBuilderTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/SpannableStringBuilderTest.java
@@ -32,11 +32,18 @@ public class SpannableStringBuilderTest {
}
@Test
+ public void testReplaceFromSquare() throws Exception {
+ SpannableStringBuilder builder = new SpannableStringBuilder("abcd");
+ builder.replace(1,3,"XXX");
+ assertThat(builder.toString(), equalTo("aXXXd"));
+ }
+
+ @Test
public void testInsert() throws Exception {
SpannableStringBuilder builder = new SpannableStringBuilder("abc");
assertThat(builder.insert(1, "xy").toString(), equalTo("axybc"));
}
-
+
@Test
public void testDelete() throws Exception {
SpannableStringBuilder builder = new SpannableStringBuilder("abc");
@@ -44,4 +51,11 @@ public class SpannableStringBuilderTest {
builder.delete( 0, 3 );
assertThat( builder.length(), equalTo(0));
}
+
+ @Test
+ public void testReplace_extraParams() throws Exception {
+ SpannableStringBuilder builder = new SpannableStringBuilder("abcd");
+ builder.replace(1,3,"ignoreXXXignore", 6, 9);
+ assertThat(builder.toString(), equalTo("aXXXd"));
+ }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/SpannedStringTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/SpannedStringTest.java
new file mode 100644
index 000000000..74895b0d7
--- /dev/null
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/SpannedStringTest.java
@@ -0,0 +1,33 @@
+package com.xtremelabs.robolectric.shadows;
+
+import android.text.SpannedString;
+import com.xtremelabs.robolectric.TestRunners;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+@RunWith(TestRunners.WithDefaults.class)
+public class SpannedStringTest {
+
+ @Test
+ public void toString_shouldDelegateToUnderlyingCharSequence() {
+ SpannedString spannedString = new SpannedString("foo");
+ assertEquals("foo", spannedString.toString());
+ }
+
+ @Test
+ public void valueOfSpannedString_shouldReturnItself() {
+ SpannedString spannedString = new SpannedString("foo");
+ assertSame(spannedString, SpannedString.valueOf(spannedString));
+ }
+
+ @Test
+ public void valueOfCharSequence_shouldReturnNewSpannedString() {
+ assertEquals("foo", SpannedString.valueOf("foo").toString());
+ }
+
+
+}
+
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/TextUtilsTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/TextUtilsTest.java
index 3b9a2ebea..cb28c7f0a 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/TextUtilsTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/TextUtilsTest.java
@@ -1,5 +1,6 @@
package com.xtremelabs.robolectric.shadows;
+import android.text.TextPaint;
import android.text.TextUtils;
import com.xtremelabs.robolectric.TestRunners;
@@ -80,4 +81,10 @@ public class TextUtilsTest {
assertThat(TextUtils.equals("a", "ab"), equalTo(false));
assertThat(TextUtils.equals("ab", "a"), equalTo(false));
}
+
+ @Test public void testEllipsize() {
+ TextPaint p = new TextPaint();
+ assertThat(TextUtils.ellipsize("apples", p, 100, TextUtils.TruncateAt.END).toString(), equalTo("apples"));
+ assertThat(TextUtils.ellipsize("", p, 100, TextUtils.TruncateAt.END).toString(), equalTo(""));
+ }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/TextViewTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/TextViewTest.java
index a157e8a63..ae9e3deca 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/TextViewTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/TextViewTest.java
@@ -150,14 +150,14 @@ public class TextViewTest {
view.setTransformationMethod(new ShadowPasswordTransformationMethod());
assertEquals(view.getTransformationMethod().getClass(), ShadowPasswordTransformationMethod.class);
}
-
+
@Test
public void testGetInputType() throws Exception {
assertThat(textView.getInputType(), not(equalTo(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD)));
textView.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
assertThat(textView.getInputType(), equalTo(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD));
}
-
+
@Test
public void givenATextViewWithATextWatcherAdded_WhenSettingTextWithTextResourceId_ShouldNotifyTextWatcher() {
MockTextWatcher mockTextWatcher = new MockTextWatcher();
@@ -167,7 +167,7 @@ public class TextViewTest {
assertEachTextWatcherEventWasInvoked(mockTextWatcher);
}
-
+
@Test
public void givenATextViewWithATextWatcherAdded_WhenSettingTextWithCharSequence_ShouldNotifyTextWatcher() {
MockTextWatcher mockTextWatcher = new MockTextWatcher();
@@ -234,6 +234,7 @@ public class TextViewTest {
assertThat(mockTextWatcher.afterTextChangeArgument.toString(), equalTo(NEW_TEXT));
}
+
@Test
public void whenAppendingText_ShouldAppendNewTextAfterOldOne() {
textView.setText(INITIAL_TEXT);
@@ -386,6 +387,26 @@ public class TextViewTest {
assertFalse(textView.hasSelection());
}
+ @Test
+ public void whenSettingTextToNull_WatchersSeeEmptyString() {
+ TextWatcher mockTextWatcher = mock(TextWatcher.class);
+ textView.addTextChangedListener(mockTextWatcher);
+ textView.setText(null);
+ verify(mockTextWatcher).onTextChanged("", 0, 0, 0);
+ }
+
+ @Test
+ public void getPaint_returnsNonNull() {
+ assertNotNull(textView.getPaint());
+ }
+
+ @Test
+ public void testNoArgAppend() {
+ textView.setText("a");
+ textView.append("b");
+ assertThat(textView.getText().toString(), equalTo("ab"));
+ }
+
private List<MockTextWatcher> anyNumberOfTextWatchers() {
List<MockTextWatcher> mockTextWatchers = new ArrayList<MockTextWatcher>();
int numberBetweenOneAndTen = new Random().nextInt(10) + 1;
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/TypedArrayTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/TypedArrayTest.java
index 0a87c9c65..6b693cff6 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/TypedArrayTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/TypedArrayTest.java
@@ -11,6 +11,7 @@ import org.junit.runner.RunWith;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertNotNull;
@RunWith(TestRunners.WithDefaults.class)
public class TypedArrayTest {
@@ -28,4 +29,29 @@ public class TypedArrayTest {
assertThat(array.getString(0), equalTo("expected value"));
}
+
+ @Test
+ public void getResources() throws Exception {
+ assertNotNull(context.obtainStyledAttributes(null).getResources());
+ }
+
+ @Test
+ public void getInt_shouldReturnDefaultValue() throws Exception {
+ assertThat(context.obtainStyledAttributes(null).getInt(1, -1), equalTo(-1));
+ }
+
+ @Test
+ public void getInteger_shouldReturnDefaultValue() throws Exception {
+ assertThat(context.obtainStyledAttributes(null).getInteger(1, -1), equalTo(-1));
+ }
+
+ @Test
+ public void getResourceId_shouldReturnDefaultValue() throws Exception {
+ assertThat(context.obtainStyledAttributes(null).getResourceId(1, -1), equalTo(-1));
+ }
+
+ @Test
+ public void getDimension_shouldReturnDefaultValue() throws Exception {
+ assertThat(context.obtainStyledAttributes(null).getDimension(1, -1f), equalTo(-1f));
+ }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/ViewAnimatorTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/ViewAnimatorTest.java
index 81bba9be1..8c95411eb 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/ViewAnimatorTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/ViewAnimatorTest.java
@@ -1,6 +1,6 @@
package com.xtremelabs.robolectric.shadows;
-import android.app.Activity;
+import android.app.Application;
import android.view.View;
import android.widget.ViewAnimator;
import com.xtremelabs.robolectric.TestRunners;
@@ -9,36 +9,69 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
@RunWith(TestRunners.WithDefaults.class)
public class ViewAnimatorTest {
- protected ViewAnimator animator;
+
+ ViewAnimator viewAnimator;
+ Application application;
@Before
public void setUp() {
- animator = new ViewAnimator(new Activity());
+ application = new Application();
+ viewAnimator = new ViewAnimator(application);
+ }
+
+ @Test
+ public void getDisplayedChildWhenEmpty_shouldDefaultToZero() {
+ assertEquals(0, viewAnimator.getDisplayedChild());
+ }
+
+ @Test
+ public void getDisplayedChild_shouldDefaultToZero() {
+ viewAnimator.addView(new View(application));
+ assertEquals(0, viewAnimator.getDisplayedChild());
+ }
+
+ @Test
+ public void setDisplayedChild_shouldUpdateDisplayedChildIndex() {
+ viewAnimator.addView(new View(application));
+ viewAnimator.addView(new View(application));
+ viewAnimator.setDisplayedChild(2);
+ assertEquals(2, viewAnimator.getDisplayedChild());
+ }
+
+ @Test
+ public void getCurrentView_shouldWork() {
+ View view0 = new View(application);
+ View view1 = new View(application);
+ viewAnimator.addView(view0);
+ viewAnimator.addView(view1);
+ assertSame(view0, viewAnimator.getCurrentView());
+ viewAnimator.setDisplayedChild(1);
+ assertSame(view1, viewAnimator.getCurrentView());
}
@Test
- public void testHappyPath() {
- View v = new View(null);
- animator.addView(v);
-
- assertEquals(0, animator.getDisplayedChild());
- assertEquals(v, animator.getCurrentView());
+ public void showNext_shouldDisplayNextChild() {
+ viewAnimator.addView(new View(application));
+ viewAnimator.addView(new View(application));
+ assertEquals(0, viewAnimator.getDisplayedChild());
+ viewAnimator.showNext();
+ assertEquals(1, viewAnimator.getDisplayedChild());
+ viewAnimator.showNext();
+ assertEquals(0, viewAnimator.getDisplayedChild());
}
@Test
- public void testAnimatorHandlesCyclingViews() {
- View v1 = new View(null);
- View v2 = new View(null);
-
- animator.addView(v1);
- animator.addView(v2);
-
- animator.showNext();
-
- assertEquals(1, animator.getDisplayedChild());
- assertEquals(v2, animator.getCurrentView());
+ public void showPrevious_shouldDisplayPreviousChild() {
+ viewAnimator.addView(new View(application));
+ viewAnimator.addView(new View(application));
+ assertEquals(0, viewAnimator.getDisplayedChild());
+ viewAnimator.showPrevious();
+ assertEquals(1, viewAnimator.getDisplayedChild());
+ viewAnimator.showPrevious();
+ assertEquals(0, viewAnimator.getDisplayedChild());
}
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/ViewGroupTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/ViewGroupTest.java
index 7f3c3e4d0..4c3c216dd 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/ViewGroupTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/ViewGroupTest.java
@@ -7,7 +7,6 @@ import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.LayoutAnimationController;
import android.widget.FrameLayout;
-import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.xtremelabs.robolectric.R;
@@ -25,8 +24,7 @@ import java.io.PrintStream;
import static com.xtremelabs.robolectric.Robolectric.DEFAULT_SDK_VERSION;
import static com.xtremelabs.robolectric.Robolectric.shadowOf;
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.sameInstance;
+import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsNull.nullValue;
import static org.junit.Assert.*;
@@ -72,6 +70,11 @@ public class ViewGroupTest {
}
@Test
+ public void removeNullView_doesNothing() {
+ root.removeView(null);
+ }
+
+ @Test
public void testLayoutAnimationListener() {
assertThat(root.getLayoutAnimationListener(), nullValue());
@@ -89,7 +92,7 @@ public class ViewGroupTest {
assertThat(root.getLayoutAnimationListener(), sameInstance(animationListener));
}
-
+
@Test
public void testLayoutAnimation() {
assertThat(root.getLayoutAnimation(), nullValue());
@@ -242,11 +245,25 @@ public class ViewGroupTest {
public void addViewWithLayoutParams_shouldStoreLayoutParams() throws Exception {
FrameLayout.LayoutParams layoutParams1 = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
FrameLayout.LayoutParams layoutParams2 = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- ImageView child1 = new ImageView(Robolectric.application);
- ImageView child2 = new ImageView(Robolectric.application);
+ View child1 = new View(Robolectric.application);
+ View child2 = new View(Robolectric.application);
root.addView(child1, layoutParams1);
root.addView(child2, 1, layoutParams2);
assertSame(layoutParams1, child1.getLayoutParams());
assertSame(layoutParams2, child2.getLayoutParams());
}
+
+ @Test
+ public void getChildAt_shouldReturnNullForInvalidIndices() {
+ assertThat(root.getChildCount(), equalTo(3));
+ assertThat(root.getChildAt(13), nullValue());
+ assertThat(root.getChildAt(3), nullValue());
+ assertThat(root.getChildAt(-1), nullValue());
+ }
+
+ @Test
+ public void layoutParams_shouldBeViewGroupLayoutParams() {
+ assertThat(child1.getLayoutParams(), instanceOf(FrameLayout.LayoutParams.class));
+ assertThat(child1.getLayoutParams(), instanceOf(ViewGroup.LayoutParams.class));
+ }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/ViewTest.java b/src/test/java/com/xtremelabs/robolectric/shadows/ViewTest.java
index f2bc93d21..03c27ad3b 100644
--- a/src/test/java/com/xtremelabs/robolectric/shadows/ViewTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/ViewTest.java
@@ -2,8 +2,11 @@ package com.xtremelabs.robolectric.shadows;
import android.app.Activity;
import android.content.Context;
+import android.graphics.BitmapFactory;
import android.graphics.Point;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.MeasureSpec;
@@ -16,12 +19,16 @@ import android.widget.LinearLayout;
import com.xtremelabs.robolectric.R;
import com.xtremelabs.robolectric.Robolectric;
import com.xtremelabs.robolectric.TestRunners;
+import com.xtremelabs.robolectric.tester.android.util.TestAttributeSet;
+import com.xtremelabs.robolectric.tester.android.view.TestWindow;
import com.xtremelabs.robolectric.util.*;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.xtremelabs.robolectric.Robolectric.shadowOf;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static com.xtremelabs.robolectric.Robolectric.*;
import static junit.framework.Assert.assertEquals;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -30,9 +37,11 @@ import static org.junit.Assert.*;
@RunWith(TestRunners.WithDefaults.class)
public class ViewTest {
private View view;
+ private Transcript transcript;
@Before
public void setUp() throws Exception {
+ transcript = new Transcript();
view = new View(new Activity());
}
@@ -53,6 +62,38 @@ public class ViewTest {
}
@Test
+ public void measuredDimensions() throws Exception {
+ View view1 = new View(null) {
+ {
+ setMeasuredDimension(123, 456);
+ }
+ };
+ assertThat(view1.getMeasuredWidth(), equalTo(123));
+ assertThat(view1.getMeasuredHeight(), equalTo(456));
+ }
+
+ @Test
+ public void layout_shouldCallOnLayoutOnlyIfChanged() throws Exception {
+ View view1 = new View(null) {
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ transcript.add("onLayout " + changed + " " + left + " " + top + " " + right + " " + bottom);
+ }
+
+ @Override
+ public void invalidate() {
+ transcript.add("invalidate");
+ }
+ };
+ view1.layout(0, 0, 0, 0);
+ transcript.assertNoEventsSoFar();
+ view1.layout(1, 2, 3, 4);
+ transcript.assertEventsSoFar("invalidate", "onLayout true 1 2 3 4");
+ view1.layout(1, 2, 3, 4);
+ transcript.assertNoEventsSoFar();
+ }
+
+ @Test
public void shouldFocus() throws Exception {
final Transcript transcript = new Transcript();
@@ -175,6 +216,14 @@ public class ViewTest {
}
@Test
+ public void shouldRecordBackgroundDrawable() {
+ Drawable drawable = new BitmapDrawable(BitmapFactory.decodeFile("some/fake/file"));
+ view.setBackgroundDrawable(drawable);
+ assertThat(view.getBackground(), sameInstance(drawable));
+ assertThat(visualize(view), equalTo("background:\nBitmap for file:some/fake/file"));
+ }
+
+ @Test
public void shouldPostActionsToTheMessageQueue() throws Exception {
Robolectric.pauseMainLooper();
@@ -218,6 +267,54 @@ public class ViewTest {
}
@Test
+ public void shouldRememberIsPressed() {
+ view.setPressed(true);
+ assertTrue(view.isPressed());
+ view.setPressed(false);
+ assertFalse(view.isPressed());
+ }
+
+ @Test
+ public void shouldAddOnClickListenerFromAttribute() throws Exception {
+ TestAttributeSet attrs = new TestAttributeSet();
+ attrs.put("android:onClick", "clickMe");
+
+ view = new View(null, attrs);
+ assertNotNull(shadowOf(view).getOnClickListener());
+ }
+
+ @Test
+ public void shouldCallOnClickWithAttribute() throws Exception {
+ final AtomicBoolean called = new AtomicBoolean(false);
+ Activity context = new Activity() {
+ public void clickMe(View view) {
+ called.set(true);
+ }
+ };
+ TestAttributeSet attrs = new TestAttributeSet();
+ attrs.put("android:onClick", "clickMe");
+
+ view = new View(context, attrs);
+ view.performClick();
+ assertTrue("Should have been called", called.get());
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void shouldThrowExceptionWithBadMethodName() throws Exception {
+ final AtomicBoolean called = new AtomicBoolean(false);
+ Activity context = new Activity() {
+ public void clickMe(View view) {
+ called.set(true);
+ }
+ };
+ TestAttributeSet attrs = new TestAttributeSet();
+ attrs.put("android:onClick", "clickYou");
+
+ view = new View(context, attrs);
+ view.performClick();
+ }
+
+ @Test
public void shouldSetAnimation() throws Exception {
Animation anim = new TestAnimation();
view.setAnimation(anim);
@@ -490,4 +587,58 @@ public class ViewTest {
super.onMeasure(800, 400);
}
}
+
+ @Test public void shouldCallOnAttachedToAndDetachedFromWindow() throws Exception {
+ MyView parent = new MyView("parent");
+ parent.addView(new MyView("child"));
+ transcript.assertNoEventsSoFar();
+
+ TestWindow window = new TestWindow(application);
+ window.setContentView(parent);
+ transcript.assertEventsSoFar("parent attached", "child attached");
+
+ parent.addView(new MyView("another child"));
+ transcript.assertEventsSoFar("another child attached");
+
+ MyView temporaryChild = new MyView("temporary child");
+ parent.addView(temporaryChild);
+ transcript.assertEventsSoFar("temporary child attached");
+ assertTrue(shadowOf(temporaryChild).isAttachedToWindow());
+
+ parent.removeView(temporaryChild);
+ transcript.assertEventsSoFar("temporary child detached");
+ assertFalse(shadowOf(temporaryChild).isAttachedToWindow());
+
+ window.setContentView(null);
+ transcript.assertEventsSoFar("parent detached", "child detached", "another child detached");
+ }
+
+ @Test public void removeAllViews_shouldCallOnAttachedToAndDetachedFromWindow() throws Exception {
+ MyView parent = new MyView("parent");
+ parent.addView(new MyView("child"));
+ parent.addView(new MyView("another child"));
+ new TestWindow(application).setContentView(parent);
+ transcript.clear();
+ parent.removeAllViews();
+ transcript.assertEventsSoFar("child detached", "another child detached");
+ }
+
+ private class MyView extends LinearLayout {
+ private String name;
+
+ public MyView(String name) {
+ super(Robolectric.application);
+ this.name = name;
+ }
+
+ @Override protected void onAttachedToWindow() {
+ transcript.add(name + " attached");
+ super.onAttachedToWindow();
+ }
+
+ @Override protected void onDetachedFromWindow() {
+ transcript.add(name + " detached");
+ super.onDetachedFromWindow();
+ }
+ }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/testing/InnerActivity.java b/src/test/java/com/xtremelabs/robolectric/shadows/testing/InnerActivity.java
new file mode 100644
index 000000000..63a56c6dc
--- /dev/null
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/testing/InnerActivity.java
@@ -0,0 +1,16 @@
+package com.xtremelabs.robolectric.shadows.testing;
+
+import android.app.Activity;
+import android.os.Bundle;
+import com.xtremelabs.robolectric.R;
+
+/**
+ *
+ */
+public class InnerActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.lam_inner);
+ }
+}
diff --git a/src/test/java/com/xtremelabs/robolectric/shadows/testing/LocalActivityManagerContainer.java b/src/test/java/com/xtremelabs/robolectric/shadows/testing/LocalActivityManagerContainer.java
new file mode 100644
index 000000000..9f4be93a6
--- /dev/null
+++ b/src/test/java/com/xtremelabs/robolectric/shadows/testing/LocalActivityManagerContainer.java
@@ -0,0 +1,40 @@
+package com.xtremelabs.robolectric.shadows.testing;
+
+import android.app.Activity;
+import android.app.LocalActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.Window;
+import android.widget.LinearLayout;
+import com.xtremelabs.robolectric.R;
+
+@SuppressWarnings("UnusedDeclaration")
+// Used in lam_outer.xml
+public class LocalActivityManagerContainer extends LinearLayout {
+ public LocalActivityManagerContainer(Context context) {
+ super(context);
+ init();
+ }
+
+ public LocalActivityManagerContainer(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public LocalActivityManagerContainer(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ private void init() {
+ LocalActivityManager lam = new LocalActivityManager((Activity) getContext(), true);
+ lam.dispatchCreate(null);
+ final Window window = lam.startActivity("foo", new Intent(getContext(), InnerActivity.class));
+ // Add the decorView's child to this LinearLayout's children.
+ final View innerContents = window.getDecorView().findViewById(R.id.lam_inner_contents);
+ addView(innerContents);
+ }
+
+}
diff --git a/src/test/java/com/xtremelabs/robolectric/tester/android/view/TestWindowTest.java b/src/test/java/com/xtremelabs/robolectric/tester/android/view/TestWindowTest.java
index fd6cb494b..49b175c29 100644
--- a/src/test/java/com/xtremelabs/robolectric/tester/android/view/TestWindowTest.java
+++ b/src/test/java/com/xtremelabs/robolectric/tester/android/view/TestWindowTest.java
@@ -1,10 +1,17 @@
package com.xtremelabs.robolectric.tester.android.view;
+import android.view.View;
+import android.view.ViewGroup;
+import com.xtremelabs.robolectric.R;
+import com.xtremelabs.robolectric.Robolectric;
import com.xtremelabs.robolectric.TestRunners;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
@RunWith(TestRunners.WithDefaults.class)
public class TestWindowTest {
@@ -13,4 +20,26 @@ public class TestWindowTest {
TestWindow window = new TestWindow(null);
Assert.assertNotNull(window.getWindowManager());
}
+
+ @Test
+ public void decorViewFindViewById__shouldReturnContentWrapper() throws Exception {
+ TestWindow window = new TestWindow(null);
+ View contentView = new View(null);
+ contentView.setTag("content view");
+ window.setContentView(contentView);
+
+ // This is the real meat of the test. ActionBarSherlock relies on this code:
+ // window.getDecorView().findViewById(R.id.content)
+ ViewGroup contentWrapper = (ViewGroup) window.getDecorView().findViewById(android.R.id.content);
+ assertThat("child count", contentWrapper.getChildCount(), equalTo(1));
+ assertThat(contentWrapper.getChildAt(0).getTag(), equalTo(contentView.getTag()));
+ }
+
+ @Test public void setContentViewByResource() throws Exception {
+ TestWindow window = new TestWindow(Robolectric.application);
+ window.setContentView(R.layout.text_views);
+
+ ViewGroup contentWrapper = (ViewGroup) window.findViewById(android.R.id.content);
+ assertThat("child count", contentWrapper.getChildCount(), equalTo(1));
+ }
}
diff --git a/src/test/java/com/xtremelabs/robolectric/util/CustomFragment.java b/src/test/java/com/xtremelabs/robolectric/util/CustomFragment.java
new file mode 100644
index 000000000..5fc50a0f5
--- /dev/null
+++ b/src/test/java/com/xtremelabs/robolectric/util/CustomFragment.java
@@ -0,0 +1,23 @@
+package com.xtremelabs.robolectric.util;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+/**
+ * Stub class that can be used for testing support-lib fragments.
+ */
+public class CustomFragment extends Fragment {
+
+ private TextView textView;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ textView = new TextView(inflater.getContext());
+ textView.setText("CustomFragment text view");
+ return textView;
+ }
+}
diff --git a/src/test/java/com/xtremelabs/robolectric/util/TestUtil.java b/src/test/java/com/xtremelabs/robolectric/util/TestUtil.java
index 7a77707af..0b0ff209b 100644
--- a/src/test/java/com/xtremelabs/robolectric/util/TestUtil.java
+++ b/src/test/java/com/xtremelabs/robolectric/util/TestUtil.java
@@ -2,8 +2,15 @@ package com.xtremelabs.robolectric.util;
import com.xtremelabs.robolectric.RobolectricConfig;
+import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.io.Writer;
import java.util.Collection;
import java.util.Map;
import java.util.Properties;
@@ -93,4 +100,19 @@ public abstract class TestUtil {
return file(new File(sdkDir, "platforms/android-" + DEFAULT_SDK_VERSION + "/data/res/"), paths);
}
+
+ public static String readString(InputStream is) throws IOException {
+ Writer writer = new StringWriter();
+ char[] buffer = new char[1024];
+ try {
+ Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+ int n;
+ while ((n = reader.read(buffer)) != -1) {
+ writer.write(buffer, 0, n);
+ }
+ } finally {
+ is.close();
+ }
+ return writer.toString();
+ }
}
diff --git a/src/test/resources/project.properties b/src/test/resources/project.properties
new file mode 100644
index 000000000..9db28a091
--- /dev/null
+++ b/src/test/resources/project.properties
@@ -0,0 +1,9 @@
+# This is for RoboelectricConfigTest to ensure that we parse and include
+# library references.
+
+# Project target.
+target=android-42
+android.library.reference.1=../lib1
+android.library.reference.2=../lib2
+android.library.reference.3=../lib3
+android.library.reference.4=../lib4 \ No newline at end of file
diff --git a/src/test/resources/res/layout-land/multi_orientation.xml b/src/test/resources/res/layout-land/multi_orientation.xml
new file mode 100644
index 000000000..3e53c2451
--- /dev/null
+++ b/src/test/resources/res/layout-land/multi_orientation.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/landscape"
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ >
+
+ <View
+ android:layout_width="fill_parent"
+ android:layout_height="10dip"
+ />
+
+ <fragment
+ android:name="com.xtremelabs.robolectric.util.CustomFragment"
+ android:id="@+id/my_landscape_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ />
+</LinearLayout>
diff --git a/src/test/resources/res/layout/edit_text.xml b/src/test/resources/res/layout/edit_text.xml
new file mode 100644
index 000000000..3b64e9482
--- /dev/null
+++ b/src/test/resources/res/layout/edit_text.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<EditText
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:hint="Hello, Hint"
+ />
diff --git a/src/test/resources/res/layout/fragment.xml b/src/test/resources/res/layout/fragment.xml
new file mode 100644
index 000000000..9cfd4c9da
--- /dev/null
+++ b/src/test/resources/res/layout/fragment.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<fragment xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="com.xtremelabs.robolectric.util.CustomFragment"
+ android:id="@+id/my_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/> \ No newline at end of file
diff --git a/src/test/resources/res/layout/fragment_contents.xml b/src/test/resources/res/layout/fragment_contents.xml
new file mode 100644
index 000000000..dbcc86d0a
--- /dev/null
+++ b/src/test/resources/res/layout/fragment_contents.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical"
+ >
+ <TextView
+ android:id="@+id/tacos"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TACOS"/>
+ <TextView
+ android:id="@+id/burritos"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="BURRITOS"/>
+</LinearLayout>
diff --git a/src/test/resources/res/layout/lam_inner.xml b/src/test/resources/res/layout/lam_inner.xml
new file mode 100644
index 000000000..688777542
--- /dev/null
+++ b/src/test/resources/res/layout/lam_inner.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ >
+
+ <TextView
+ android:id="@+id/lam_inner_contents"
+ android:layout_weight="fill_parent"
+ android:layout_height="fill_parent"
+ />
+</LinearLayout>
+
diff --git a/src/test/resources/res/layout/lam_outer.xml b/src/test/resources/res/layout/lam_outer.xml
new file mode 100644
index 000000000..4d771a7b4
--- /dev/null
+++ b/src/test/resources/res/layout/lam_outer.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ >
+
+ <com.xtremelabs.robolectric.shadows.testing.LocalActivityManagerContainer
+ android:id="@+id/lam_container"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ />
+
+</LinearLayout>
diff --git a/src/test/resources/res/layout/multi_orientation.xml b/src/test/resources/res/layout/multi_orientation.xml
new file mode 100644
index 000000000..351e48d42
--- /dev/null
+++ b/src/test/resources/res/layout/multi_orientation.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/portrait"
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ >
+
+ <View
+ android:layout_width="fill_parent"
+ android:layout_height="10dip"
+ />
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="14dip"
+ android:textColor="#fff"
+ android:text="I'm a Portrait Layout!"
+ />
+</LinearLayout>
diff --git a/src/test/resources/res/values/attrs.xml b/src/test/resources/res/values/attrs.xml
index b0f0b1298..f929d515b 100644
--- a/src/test/resources/res/values/attrs.xml
+++ b/src/test/resources/res/values/attrs.xml
@@ -1,9 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <declare-styleable name="com.xtremelabs.robolectric.util.CustomView">
+ <declare-styleable name="CustomView">
<attr name="itemType" format="enum">
<enum name="integer" value="0"/>
<enum name="string" value="1"/>
</attr>
+
+ <attr name="scrollbars">
+ <flag name="horizontal" value="0x00000100" />
+ <flag name="vertical" value="0x00000200" />
+ </attr>
+
+ <attr name="gravity"/>
+
+ <attr name="keycode"/>
</declare-styleable>
-</resources> \ No newline at end of file
+
+ <attr name="gravity">
+ <flag name="center" value="0x11" />
+ <flag name="fill_vertical" value="0x70" />
+ </attr>
+
+ <attr name="keycode">
+ <enum name="KEYCODE_SOFT_RIGHT" value="2" />
+ <enum name="KEYCODE_HOME" value="3" />
+ </attr>
+</resources>
diff --git a/src/test/resources/res/values/colors.xml b/src/test/resources/res/values/colors.xml
index 01f249b31..d4189fd27 100644
--- a/src/test/resources/res/values/colors.xml
+++ b/src/test/resources/res/values/colors.xml
@@ -11,6 +11,8 @@
<color name="android_namespaced_black">@android:color/black</color>
+ <color name="android_namespaced_transparent">@android:color/transparent</color>
+
<color name="android_red">red</color>
</resources>
diff --git a/src/test/resources/res/values/integers.xml b/src/test/resources/res/values/integers.xml
new file mode 100644
index 000000000..5dc832695
--- /dev/null
+++ b/src/test/resources/res/values/integers.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <integer name="meaning_of_life">42</integer>
+ <integer name="loneliest_number">1</integer>
+ <integer name="there_can_be_only">@integer/loneliest_number</integer>
+ <integer name="hex_int">0xFFFF0000</integer>
+</resources> \ No newline at end of file
diff --git a/src/test/resources/res/xml/preferences.xml b/src/test/resources/res/xml/preferences.xml
index ad4f095fc..4fbd9c40b 100644
--- a/src/test/resources/res/xml/preferences.xml
+++ b/src/test/resources/res/xml/preferences.xml
@@ -2,45 +2,56 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
- <PreferenceCategory
- android:key="category"
- android:title="Category Test">
-
- <Preference
- android:key="inside_category"
- android:title="Inside Category Test"
- android:summary=""/>
-
- </PreferenceCategory>
-
- <CheckBoxPreference
- android:key="checkbox"
- android:title="Checkbox Test"
- android:summary=""
- android:defaultValue="true"
- />
-
- <EditTextPreference
- android:key="edit_text"
- android:title="EditText Test"
- android:summary=""
- />
-
- <ListPreference
- android:key="list"
- android:title="List Test"
- android:summary=""
- />
-
- <Preference
- android:key="preference"
- android:title="Preference Title"
- android:summary=""/>
-
- <RingtonePreference
- android:key="ringtone"
- android:title="Ringtone Test"
- android:summary=""
- />
-
-</PreferenceScreen> \ No newline at end of file
+ <PreferenceCategory
+ android:key="category"
+ android:title="Category Test">
+
+ <Preference
+ android:key="inside_category"
+ android:title="Inside Category Test"
+ android:summary=""/>
+
+ </PreferenceCategory>
+
+ <PreferenceScreen
+ android:key="screen"
+ android:title="Screen Test">
+
+ <Preference
+ android:key="inside_screen"
+ android:title="Inside Screen Test"
+ android:summary=""/>
+
+ </PreferenceScreen>
+
+ <CheckBoxPreference
+ android:key="checkbox"
+ android:title="Checkbox Test"
+ android:summary=""
+ android:defaultValue="true"
+ />
+
+ <EditTextPreference
+ android:key="edit_text"
+ android:title="EditText Test"
+ android:summary=""
+ />
+
+ <ListPreference
+ android:key="list"
+ android:title="List Test"
+ android:summary=""
+ />
+
+ <Preference
+ android:key="preference"
+ android:title="Preference Title"
+ android:summary=""/>
+
+ <RingtonePreference
+ android:key="ringtone"
+ android:title="Ringtone Test"
+ android:summary=""
+ />
+
+</PreferenceScreen> \ No newline at end of file