From f177bcb465e698bd2aca290f688b6f98d041685c Mon Sep 17 00:00:00 2001 From: Kyle Horimoto Date: Thu, 17 Sep 2015 11:48:35 -0700 Subject: Fix StartupTest tests to work with RecyclerView. --- .../java/org/connectbot/ConnectbotMatchers.java | 112 +++++++++++++-------- .../java/org/connectbot/StartupTest.java | 34 +++---- 2 files changed, 84 insertions(+), 62 deletions(-) (limited to 'app/src/androidTest') diff --git a/app/src/androidTest/java/org/connectbot/ConnectbotMatchers.java b/app/src/androidTest/java/org/connectbot/ConnectbotMatchers.java index 85a071d..a44e88c 100644 --- a/app/src/androidTest/java/org/connectbot/ConnectbotMatchers.java +++ b/app/src/androidTest/java/org/connectbot/ConnectbotMatchers.java @@ -2,7 +2,10 @@ package org.connectbot; import android.support.annotation.ColorInt; import android.support.annotation.NonNull; +import android.support.test.espresso.NoMatchingViewException; +import android.support.test.espresso.ViewAssertion; import android.support.test.espresso.matcher.BoundedMatcher; +import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.ImageView; import android.widget.TextView; @@ -10,22 +13,18 @@ import android.widget.TextView; import org.connectbot.bean.HostBean; import org.hamcrest.Description; import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; - -import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; -import static android.support.test.espresso.matcher.ViewMatchers.withId; -import static org.hamcrest.CoreMatchers.allOf; +import org.junit.Assert; public class ConnectbotMatchers { /** * Matches the nickname of a {@link HostBean}. */ @NonNull - public static Matcher withHostNickname(final String content) { - return new BoundedMatcher(HostBean.class) { + public static Matcher withHostNickname(final String content) { + return new BoundedMatcher(HostListActivity.HostAdapter.ViewHolder.class) { @Override - public boolean matchesSafely(HostBean host) { - return host.getNickname().matches(content); + public boolean matchesSafely(HostListActivity.HostAdapter.ViewHolder holder) { + return holder.host.getNickname().matches(content); } @Override @@ -35,63 +34,90 @@ public class ConnectbotMatchers { }; } - /** - * Matches the drawable state on an ImageView that is set with setImageState. - */ @NonNull - public static Matcher withDrawableState(final int expectedState) { - return new TypeSafeMatcher() { + public static Matcher withConnectedHost() { + return new BoundedMatcher(HostListActivity.HostAdapter.ViewHolder.class) { @Override - public boolean matchesSafely(View view) { - if (!(view instanceof ImageView)) { - return false; - } - - int[] states = view.getDrawableState(); - for (int state : states) { - if (state == expectedState) { - return true; - } - } - return false; + public boolean matchesSafely(HostListActivity.HostAdapter.ViewHolder holder) { + return hasDrawableState(holder.icon, android.R.attr.state_checked); } @Override public void describeTo(Description description) { - description.appendText("with drawable state '" + expectedState + "'"); + description.appendText("is displayed"); } }; } @NonNull - public static Matcher withTextColor(@ColorInt final int expectedColor) { - return new TypeSafeMatcher() { + public static Matcher withDisconnectedHost() { + return new BoundedMatcher(HostListActivity.HostAdapter.ViewHolder.class) { @Override - public boolean matchesSafely(View view) { - if (!(view instanceof TextView)) { - return false; - } - - TextView tv = (TextView) view; - return tv.getCurrentTextColor() == expectedColor; + public boolean matchesSafely(HostListActivity.HostAdapter.ViewHolder holder) { + return hasDrawableState(holder.icon, android.R.attr.state_expanded); } @Override public void describeTo(Description description) { - description.appendText("with color '" + Integer.toHexString(expectedColor) + "'"); + description.appendText("is displayed"); } }; } @NonNull - public static Matcher hostDisconnected() { - return hasDescendant(allOf(withId(android.R.id.icon), - withDrawableState(android.R.attr.state_expanded))); + public static Matcher withColoredText(@ColorInt final int expectedColor) { + return new BoundedMatcher(HostListActivity.HostAdapter.ViewHolder.class) { + @Override + public boolean matchesSafely(HostListActivity.HostAdapter.ViewHolder holder) { + return hasTextColor(holder.nickname, expectedColor); + } + + @Override + public void describeTo(Description description) { + description.appendText("is displayed"); + } + }; + } + + private static boolean hasDrawableState(View view, final int expectedState) { + if (!(view instanceof ImageView)) { + return false; + } + + int[] states = view.getDrawableState(); + for (int state : states) { + if (state == expectedState) { + return true; + } + } + return false; + } + + private static boolean hasTextColor(View view, @ColorInt final int expectedColor) { + if (!(view instanceof TextView)) { + return false; + } + + TextView tv = (TextView) view; + return tv.getCurrentTextColor() == expectedColor; } @NonNull - public static Matcher hostConnected() { - return hasDescendant(allOf(withId(android.R.id.icon), - withDrawableState(android.R.attr.state_checked))); + public static ViewAssertion hasHolderItem(final Matcher viewHolderMatcher) { + return new ViewAssertion() { + @Override public void check(View view, NoMatchingViewException e) { + if (!(view instanceof RecyclerView)) { + throw e; + } + + boolean hasMatch = false; + RecyclerView rv = (RecyclerView) view; + for (int i = 0; i < rv.getChildCount(); i++) { + RecyclerView.ViewHolder vh = rv.findViewHolderForAdapterPosition(i); + hasMatch |= viewHolderMatcher.matches(vh); + } + Assert.assertTrue(hasMatch); + } + }; } } diff --git a/app/src/androidTest/java/org/connectbot/StartupTest.java b/app/src/androidTest/java/org/connectbot/StartupTest.java index 14eabff..72259eb 100644 --- a/app/src/androidTest/java/org/connectbot/StartupTest.java +++ b/app/src/androidTest/java/org/connectbot/StartupTest.java @@ -16,6 +16,7 @@ import android.support.test.InstrumentationRegistry; import android.support.test.espresso.UiController; import android.support.test.espresso.ViewAction; import android.support.test.espresso.action.CloseKeyboardAction; +import android.support.test.espresso.contrib.RecyclerViewActions; import android.support.test.espresso.intent.Intents; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; @@ -36,10 +37,11 @@ import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; import static android.support.test.espresso.matcher.ViewMatchers.withId; import static android.support.test.espresso.matcher.ViewMatchers.withText; -import static org.connectbot.ConnectbotMatchers.hostConnected; -import static org.connectbot.ConnectbotMatchers.hostDisconnected; +import static org.connectbot.ConnectbotMatchers.hasHolderItem; +import static org.connectbot.ConnectbotMatchers.withColoredText; +import static org.connectbot.ConnectbotMatchers.withConnectedHost; +import static org.connectbot.ConnectbotMatchers.withDisconnectedHost; import static org.connectbot.ConnectbotMatchers.withHostNickname; -import static org.connectbot.ConnectbotMatchers.withTextColor; import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; @@ -65,16 +67,16 @@ public class StartupTest { onView(withId(R.id.console_flip)).perform(closeSoftKeyboard(), pressBack()); // Make sure we're still connected. - onData(withHostNickname("Local")).inAdapterView(withId(android.R.id.list)) - .check(matches(hostConnected())) - .perform(longClick()); + onView(withId(R.id.list)) + .check(hasHolderItem(allOf(withHostNickname("Local"), withConnectedHost()))) + .perform(RecyclerViewActions.actionOnHolderItem( + allOf(withHostNickname("Local"), withConnectedHost()), longClick())); // Click on the disconnect context menu item. onView(withText(R.string.list_host_disconnect)).check(matches(isDisplayed())).perform(click()); // Now make sure we're disconnected. - onData(withHostNickname("Local")).inAdapterView(withId(android.R.id.list)) - .check(matches(hostDisconnected())); + onView(withId(R.id.list)).check(hasHolderItem(allOf(withHostNickname("Local"), withDisconnectedHost()))); } @Test @@ -87,15 +89,13 @@ public class StartupTest { onView(withText(R.string.list_host_disconnect)).check(matches(isDisplayed())).perform(click()); // Now make sure we're disconnected. - onData(withHostNickname("Local")).inAdapterView(withId(android.R.id.list)) - .check(matches(hostDisconnected())); + onView(withId(R.id.list)).check(hasHolderItem(allOf(withHostNickname("Local"), withDisconnectedHost()))); } @Test public void localConnectionCanDelete() { startNewLocalConnectionAndGoBack("Local"); - onData(withHostNickname("Local")).inAdapterView(withId(android.R.id.list)) - .perform(longClick()); + onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnHolderItem(withHostNickname("Local"), longClick())); onView(withText(R.string.list_host_delete)).perform(click()); onView(withText(R.string.delete_pos)).perform(click()); } @@ -113,8 +113,7 @@ public class StartupTest { */ private void changeColor(String hostName, @ColorRes int color, @StringRes int stringForColor) { // Bring up the context menu. - onData(withHostNickname(hostName)).inAdapterView(withId(android.R.id.list)) - .perform(longClick()); + onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnHolderItem(withHostNickname(hostName), longClick())); onView(withText(R.string.list_host_edit)).perform(click()); // Click on the color category and select the desired one. @@ -125,16 +124,13 @@ public class StartupTest { onView(withText(R.string.hostpref_color_title)).perform(pressBack()); Resources res = InstrumentationRegistry.getTargetContext().getResources(); - onData(withHostNickname(hostName)).inAdapterView(withId(android.R.id.list)) - .check(matches(hasDescendant(allOf(withId(android.R.id.text1), - withTextColor(res.getColor(color)))))); + onView(withId(R.id.list)).check(hasHolderItem(withColoredText(res.getColor(color)))); } private void startNewLocalConnectionAndGoBack(String name) { startNewLocalConnection(name); onView(withId(R.id.console_flip)).perform(closeSoftKeyboard(), pressBack()); - onData(withHostNickname(name)).inAdapterView(withId(android.R.id.list)) - .check(matches(isDisplayed())); + onView(withId(R.id.list)).check(hasHolderItem(withHostNickname(name))); } private void startNewLocalConnection() { -- cgit v1.2.3