diff --git a/app/build.gradle b/app/build.gradle index ae13fda3..67b8e287 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -53,6 +53,9 @@ android { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 } + defaultConfig { + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } } dependencies { @@ -111,6 +114,12 @@ dependencies { testCompile 'org.mockito:mockito-all:1.9.5' testCompile 'org.skyscreamer:jsonassert:1.2.3' testCompile(name: 'org.apache.http.legacy', ext: 'jar') + + androidTestCompile 'com.android.support:support-annotations:23.1.1' + androidTestCompile 'com.android.support.test:runner:0.4.1' + androidTestCompile 'com.android.support.test:rules:0.4.1' + androidTestCompile 'org.hamcrest:hamcrest-library:1.3' + androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1' } apt { diff --git a/app/src/androidTest/java/net/slideshare/mobile/test/util/OrientationChangeAction.java b/app/src/androidTest/java/net/slideshare/mobile/test/util/OrientationChangeAction.java new file mode 100644 index 00000000..2aa70ee5 --- /dev/null +++ b/app/src/androidTest/java/net/slideshare/mobile/test/util/OrientationChangeAction.java @@ -0,0 +1,79 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 - Nathan Barraille + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +package net.slideshare.mobile.test.util; + +import android.app.Activity; +import android.content.pm.ActivityInfo; +import android.support.test.espresso.UiController; +import android.support.test.espresso.ViewAction; +import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry; +import android.support.test.runner.lifecycle.Stage; +import android.view.View; +import org.hamcrest.Matcher; + +import java.util.Collection; + +import static android.support.test.espresso.matcher.ViewMatchers.isRoot; + +/** + * An Espresso ViewAction that changes the orientation of the screen + */ +public class OrientationChangeAction implements ViewAction { + private final int orientation; + + private OrientationChangeAction(int orientation) { + this.orientation = orientation; + } + + @Override + public Matcher getConstraints() { + return isRoot(); + } + + @Override + public String getDescription() { + return "change orientation to " + orientation; + } + + @Override + public void perform(UiController uiController, View view) { + uiController.loopMainThreadUntilIdle(); + final Activity activity = (Activity) view.getContext(); + activity.setRequestedOrientation(orientation); + + Collection resumedActivities = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED); + if (resumedActivities.isEmpty()) { + throw new RuntimeException("Could not change orientation"); + } + } + + public static ViewAction orientationLandscape() { + return new OrientationChangeAction(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } + + public static ViewAction orientationPortrait() { + return new OrientationChangeAction(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/org/solovyev/android/calculator/wizard/WizardActivityTest.java b/app/src/androidTest/java/org/solovyev/android/calculator/wizard/WizardActivityTest.java new file mode 100644 index 00000000..2fb022f6 --- /dev/null +++ b/app/src/androidTest/java/org/solovyev/android/calculator/wizard/WizardActivityTest.java @@ -0,0 +1,65 @@ +package org.solovyev.android.calculator.wizard; + +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; +import android.test.suitebuilder.annotation.LargeTest; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.solovyev.android.calculator.R; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.swipeLeft; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.RootMatchers.isDialog; +import static android.support.test.espresso.matcher.ViewMatchers.*; +import static net.slideshare.mobile.test.util.OrientationChangeAction.orientationLandscape; +import static net.slideshare.mobile.test.util.OrientationChangeAction.orientationPortrait; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.not; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class WizardActivityTest { + + @Rule + public ActivityTestRule rule = new ActivityTestRule<>(WizardActivity.class); + + @Test + public void shouldShowConfirmationDialogOnSkip() { + onView(withText(R.string.cpp_wizard_skip)).perform(click()); + onView(withText(R.string.cpp_wizard_finish_confirmation_title)).inRoot(isDialog()).check(matches(isDisplayed())); + } + + @Test + public void testShouldGoThroughTheWizard() throws Exception { + onView(withText(R.string.cpp_wizard_start)).perform(click()); + onView(withId(R.id.pager)).check(matches(allOf( + hasDescendant(withText(R.string.cpp_wizard_mode_title)), + not(hasDescendant(withText(R.string.cpp_wizard_welcome_title)))))); + + onView(withId(R.id.pager)).perform(swipeLeft()); + onView(withId(R.id.pager)).check(matches(hasDescendant(withText(R.string.cpp_wizard_theme_title)))); + + onView(withId(R.id.pager)).perform(swipeLeft()); + onView(withId(R.id.pager)).check(matches(hasDescendant(withText(R.string.cpp_wizard_onscreen_description)))); + + onView(withId(R.id.pager)).perform(swipeLeft()); + onView(withId(R.id.pager)).check(matches(hasDescendant(withText(R.string.cpp_wizard_dragbutton_description)))); + + onView(withId(R.id.pager)).perform(swipeLeft()); + onView(withId(R.id.pager)).check(matches(hasDescendant(withText(R.string.cpp_wizard_final_done)))); + + onView(withText(R.string.cpp_wizard_final_done)).perform(click()); + } + + @Test + public void testShouldPreserveStepOnScreenRotation() throws Exception { + onView(withId(R.id.pager)).perform(swipeLeft()); + onView(isRoot()).perform(orientationLandscape()); + onView(withId(R.id.pager)).check(matches(hasDescendant(withText(R.string.cpp_wizard_mode_title)))); + onView(isRoot()).perform(orientationPortrait()); + onView(withId(R.id.pager)).check(matches(hasDescendant(withText(R.string.cpp_wizard_mode_title)))); + } +} \ No newline at end of file diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml index c40436a7..56e5cd3c 100644 --- a/app/src/main/res/values/ids.xml +++ b/app/src/main/res/values/ids.xml @@ -58,9 +58,6 @@ - - -