blob: 273cce9598ed52a90a1b9d868b8f2b683acfaee0 [file] [log] [blame]
package com.xtremelabs.robolectric.shadows;
import android.app.Activity;
import android.app.Dialog;
import android.appwidget.AppWidgetProvider;
import android.content.*;
import android.content.pm.ActivityInfo;
import android.database.CharArrayBuffer;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.database.sqlite.SQLiteCursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.widget.FrameLayout;
import com.xtremelabs.robolectric.ApplicationResolver;
import com.xtremelabs.robolectric.R;
import com.xtremelabs.robolectric.Robolectric;
import com.xtremelabs.robolectric.WithTestDefaultsRunner;
import com.xtremelabs.robolectric.util.TestRunnable;
import com.xtremelabs.robolectric.util.Transcript;
import org.hamcrest.CoreMatchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.concurrent.atomic.AtomicBoolean;
import static com.xtremelabs.robolectric.Robolectric.shadowOf;
import static com.xtremelabs.robolectric.util.TestUtil.assertInstanceOf;
import static com.xtremelabs.robolectric.util.TestUtil.newConfig;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.core.StringStartsWith.startsWith;
import static org.junit.Assert.*;
@RunWith(WithTestDefaultsRunner.class)
public class ActivityTest {
@Test(expected = IllegalStateException.class)
public void shouldComplainIfActivityIsDestroyedWithRegisteredBroadcastReceivers() throws Exception {
DialogLifeCycleActivity activity = new DialogLifeCycleActivity();
activity.registerReceiver(new AppWidgetProvider(), new IntentFilter());
activity.onDestroy();
}
@Test
public void shouldNotComplainIfActivityIsDestroyedWhileAnotherActivityHasRegisteredBroadcastReceivers() throws Exception {
DialogLifeCycleActivity activity = new DialogLifeCycleActivity();
DialogLifeCycleActivity activity2 = new DialogLifeCycleActivity();
activity2.registerReceiver(new AppWidgetProvider(), new IntentFilter());
activity.onDestroy(); // should not throw exception
}
@Test
public void shouldNotRegisterNullBroadcastReceiver() {
DialogLifeCycleActivity activity = new DialogLifeCycleActivity();
activity.registerReceiver(null, new IntentFilter());
activity.onDestroy();
}
@Test
public void startActivityForResultAndReceiveResult_shouldSendResponsesBackToActivity() throws Exception {
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.startActivityForResult(new Intent().setType("audio/*"), 123);
activity.startActivityForResult(new Intent().setType("image/*"), 456);
shadowOf(activity).receiveResult(new Intent().setType("image/*"), Activity.RESULT_OK,
new Intent().setData(Uri.parse("content:foo")));
transcript.assertEventsSoFar("onActivityResult called with requestCode 456, resultCode -1, intent data content:foo");
}
@Test
public void startActivityForResultAndReceiveResult_whenNoIntentMatches_shouldThrowException() throws Exception {
Activity activity = new Activity() {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
throw new IllegalStateException("should not be called");
}
};
activity.startActivityForResult(new Intent().setType("audio/*"), 123);
activity.startActivityForResult(new Intent().setType("image/*"), 456);
Intent requestIntent = new Intent().setType("video/*");
try {
shadowOf(activity).receiveResult(requestIntent, Activity.RESULT_OK,
new Intent().setData(Uri.parse("content:foo")));
fail();
} catch (Exception e) {
assertThat(e.getMessage(), startsWith("No intent matches " + requestIntent));
}
}
@Test
public void shouldSupportStartActivityForResult() throws Exception {
DialogLifeCycleActivity activity = new DialogLifeCycleActivity();
ShadowActivity shadowActivity = Robolectric.shadowOf(activity);
Intent intent = new Intent().setClass(activity, DialogLifeCycleActivity.class);
assertThat(shadowActivity.getNextStartedActivity(), nullValue());
activity.startActivityForResult(intent, 142);
Intent startedIntent = shadowActivity.getNextStartedActivity();
assertThat(startedIntent, notNullValue());
assertThat(startedIntent, sameInstance(intent));
}
@Test
public void shouldSupportGetStartedActitivitesForResult() throws Exception {
DialogLifeCycleActivity activity = new DialogLifeCycleActivity();
ShadowActivity shadowActivity = Robolectric.shadowOf(activity);
Intent intent = new Intent().setClass(activity, DialogLifeCycleActivity.class);
activity.startActivityForResult(intent, 142);
ShadowActivity.IntentForResult intentForResult = shadowActivity.getNextStartedActivityForResult();
assertThat(intentForResult, notNullValue());
assertThat(shadowActivity.getNextStartedActivityForResult(), nullValue());
assertThat(intentForResult.intent, notNullValue());
assertThat(intentForResult.intent, sameInstance(intent));
assertThat(intentForResult.requestCode, equalTo(142));
}
@Test
public void shouldSupportPeekStartedActitivitesForResult() throws Exception {
DialogLifeCycleActivity activity = new DialogLifeCycleActivity();
ShadowActivity shadowActivity = Robolectric.shadowOf(activity);
Intent intent = new Intent().setClass(activity, DialogLifeCycleActivity.class);
activity.startActivityForResult(intent, 142);
ShadowActivity.IntentForResult intentForResult = shadowActivity.peekNextStartedActivityForResult();
assertThat(intentForResult, notNullValue());
assertThat(shadowActivity.peekNextStartedActivityForResult(), sameInstance(intentForResult));
assertThat(intentForResult.intent, notNullValue());
assertThat(intentForResult.intent, sameInstance(intent));
assertThat(intentForResult.requestCode, equalTo(142));
}
@Test
public void onContentChangedShouldBeCalledAfterContentViewIsSet() throws RuntimeException {
final Transcript transcript = new Transcript();
Activity customActivity = new Activity() {
@Override
public void onContentChanged() {
transcript.add("onContentChanged was called; title is \"" + shadowOf(findViewById(R.id.title)).innerText() + "\"");
}
};
customActivity.setContentView(R.layout.main);
transcript.assertEventsSoFar("onContentChanged was called; title is \"Main Layout\"");
}
@Test
public void shouldRetrievePackageNameFromTheManifest() throws Exception {
Robolectric.application = new ApplicationResolver(newConfig("TestAndroidManifestWithPackageName.xml")).resolveApplication();
assertThat("com.wacka.wa", equalTo(new Activity().getPackageName()));
}
@Test
public void shouldRunUiTasksImmediatelyByDefault() throws Exception {
TestRunnable runnable = new TestRunnable();
DialogLifeCycleActivity activity = new DialogLifeCycleActivity();
activity.runOnUiThread(runnable);
assertTrue(runnable.wasRun);
}
@Test
public void shouldQueueUiTasksWhenUiThreadIsPaused() throws Exception {
Robolectric.pauseMainLooper();
DialogLifeCycleActivity activity = new DialogLifeCycleActivity();
TestRunnable runnable = new TestRunnable();
activity.runOnUiThread(runnable);
assertFalse(runnable.wasRun);
Robolectric.unPauseMainLooper();
assertTrue(runnable.wasRun);
}
@Test
public void showDialog_shouldCreatePrepareAndShowDialog() {
final DialogLifeCycleActivity activity = new DialogLifeCycleActivity();
final AtomicBoolean dialogWasShown = new AtomicBoolean(false);
new Dialog(activity) {
{
activity.dialog = this;
}
@Override
public void show() {
dialogWasShown.set(true);
}
};
activity.showDialog(1);
assertTrue(activity.createdDialog);
assertTrue(activity.preparedDialog);
assertTrue(dialogWasShown.get());
}
@Test
public void showDialog_shouldCreatePrepareAndShowDialogWithBundle() {
final DialogLifeCycleActivity activity = new DialogLifeCycleActivity();
final AtomicBoolean dialogWasShown = new AtomicBoolean(false);
new Dialog(activity) {
{
activity.dialog = this;
}
@Override
public void show() {
dialogWasShown.set(true);
}
};
activity.showDialog(1, new Bundle());
assertTrue(activity.createdDialog);
assertTrue(activity.preparedDialogWithBundle);
assertTrue(dialogWasShown.get());
}
@Test
public void showDialog_shouldReuseDialogs() {
final DialogCreatingActivity activity = new DialogCreatingActivity();
activity.showDialog(1);
Dialog firstDialog = ShadowDialog.getLatestDialog();
activity.showDialog(1);
final Dialog secondDialog = ShadowDialog.getLatestDialog();
assertSame("dialogs should be the same instance", firstDialog, secondDialog);
}
@Test
public void showDialog_shouldShowDialog() throws Exception {
final DialogCreatingActivity activity = new DialogCreatingActivity();
activity.showDialog(1);
Dialog dialog = ShadowDialog.getLatestDialog();
assertTrue(dialog.isShowing());
}
@Test
public void dismissDialog_shouldDismissPreviouslyShownDialog() throws Exception {
final DialogCreatingActivity activity = new DialogCreatingActivity();
activity.showDialog(1);
activity.dismissDialog(1);
Dialog dialog = ShadowDialog.getLatestDialog();
assertFalse(dialog.isShowing());
}
@Test(expected = IllegalArgumentException.class)
public void dismissDialog_shouldThrowExceptionIfDialogWasNotPreviouslyShown() throws Exception {
final DialogCreatingActivity activity = new DialogCreatingActivity();
activity.dismissDialog(1);
}
@Test
public void removeDialog_shouldCreateDialogAgain() {
final DialogCreatingActivity activity = new DialogCreatingActivity();
activity.showDialog(1);
Dialog firstDialog = ShadowDialog.getLatestDialog();
activity.removeDialog(1);
assertNull(Robolectric.shadowOf(activity).getDialogById(1));
activity.showDialog(1);
Dialog secondDialog = ShadowDialog.getLatestDialog();
assertNotSame("dialogs should not be the same instance", firstDialog, secondDialog);
}
@Test
public void shouldCallOnCreateDialogFromShowDialog() {
ActivityWithOnCreateDialog activity = new ActivityWithOnCreateDialog();
activity.showDialog(123);
assertTrue(activity.onCreateDialogWasCalled);
assertThat(ShadowDialog.getLatestDialog(), CoreMatchers.<Object>notNullValue());
}
@Test
public void shouldCallFinishInOnBackPressed() {
Activity activity = new Activity();
activity.onBackPressed();
ShadowActivity shadowActivity = shadowOf(activity);
assertTrue(shadowActivity.isFinishing());
}
@Test
public void shouldSupportCurrentFocus() {
DialogLifeCycleActivity activity = new DialogLifeCycleActivity();
ShadowActivity shadow = shadowOf(activity);
assertNull(shadow.getCurrentFocus());
View view = new View(activity);
shadow.setCurrentFocus(view);
assertEquals(view, shadow.getCurrentFocus());
}
@Test
public void shouldSetOrientation() {
DialogLifeCycleActivity activity = new DialogLifeCycleActivity();
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
assertThat(activity.getRequestedOrientation(), equalTo(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT));
}
@Test
public void retrieveIdOfResource() {
Activity activity = new Activity();
int id1 = R.string.hello;
String string = activity.getString(id1);
assertEquals("Hello", string);
int id = activity.getResources().getIdentifier("hello", "string", "com.xtremelabs.robolectric");
assertTrue(id > 0);
String hello = activity.getResources().getString(id);
assertEquals("Hello", hello);
}
@Test
public void getCurrentFocus_shouldBeNullWhenNoFocusRequested() {
Activity activity = new Activity();
activity.setContentView(R.layout.main);
View focusedView = shadowOf(activity).getCurrentFocus();
assertNull(focusedView);
}
@Test
public void getCurrentFocus_shouldReturnSubViewAfterFocusedRequest() {
Activity activity = new Activity();
activity.setContentView(R.layout.main);
View view = activity.findViewById(R.id.button);
view.requestFocus();
View focusedView = shadowOf(activity).getCurrentFocus();
assertEquals(R.id.button, focusedView.getId());
}
@Test
public void retrieveIdOfNonExistingResource() {
Activity activity = new Activity();
int id = activity.getResources().getIdentifier("just_alot_of_crap", "string", "com.xtremelabs.robolectric");
assertTrue(id == 0);
}
@Test
public void shouldSetContentViewWithFrameLayoutAsParent() throws Exception {
Activity activity = new Activity();
activity.setContentView(R.layout.toplevel_merge);
View contentView = shadowOf(activity).getContentView();
assertInstanceOf(FrameLayout.class, contentView);
assertThat(((FrameLayout) contentView).getChildCount(), equalTo(2));
}
@Test
public void onKeyUp_recordsThatItWasCalled() throws Exception {
Activity activity = new Activity();
boolean consumed = activity.onKeyUp(KeyEvent.KEYCODE_0, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_0));
assertFalse(consumed);
assertTrue(shadowOf(activity).onKeyUpWasCalled());
shadowOf(activity).resetKeyUpWasCalled();
assertFalse(shadowOf(activity).onKeyUpWasCalled());
}
@Test
public void onKeyUp_callsOnBackPressedWhichFinishesTheActivity() throws Exception {
Activity activity = new Activity();
boolean consumed = activity.onKeyUp(KeyEvent.KEYCODE_BACK, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));
assertTrue(consumed);
assertTrue(shadowOf(activity).onKeyUpWasCalled());
assertTrue(activity.isFinishing());
}
@Test
public void shouldGiveSharedPreferences() throws Exception {
Activity activity = new Activity();
SharedPreferences preferences = activity.getPreferences(Context.MODE_PRIVATE);
assertNotNull(preferences);
preferences.edit().putString("foo", "bar").commit();
assertThat(activity.getPreferences(Context.MODE_PRIVATE).getString("foo", null), equalTo("bar"));
}
@Test
public void shouldFindContentViewContainer() throws Exception {
Activity activity = new Activity();
View contentView = new View(activity);
activity.setContentView(contentView);
FrameLayout contentViewContainer = (FrameLayout) activity.findViewById(android.R.id.content);
assertThat(contentViewContainer.getChildAt(0), is(contentView));
}
@Test
public void createGoesThroughFullLifeCycle() throws Exception {
TestActivity activity = new TestActivity();
shadowOf(activity).create();
activity.transcript.assertEventsSoFar(
"onCreate",
"onStart",
"onPostCreate",
"onResume"
);
}
@Test
public void recreateGoesThroughFullLifeCycle() throws Exception {
TestActivity activity = new TestActivity();
ShadowActivity shadow = shadowOf(activity);
shadow.recreate();
activity.transcript.assertEventsSoFar(
"onSaveInstanceState",
"onPause",
"onStop",
"onRetainNonConfigurationInstance",
"onDestroy",
"onCreate",
"onStart",
"onRestoreInstanceState",
"onResume"
);
Integer storedValue = (Integer) activity.getLastNonConfigurationInstance();
assertEquals(5, storedValue.intValue());
}
@Test
public void startAndStopManagingCursorTracksCursors() throws Exception {
TestActivity activity = new TestActivity();
ShadowActivity shadow = shadowOf(activity);
assertThat( shadow.getManagedCursors(), notNullValue() );
assertThat( shadow.getManagedCursors().size(), equalTo(0) );
Cursor c = Robolectric.newInstanceOf(SQLiteCursor.class);
activity.startManagingCursor(c);
assertThat( shadow.getManagedCursors(), notNullValue() );
assertThat( shadow.getManagedCursors().size(), equalTo(1) );
assertThat( shadow.getManagedCursors().get(0), sameInstance(c) );
activity.stopManagingCursor(c);
assertThat( shadow.getManagedCursors(), notNullValue() );
assertThat( shadow.getManagedCursors().size(), equalTo(0) );
}
private static class TestActivity extends Activity {
Transcript transcript = new Transcript();
private boolean isRecreating = false;
@Override
public void onSaveInstanceState(Bundle outState) {
isRecreating = true;
transcript.add("onSaveInstanceState");
outState.putString("TestActivityKey", "TestActivityValue");
super.onSaveInstanceState(outState);
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
transcript.add("onRestoreInstanceState");
assertTrue(savedInstanceState.containsKey("TestActivityKey"));
assertEquals("TestActivityValue", savedInstanceState.getString("TestActivityKey"));
super.onRestoreInstanceState(savedInstanceState);
}
@Override
public Object onRetainNonConfigurationInstance() {
transcript.add("onRetainNonConfigurationInstance");
return new Integer(5);
}
@Override
public void onPause() {
transcript.add("onPause");
super.onPause();
}
@Override
public void onDestroy() {
transcript.add("onDestroy");
super.onDestroy();
}
@Override
public void onCreate(Bundle savedInstanceState) {
transcript.add("onCreate");
if( isRecreating ) {
assertTrue(savedInstanceState.containsKey("TestActivityKey"));
assertEquals("TestActivityValue", savedInstanceState.getString("TestActivityKey"));
}
super.onCreate(savedInstanceState);
}
@Override
public void onStart() {
transcript.add("onStart");
super.onStart();
}
@Override
public void onPostCreate(Bundle savedInstanceState) {
transcript.add("onPostCreate");
super.onPostCreate(savedInstanceState);
}
@Override
public void onStop() {
transcript.add("onStop");
super.onStop();
}
@Override
public void onResume() {
transcript.add("onResume");
super.onResume();
}
}
private static class DialogCreatingActivity extends Activity {
@Override
protected Dialog onCreateDialog(int id) {
return new Dialog(this);
}
}
private static class DialogLifeCycleActivity extends Activity {
public boolean createdDialog = false;
public boolean preparedDialog = false;
public boolean preparedDialogWithBundle = false;
public Dialog dialog = null;
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
protected Dialog onCreateDialog(int id) {
createdDialog = true;
return dialog;
}
@Override
protected void onPrepareDialog(int id, Dialog dialog) {
preparedDialog = true;
}
@Override
protected void onPrepareDialog(int id, Dialog dialog, Bundle bundle) {
preparedDialogWithBundle = true;
}
}
private static class ActivityWithOnCreateDialog extends Activity {
boolean onCreateDialogWasCalled = false;
@Override
protected Dialog onCreateDialog(int id) {
onCreateDialogWasCalled = true;
return new Dialog(null);
}
}
}