package org.robolectric.android.controller;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.robolectric.Shadows.shadowOf;
import static org.robolectric.util.TestUtil.assertStringsInclude;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.TestRunners;
import org.robolectric.annotation.Config;
import org.robolectric.android.runtime.RuntimeAdapter;
import org.robolectric.android.runtime.RuntimeAdapterFactory;
import org.robolectric.shadows.CoreShadowsAdapter;
import org.robolectric.shadows.ShadowLooper;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.Window;
import android.widget.LinearLayout;
import org.robolectric.util.ReflectionHelpers;
import org.robolectric.util.Scheduler;
import org.robolectric.util.TestRunnable;
import java.util.ArrayList;
import java.util.List;
@RunWith(TestRunners.SelfTest.class)
public class ActivityControllerTest {
private static final List<String> transcript = new ArrayList<>();
private final ComponentName componentName = new ComponentName("org.robolectric", MyActivity.class.getName());
private final ActivityController<MyActivity> controller = Robolectric.buildActivity(MyActivity.class);
@Before
public void setUp() throws Exception {
transcript.clear();
}
@Test
@Config(manifest = Config.NONE)
public void canCreateActivityNotListedInManifest() {
ActivityController<Activity> activityController = Robolectric.buildActivity(Activity.class);
assertThat(activityController.setup()).isNotNull();
}
public static class TestDelayedPostActivity extends Activity {
TestRunnable r1 = new TestRunnable();
TestRunnable r2 = new TestRunnable();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Handler h = new Handler();
h.post(r1);
h.postDelayed(r2, 60000);
}
}
@Test
public void pendingTasks_areRunEagerly_whenActivityIsStarted_andSchedulerUnPaused() {
final Scheduler s = Robolectric.getForegroundThreadScheduler();
final long startTime = s.getCurrentTime();
TestDelayedPostActivity activity = Robolectric.setupActivity(TestDelayedPostActivity.class);
assertThat(activity.r1.wasRun).as("immediate task").isTrue();
assertThat(s.getCurrentTime()).as("currentTime").isEqualTo(startTime);
}
@Test
public void delayedTasks_areNotRunEagerly_whenActivityIsStarted_andSchedulerUnPaused() {
// Regression test for issue #1509
final Scheduler s = Robolectric.getForegroundThreadScheduler();
final long startTime = s.getCurrentTime();
TestDelayedPostActivity activity = Robolectric.setupActivity(TestDelayedPostActivity.class);
assertThat(activity.r2.wasRun).as("before flush").isFalse();
assertThat(s.getCurrentTime()).as("currentTime before flush").isEqualTo(startTime);
s.advanceToLastPostedRunnable();
assertThat(activity.r2.wasRun).as("after flush").isTrue();
assertThat(s.getCurrentTime()).as("currentTime after flush").isEqualTo(startTime + 60000);
}
@Test
public void shouldSetIntent() throws Exception {
MyActivity myActivity = controller.create().get();
assertThat(myActivity.getIntent()).isNotNull();
assertThat(myActivity.getIntent().getComponent()).isEqualTo(componentName);
}
@Test
public void shouldSetIntentComponentWithCustomIntentWithoutComponentSet() throws Exception {
MyActivity myActivity = Robolectric.buildActivity(MyActivity.class, new Intent(Intent.ACTION_VIEW)).create().get();
assertThat(myActivity.getIntent().getAction()).isEqualTo(Intent.ACTION_VIEW);
assertThat(myActivity.getIntent().getComponent()).isEqualTo(componentName);
}
@Test
public void shouldSetIntentForGivenActivityInstance() throws Exception {
ActivityController<MyActivity> activityController = ActivityController.of(new CoreShadowsAdapter(), new MyActivity()).create();
assertThat(activityController.get().getIntent()).isNotNull();
}
@Test
public void whenLooperIsNotPaused_shouldCreateWithMainLooperPaused() throws Exception {
ShadowLooper.unPauseMainLooper();
controller.create();
assertThat(shadowOf(Looper.getMainLooper()).isPaused()).isFalse();
assertStringsInclude(transcript, "finishedOnCreate", "onCreate");
}
@Test
public void whenLooperIsAlreadyPaused_shouldCreateWithMainLooperPaused() throws Exception {
ShadowLooper.pauseMainLooper();
controller.create();
assertThat(shadowOf(Looper.getMainLooper()).isPaused()).isTrue();
assertStringsInclude(transcript, "finishedOnCreate");
ShadowLooper.unPauseMainLooper();
assertStringsInclude(transcript, "onCreate");
}
@Test
public void visible_addsTheDecorViewToTheWindowManager() {
controller.create().visible();
assertEquals(controller.get().getWindow().getDecorView().getParent().getClass().getName(), "android.view.ViewRootImpl");
}
@Test
public void start_callsPerformStartWhilePaused() {
controller.create().start();
assertStringsInclude(transcript, "finishedOnStart", "onStart");
}
@Test
public void stop_callsPerformStopWhilePaused() {
controller.create().start().stop();
assertStringsInclude(transcript, "finishedOnStop", "onStop");
}
@Test
public void restart_callsPerformRestartWhilePaused() {
controller.create().start().stop().restart();
assertStringsInclude(transcript, "finishedOnRestart", "onRestart");
}
@Test
public void pause_callsPerformPauseWhilePaused() {
controller.create().pause();
assertStringsInclude(transcript, "finishedOnPause", "onPause");
}
@Test
public void resume_callsPerformResumeWhilePaused() {
controller.create().start().resume();
assertStringsInclude(transcript, "finishedOnResume", "onResume");
}
@Test
public void destroy_callsPerformDestroyWhilePaused() {
controller.create().destroy();
assertStringsInclude(transcript, "finishedOnDestroy", "onDestroy");
}
@Test
public void postCreate_callsOnPostCreateWhilePaused() {
controller.create().postCreate(new Bundle());
assertStringsInclude(transcript, "finishedOnPostCreate", "onPostCreate");
}
@Test
public void postResume_callsOnPostResumeWhilePaused() {
controller.create().postResume();
assertStringsInclude(transcript, "finishedOnPostResume", "onPostResume");
}
@Test
public void restoreInstanceState_callsPerformRestoreInstanceStateWhilePaused() {
controller.create().restoreInstanceState(new Bundle());
assertStringsInclude(transcript, "finishedOnRestoreInstanceState", "onRestoreInstanceState");
}
@Test
public void newIntent_callsOnNewIntentWhilePaused() {
controller.create().newIntent(new Intent(Intent.ACTION_VIEW));
assertStringsInclude(transcript, "finishedOnNewIntent", "onNewIntent");
}
@Test
public void userLeaving_callsPerformUserLeavingWhilePaused() {
controller.create().userLeaving();
assertStringsInclude(transcript, "finishedOnUserLeaveHint", "onUserLeaveHint");
}
@Test
public void setup_callsLifecycleMethodsAndMakesVisible() {
controller.setup();
assertStringsInclude(transcript, "onCreate", "onStart", "onPostCreate", "onResume", "onPostResume");
assertEquals(controller.get().getWindow().getDecorView().getParent().getClass().getName(), "android.view.ViewRootImpl");
}
@Test
public void setupWithBundle_callsLifecycleMethodsAndMakesVisible() {
controller.setup(new Bundle());
assertStringsInclude(transcript, "onCreate", "onStart", "onRestoreInstanceState", "onPostCreate", "onResume", "onPostResume");
assertEquals(controller.get().getWindow().getDecorView().getParent().getClass().getName(), "android.view.ViewRootImpl");
}
@Test
@Config(sdk = Build.VERSION_CODES.KITKAT)
public void attach_shouldWorkWithAPI19() {
MyActivity activity = Robolectric.buildActivity(MyActivity.class).create().get();
assertThat(activity).isNotNull();
}
@Test
@Config(sdk = Build.VERSION_CODES.KITKAT)
public void shouldUseCorrectRuntimeAdapter() {
ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", 15);
MyActivity activity = Robolectric.buildActivity(MyActivity.class).setup().get();
assertThat(activity).isNotNull();
RuntimeAdapter adapter = RuntimeAdapterFactory.getInstance();
assertThat(adapter.getClass().getName()).isEqualTo("org.robolectric.android.runtime.Api19RuntimeAdapter");
}
@Test
public void configurationChange_callsLifecycleMethodsAndAppliesConfig() {
Configuration config = new Configuration(RuntimeEnvironment.application.getResources().getConfiguration());
final float newFontScale = config.fontScale *= 2;
controller.configurationChange(config);
assertStringsInclude(
transcript, "onPause",
"onStop",
"onDestroy",
"onCreate",
"onStart",
"onRestoreInstanceState",
"onPostCreate",
"onResume");
assertThat(controller.get().getResources().getConfiguration().fontScale).isEqualTo(newFontScale);
}
@Test
public void configurationChange_callsOnConfigurationChangedAndAppliesConfigWhenAllManaged() {
Configuration config = new Configuration(RuntimeEnvironment.application.getResources().getConfiguration());
final float newFontScale = config.fontScale *= 2;
ActivityController<ConfigAwareActivity> configController = Robolectric.buildActivity(ConfigAwareActivity.class);
configController.configurationChange(config);
assertStringsInclude(transcript, "onConfigurationChanged");
assertThat(configController.get().getResources().getConfiguration().fontScale).isEqualTo(newFontScale);
}
@Test
public void configurationChange_callsLifecycleMethodsAndAppliesConfigWhenAnyNonManaged() {
Configuration config = new Configuration(RuntimeEnvironment.application.getResources().getConfiguration());
final float newFontScale = config.fontScale *= 2;
final int newOrientation = config.orientation = (config.orientation + 1) % 3;
ActivityController<ConfigAwareActivity> configController = Robolectric.buildActivity(ConfigAwareActivity.class);
configController.configurationChange(config);
assertStringsInclude(transcript, "onPause", "onStop", "onDestroy", "onCreate", "onStart", "onResume");
assertThat(configController.get().getResources().getConfiguration().fontScale).isEqualTo(newFontScale);
assertThat(configController.get().getResources().getConfiguration().orientation).isEqualTo(newOrientation);
}
public static class MyActivity extends Activity {
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
transcribeWhilePaused("onRestoreInstanceState");
transcript.add("finishedOnRestoreInstanceState");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
setContentView(new LinearLayout(RuntimeEnvironment.application));
transcribeWhilePaused("onCreate");
transcript.add("finishedOnCreate");
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
transcribeWhilePaused("onPostCreate");
transcript.add("finishedOnPostCreate");
}
@Override
protected void onPostResume() {
super.onPostResume();
transcribeWhilePaused("onPostResume");
transcript.add("finishedOnPostResume");
}
@Override
protected void onDestroy() {
super.onDestroy();
transcribeWhilePaused("onDestroy");
transcript.add("finishedOnDestroy");
}
@Override
protected void onStart() {
super.onStart();
transcribeWhilePaused("onStart");
transcript.add("finishedOnStart");
}
@Override
protected void onStop() {
super.onStop();
transcribeWhilePaused("onStop");
transcript.add("finishedOnStop");
}
@Override
protected void onResume() {
super.onResume();
transcribeWhilePaused("onResume");
transcript.add("finishedOnResume");
}
@Override
protected void onRestart() {
super.onRestart();
transcribeWhilePaused("onRestart");
transcript.add("finishedOnRestart");
}
@Override
protected void onPause() {
super.onPause();
transcribeWhilePaused("onPause");
transcript.add("finishedOnPause");
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
transcribeWhilePaused("onNewIntent");
transcript.add("finishedOnNewIntent");
}
@Override
protected void onUserLeaveHint() {
super.onUserLeaveHint();
transcribeWhilePaused("onUserLeaveHint");
transcript.add("finishedOnUserLeaveHint");
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
transcribeWhilePaused("onConfigurationChanged");
transcript.add("finishedOnConfigurationChanged");
}
private void transcribeWhilePaused(final String event) {
runOnUiThread(new Runnable() {
@Override public void run() {
transcript.add(event);
}
});
}
}
public static class ConfigAwareActivity extends MyActivity {
}
}