27

I'm starting to play with Espresso, got my basic tests running. Now trying to figure out how to check that my edit text has a specific hint text? Thanks.

onView(withId(R.id.locationInput)).check(matches...?)

tomrozb
  • 25,773
  • 31
  • 101
  • 122
Eduard
  • 3,482
  • 2
  • 27
  • 45

4 Answers4

61

Since Espresso 2.0 just use internal ViewMatcher withHint:

onView(withId(R.id.locationInput)).check(matches(withHint("your_hint")))
Dmytro Bilko
  • 727
  • 1
  • 7
  • 12
  • 1
    This should now be the accepted answer - it supports `String`, `Matcher` and `int` (resource id) arguments. – David Lord Mar 18 '16 at 00:56
  • 7
    This doesn't work when the EditText is wrapped in TextInputLayout. https://code.google.com/p/android/issues/detail?id=191261 – Elye Aug 09 '16 at 01:10
  • This doesn't work when the EditText is wrapped in TextInputLayout,Debug log shows hintText as null – Sam Oct 27 '16 at 12:12
20

Looks like I figured it out. Basically, you need to create your own matcher:

public static Matcher<View> withHint(final String expectedHint) {
    return new TypeSafeMatcher<View>() {

        @Override
        public boolean matchesSafely(View view) {
            if (!(view instanceof EditText)) {
                return false;
            }

            String hint = ((EditText) view).getHint().toString();

            return expectedHint.equals(hint);
        }

        @Override
        public void describeTo(Description description) {
        }
    };
}

Then you can use it:

onView(withId(R.id.locationInput)).check(matches(withHint("Location (Optional)")));
Snicolas
  • 37,840
  • 15
  • 114
  • 173
Eduard
  • 3,482
  • 2
  • 27
  • 45
  • 1
    You can also use BoundedMatcher to avoid the instanceof check: https://code.google.com/p/android-test-kit/source/browse/espresso/lib/src/main/java/com/google/android/apps/common/testing/ui/espresso/matcher/BoundedMatcher.java Here is an example: https://code.google.com/p/android-test-kit/source/browse/espresso/lib/src/main/java/com/google/android/apps/common/testing/ui/espresso/matcher/ViewMatchers.java?r=e57a8823a21e05c85a268603d6abe4114fd2dc7c#368 – ValeraZakharov Dec 13 '13 at 21:54
  • TypeSafeMatcher is deprecated, then what can I use? – Daniel Gomez Rico Jun 30 '15 at 01:07
  • 2
    org.junit.internal.matchers.TypeSafeMatcher is deprecated. Use org.hamcrest.TypeSafeMatcher instead. – Maurice Gavin Aug 06 '15 at 15:28
3

There is a slightly different way to do it. In my case you check that the String is not null, before pass it to matcher (as explained in Espresso examples). And also in code below you don't need the R.id of the EditText with this hint. You just check if hint with "hintText" is displayed:

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

public final class Matchers {

    public static Matcher<View> withItemHint(String hintText) {
        // use preconditions to fail fast when a test is creating an invalid matcher.
        checkArgument(!(hintText.equals(null)));
        return withItemHint(is(hintText));
    }

    public static Matcher<View> withItemHint(final Matcher<String> matcherText) {
        // use preconditions to fail fast when a test is creating an invalid matcher.
        checkNotNull(matcherText);
        return new BoundedMatcher<View, EditText>(EditText.class) {      

            @Override
            public void describeTo(Description description) {
                description.appendText("with item hint: " + matcherText);
            }

            @Override
            protected boolean matchesSafely(EditText editTextField) {
                return matcherText.matches(editTextField.getHint().toString());
            }
        };
    }
}

Usage:

import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.isDisplayed;
import static com.google.android.apps.common.testing.ui.espresso.assertion.ViewAssertions.matches;
import static com.google.android.apps.common.testing.ui.espresso.Espresso.onView;
import static com.your.package.withMatcher.withItemHint;
.
.
.
onView(withItemHint(someHintString)).check(matches(isDisplayed()));
denys
  • 6,834
  • 3
  • 37
  • 36
1

I've created a Matcher that supports passing a resourceId instead of a String

public static Matcher<View> withHint(final int resourceId) {
     return new BoundedMatcher<View, TextView>(TextView.class) {
     private String resourceName = null;
     private String expectedHint = null;

     @Override
     public boolean matchesSafely(TextView editText) {
        if (null == expectedHint) {
          try {
            expectedHint = editText.getResources().getString(resourceId);
            resourceName = editText.getResources().getResourceEntryName(resourceId);
          } catch (Resources.NotFoundException ignored) {
            /* view could be from a context unaware of the resource id. */
          }
        }

        if (null != expectedHint) {
          return expectedHint.equals(editText.getHint());
        } else {
          return false;
        }
      }

      @Override
      public void describeTo(Description description) {
        description.appendText("with string from resource id: ");
        description.appendValue(resourceId);
        if (null != resourceName) {
          description.appendText("[");
          description.appendText(resourceName);
          description.appendText("]");
        }
        if (null != expectedHint) {
          description.appendText(" value: ");
          description.appendText(expectedHint);
        }
      }
    };
  }

It's a replication of Espresso's withText matcher pointed by Valera Zakharov (withText(resourceId)

Maragues
  • 37,861
  • 14
  • 95
  • 96