diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index dd1bbf03c..774a66d71 100755
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -20,10 +20,13 @@
-
+
Profile
People
Settings
+
+ This is a test message
+ Undo
\ No newline at end of file
diff --git a/tests/src/android/support/design/testutils/TestUtilsActions.java b/tests/src/android/support/design/testutils/TestUtilsActions.java
index 320f6e761..e0c6bd326 100644
--- a/tests/src/android/support/design/testutils/TestUtilsActions.java
+++ b/tests/src/android/support/design/testutils/TestUtilsActions.java
@@ -21,12 +21,14 @@ import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
+import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.hamcrest.Matcher;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast;
public class TestUtilsActions {
@@ -73,4 +75,30 @@ public class TestUtilsActions {
}
};
}
+
+ /**
+ * Sets layout direction on the view.
+ */
+ public static ViewAction setLayoutDirection(final int layoutDirection) {
+ return new ViewAction() {
+ @Override
+ public Matcher getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return "set layout direction";
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ uiController.loopMainThreadUntilIdle();
+
+ ViewCompat.setLayoutDirection(view, layoutDirection);
+
+ uiController.loopMainThreadUntilIdle();
+ }
+ };
+ }
}
diff --git a/tests/src/android/support/design/widget/SnackbarTest.java b/tests/src/android/support/design/widget/SnackbarTest.java
index 9f429a787..145261eba 100644
--- a/tests/src/android/support/design/widget/SnackbarTest.java
+++ b/tests/src/android/support/design/widget/SnackbarTest.java
@@ -16,28 +16,42 @@
package android.support.design.widget;
+import android.content.res.Resources;
import android.os.SystemClock;
+import android.support.annotation.Nullable;
+import android.support.annotation.StringRes;
import android.support.design.test.R;
+import android.support.test.InstrumentationRegistry;
import android.support.test.espresso.ViewAction;
import android.support.test.espresso.ViewInteraction;
-import android.support.test.espresso.action.ViewActions;
+import android.support.v4.view.ViewCompat;
import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
import android.view.View;
import org.junit.Before;
import org.junit.Test;
+import static android.support.design.testutils.TestUtilsActions.setLayoutDirection;
import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.action.ViewActions.*;
+import static android.support.test.espresso.matcher.ViewMatchers.*;
+import static org.hamcrest.core.AllOf.allOf;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;
public class SnackbarTest extends BaseInstrumentationTestCase {
private static final String MESSAGE_TEXT = "Test Message";
+ private static final @StringRes int MESSAGE_ID = R.string.snackbar_text;
private static final String ACTION_TEXT = "Action";
+ private static final @StringRes int ACTION_ID = R.string.snackbar_action;
private CoordinatorLayout mCoordinatorLayout;
+ private static interface DismissAction {
+ void dismiss(Snackbar snackbar);
+ }
+
public SnackbarTest() {
super(SnackbarActivity.class);
}
@@ -48,7 +62,74 @@ public class SnackbarTest extends BaseInstrumentationTestCase
(CoordinatorLayout) mActivityTestRule.getActivity().findViewById(R.id.col);
}
- private void verifyDismissCallback(final ViewInteraction interaction, final ViewAction action,
+ private void verifySnackbarContent(final Snackbar snackbar, final String expectedMessage,
+ final String expectedAction) {
+ // Now show the Snackbar
+ snackbar.show();
+ // Sleep for the animation
+ SystemClock.sleep(Snackbar.ANIMATION_DURATION + 50);
+
+ // Verify that we're showing the message
+ withText(expectedMessage).matches(allOf(
+ isDescendantOfA(isAssignableFrom(Snackbar.SnackbarLayout.class)),
+ isCompletelyDisplayed()));
+
+ // If the action is not empty, verify that we're showing it
+ if (!TextUtils.isEmpty(expectedAction)) {
+ withText(expectedAction).matches(allOf(
+ isDescendantOfA(isAssignableFrom(Snackbar.SnackbarLayout.class)),
+ isCompletelyDisplayed()));
+ }
+
+ // Dismiss the snackbar
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ snackbar.dismiss();
+ }
+ });
+ }
+
+ @Test
+ @SmallTest
+ public void testBasicContent() {
+ // Verify different combinations of snackbar content (message and action) and duration
+
+ final Resources res = mActivityTestRule.getActivity().getResources();
+ final String resolvedMessage = res.getString(MESSAGE_ID);
+ final String resolvedAction = res.getString(ACTION_ID);
+
+ // String message and no action
+ verifySnackbarContent(
+ Snackbar.make(mCoordinatorLayout, MESSAGE_TEXT, Snackbar.LENGTH_SHORT),
+ MESSAGE_TEXT, null);
+
+ // Resource message and no action
+ verifySnackbarContent(
+ Snackbar.make(mCoordinatorLayout, MESSAGE_ID, Snackbar.LENGTH_LONG),
+ resolvedMessage, null);
+
+ // String message and string action
+ verifySnackbarContent(
+ Snackbar.make(mCoordinatorLayout, MESSAGE_TEXT, Snackbar.LENGTH_INDEFINITE)
+ .setAction(ACTION_TEXT, mock(View.OnClickListener.class)),
+ MESSAGE_TEXT, ACTION_TEXT);
+
+ // String message and resource action
+ verifySnackbarContent(
+ Snackbar.make(mCoordinatorLayout, MESSAGE_TEXT, Snackbar.LENGTH_SHORT)
+ .setAction(ACTION_ID, mock(View.OnClickListener.class)),
+ MESSAGE_TEXT, resolvedAction);
+
+ // Resource message and resource action
+ verifySnackbarContent(
+ Snackbar.make(mCoordinatorLayout, MESSAGE_ID, Snackbar.LENGTH_LONG)
+ .setAction(ACTION_ID, mock(View.OnClickListener.class)),
+ resolvedMessage, resolvedAction);
+ }
+
+ private void verifyDismissCallback(final ViewInteraction interaction,
+ final @Nullable ViewAction action, final @Nullable DismissAction dismissAction,
final int length, @Snackbar.Callback.DismissEvent final int expectedEvent) {
final Snackbar.Callback mockCallback = mock(Snackbar.Callback.class);
final Snackbar snackbar = Snackbar.make(mCoordinatorLayout, MESSAGE_TEXT, length)
@@ -60,7 +141,16 @@ public class SnackbarTest extends BaseInstrumentationTestCase
// Sleep for the animation
SystemClock.sleep(Snackbar.ANIMATION_DURATION + 50);
// ...and perform the UI interaction
- interaction.perform(action);
+ if (action != null) {
+ interaction.perform(action);
+ } else if (dismissAction != null) {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ dismissAction.dismiss(snackbar);
+ }
+ });
+ }
// Now wait until the Snackbar has been removed from the view hierarchy
while (snackbar.isShownOrQueued()) {
SystemClock.sleep(20);
@@ -73,24 +163,98 @@ public class SnackbarTest extends BaseInstrumentationTestCase
@Test
@MediumTest
- public void testActionClickDismiss() {
+ public void testDismissViaActionClick() {
verifyDismissCallback(
onView(withId(R.id.snackbar_action)),
- ViewActions.click(),
+ click(),
+ null,
Snackbar.LENGTH_LONG,
Snackbar.Callback.DISMISS_EVENT_ACTION);
}
@Test
@MediumTest
- public void testSwipeDismissCallback() {
+ public void testDismissViaSwipe() {
verifyDismissCallback(
onView(isAssignableFrom(Snackbar.SnackbarLayout.class)),
- ViewActions.swipeRight(),
+ swipeRight(),
+ null,
Snackbar.LENGTH_LONG,
Snackbar.Callback.DISMISS_EVENT_SWIPE);
}
+ @Test
+ @MediumTest
+ public void testDismissViaSwipeRtl() {
+ onView(withId(R.id.col)).perform(setLayoutDirection(ViewCompat.LAYOUT_DIRECTION_RTL));
+ if (ViewCompat.getLayoutDirection(mCoordinatorLayout) == ViewCompat.LAYOUT_DIRECTION_RTL) {
+ // On devices that support RTL layout, the start-to-end dismiss swipe is done
+ // with swipeLeft() action
+ verifyDismissCallback(
+ onView(isAssignableFrom(Snackbar.SnackbarLayout.class)),
+ swipeLeft(),
+ null,
+ Snackbar.LENGTH_LONG,
+ Snackbar.Callback.DISMISS_EVENT_SWIPE);
+ }
+ }
+
+ @Test
+ @MediumTest
+ public void testDismissViaApi() {
+ verifyDismissCallback(
+ onView(isAssignableFrom(Snackbar.SnackbarLayout.class)),
+ null,
+ new DismissAction() {
+ @Override
+ public void dismiss(Snackbar snackbar) {
+ snackbar.dismiss();
+ }
+ },
+ Snackbar.LENGTH_LONG,
+ Snackbar.Callback.DISMISS_EVENT_MANUAL);
+ }
+
+ @Test
+ @MediumTest
+ public void testDismissViaTimeout() {
+ verifyDismissCallback(
+ onView(isAssignableFrom(Snackbar.SnackbarLayout.class)),
+ null,
+ null,
+ Snackbar.LENGTH_LONG,
+ Snackbar.Callback.DISMISS_EVENT_TIMEOUT);
+ }
+
+ @Test
+ @MediumTest
+ public void testDismissViaAnotherSnackbar() {
+ final Snackbar anotherSnackbar =
+ Snackbar.make(mCoordinatorLayout, "A different message", Snackbar.LENGTH_SHORT);
+
+ // Our dismiss action is to show another snackbar (and verify that the original snackbar
+ // is now dismissed with CONSECUTIVE event)
+ verifyDismissCallback(
+ onView(isAssignableFrom(Snackbar.SnackbarLayout.class)),
+ null,
+ new DismissAction() {
+ @Override
+ public void dismiss(Snackbar snackbar) {
+ anotherSnackbar.show();
+ }
+ },
+ Snackbar.LENGTH_LONG,
+ Snackbar.Callback.DISMISS_EVENT_CONSECUTIVE);
+
+ // And dismiss the second snackbar to get back to clean state
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ anotherSnackbar.dismiss();
+ }
+ });
+ }
+
@Test
@MediumTest
public void testActionClickListener() {
@@ -103,7 +267,7 @@ public class SnackbarTest extends BaseInstrumentationTestCase
// Sleep for the animation
SystemClock.sleep(Snackbar.ANIMATION_DURATION + 50);
// Perform the action click
- onView(withId(R.id.snackbar_action)).perform(ViewActions.click());
+ onView(withId(R.id.snackbar_action)).perform(click());
verify(mockClickListener, times(1)).onClick(any(View.class));
}