Skip to content

Instantly share code, notes, and snippets.

@nbarraille
Last active January 30, 2023 00:04
Show Gist options
  • Save nbarraille/03e8910dc1d415ed9740 to your computer and use it in GitHub Desktop.
Save nbarraille/03e8910dc1d415ed9740 to your computer and use it in GitHub Desktop.
An Espresso ViewAction that changes the orientation of the screen
/*
* 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.internal.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<View> 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<Activity> 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);
}
}
@levibostian
Copy link

levibostian commented Jan 16, 2019

Kotlin version:

import android.view.View
import androidx.test.espresso.UiController
import androidx.test.espresso.ViewAction
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import org.hamcrest.Matcher
import android.content.pm.ActivityInfo
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry
import android.app.Activity
import androidx.test.runner.lifecycle.Stage

/*
 * 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.
 *
 */

class OrientationChangeAction(private val orientation: Int): ViewAction {

    companion object {
        fun orientationLandscape(): ViewAction = OrientationChangeAction(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
        fun orientationPortrait(): ViewAction = OrientationChangeAction(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
    }

    override fun getDescription(): String = "change orientation to $orientation"

    override fun getConstraints(): Matcher<View> = isRoot()

    override fun perform(uiController: UiController, view: View) {
        uiController.loopMainThreadUntilIdle()
        var activity = getActivity(view.context)
        if (activity == null && view is ViewGroup) {
            val c = view.childCount
            var i = 0
            while (i < c && activity == null) {
                activity = getActivity(view.getChildAt(i).context)
                ++i
            }
        }
        activity!!.requestedOrientation = orientation
    }

    private fun getActivity(context: Context): Activity? {
        var context = context
        while (context is ContextWrapper) {
            if (context is Activity) {
                return context
            }
            context = (context as ContextWrapper).baseContext
        }
        return null
    }

}

@anandwana001
Copy link

anandwana001 commented Nov 1, 2020

@nbarraille Does this work when we use config annotation?
I tried to run Espresso test case, it worked, but not with Robolectric. I guess I might facing robolectric issue!!

@Config(
  qualifiers = "port-xxhdpi"
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment