blob: 4c3d48cc60769a983e9a1397b0ea4cf7879788ef [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.appcompat.testutils;
import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
import android.support.test.espresso.Espresso;
import android.support.test.espresso.IdlingResource;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.drawerlayout.widget.DrawerLayout;
import org.hamcrest.Matcher;
public class DrawerLayoutActions {
/**
* Drawer listener that serves as Espresso's {@link IdlingResource} and notifies the registered
* callback when the drawer gets to STATE_IDLE state.
*/
private static class CustomDrawerListener
implements DrawerLayout.DrawerListener, IdlingResource {
private int mCurrState = DrawerLayout.STATE_IDLE;
@Nullable private IdlingResource.ResourceCallback mCallback;
private boolean mNeedsIdle = false;
@Override
public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
mCallback = resourceCallback;
}
@Override
public String getName() {
return "Drawer listener";
}
@Override
public boolean isIdleNow() {
if (!mNeedsIdle) {
return true;
} else {
return mCurrState == DrawerLayout.STATE_IDLE;
}
}
@Override
public void onDrawerClosed(View drawer) {
if (mCurrState == DrawerLayout.STATE_IDLE) {
if (mCallback != null) {
mCallback.onTransitionToIdle();
}
}
}
@Override
public void onDrawerOpened(View drawer) {
if (mCurrState == DrawerLayout.STATE_IDLE) {
if (mCallback != null) {
mCallback.onTransitionToIdle();
}
}
}
@Override
public void onDrawerSlide(View drawer, float slideOffset) {
}
@Override
public void onDrawerStateChanged(int state) {
mCurrState = state;
if (state == DrawerLayout.STATE_IDLE) {
if (mCallback != null) {
mCallback.onTransitionToIdle();
}
}
}
}
private abstract static class WrappedViewAction implements ViewAction {
}
public static ViewAction wrap(final ViewAction baseAction) {
if (baseAction instanceof WrappedViewAction) {
throw new IllegalArgumentException("Don't wrap and already wrapped action");
}
return new WrappedViewAction() {
@Override
public Matcher<View> getConstraints() {
return baseAction.getConstraints();
}
@Override
public String getDescription() {
return baseAction.getDescription();
}
@Override
public final void perform(UiController uiController, View view) {
final DrawerLayout drawer = (DrawerLayout) view;
// Add a custom tracker listener
final CustomDrawerListener customListener = new CustomDrawerListener();
drawer.addDrawerListener(customListener);
// Note that we're running the following block in a try-finally construct. This
// is needed since some of the wrapped actions are going to throw (expected)
// exceptions. If that happens, we still need to clean up after ourselves to
// leave the system (Espesso) in a good state.
try {
// Register our listener as idling resource so that Espresso waits until the
// wrapped action results in the drawer getting to the STATE_IDLE state
Espresso.registerIdlingResources(customListener);
baseAction.perform(uiController, view);
customListener.mNeedsIdle = true;
uiController.loopMainThreadUntilIdle();
customListener.mNeedsIdle = false;
} finally {
// Unregister our idling resource
Espresso.unregisterIdlingResources(customListener);
// And remove our tracker listener from DrawerLayout
drawer.removeDrawerListener(customListener);
}
}
};
}
/**
* Opens the drawer at the specified edge gravity.
*/
public static ViewAction openDrawer(final int drawerEdgeGravity, final boolean animate) {
return wrap(new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return isAssignableFrom(DrawerLayout.class);
}
@Override
public String getDescription() {
return "Opens the drawer";
}
@Override
public void perform(UiController uiController, View view) {
uiController.loopMainThreadUntilIdle();
DrawerLayout drawerLayout = (DrawerLayout) view;
drawerLayout.openDrawer(drawerEdgeGravity, animate);
}
});
}
/**
* Opens the drawer at the specified edge gravity.
*/
public static ViewAction openDrawer(final int drawerEdgeGravity) {
return wrap(new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return isAssignableFrom(DrawerLayout.class);
}
@Override
public String getDescription() {
return "Opens the drawer";
}
@Override
public void perform(UiController uiController, View view) {
uiController.loopMainThreadUntilIdle();
DrawerLayout drawerLayout = (DrawerLayout) view;
drawerLayout.openDrawer(drawerEdgeGravity);
}
});
}
/**
* Opens the drawer.
*/
public static ViewAction openDrawer(final View drawerView) {
return wrap(new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return isAssignableFrom(DrawerLayout.class);
}
@Override
public String getDescription() {
return "Opens the drawer";
}
@Override
public void perform(UiController uiController, View view) {
uiController.loopMainThreadUntilIdle();
DrawerLayout drawerLayout = (DrawerLayout) view;
drawerLayout.openDrawer(drawerView);
}
});
}
/**
* Closes the drawer at the specified edge gravity.
*/
public static ViewAction closeDrawer(final int drawerEdgeGravity) {
return wrap(new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return isAssignableFrom(DrawerLayout.class);
}
@Override
public String getDescription() {
return "Closes the drawer";
}
@Override
public void perform(UiController uiController, View view) {
uiController.loopMainThreadUntilIdle();
DrawerLayout drawerLayout = (DrawerLayout) view;
drawerLayout.closeDrawer(drawerEdgeGravity);
}
});
}
/**
* Closes the drawer at the specified edge gravity.
*/
public static ViewAction closeDrawer(final int drawerEdgeGravity, final boolean animate) {
return wrap(new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return isAssignableFrom(DrawerLayout.class);
}
@Override
public String getDescription() {
return "Closes the drawer";
}
@Override
public void perform(UiController uiController, View view) {
uiController.loopMainThreadUntilIdle();
DrawerLayout drawerLayout = (DrawerLayout) view;
drawerLayout.closeDrawer(drawerEdgeGravity, animate);
}
});
}
/**
* Closes the drawer.
*/
public static ViewAction closeDrawer(final View drawerView) {
return wrap(new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return isAssignableFrom(DrawerLayout.class);
}
@Override
public String getDescription() {
return "Closes the drawer";
}
@Override
public void perform(UiController uiController, View view) {
uiController.loopMainThreadUntilIdle();
DrawerLayout drawerLayout = (DrawerLayout) view;
drawerLayout.closeDrawer(drawerView);
}
});
}
/**
* Sets the lock mode for the drawer at the specified edge gravity.
*/
public static ViewAction setDrawerLockMode(final int lockMode, final int drawerEdgeGravity) {
return wrap(new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return isAssignableFrom(DrawerLayout.class);
}
@Override
public String getDescription() {
return "Sets drawer lock mode";
}
@Override
public void perform(UiController uiController, View view) {
uiController.loopMainThreadUntilIdle();
DrawerLayout drawerLayout = (DrawerLayout) view;
drawerLayout.setDrawerLockMode(lockMode, drawerEdgeGravity);
uiController.loopMainThreadUntilIdle();
}
});
}
/**
* Sets the lock mode for the drawer.
*/
public static ViewAction setDrawerLockMode(final int lockMode, final View drawerView) {
return wrap(new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return isAssignableFrom(DrawerLayout.class);
}
@Override
public String getDescription() {
return "Sets drawer lock mode";
}
@Override
public void perform(UiController uiController, View view) {
uiController.loopMainThreadUntilIdle();
DrawerLayout drawerLayout = (DrawerLayout) view;
drawerLayout.setDrawerLockMode(lockMode, drawerView);
uiController.loopMainThreadUntilIdle();
}
});
}
}