Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Espresso. How to check ErrorText in TextInputLayout

Basically I am trying to test that after login incorrectly I have an error showing in the email field.

The view is:

<android.support.design.widget.TextInputLayout
    android:id="@+id/ti_email"
    android:paddingEnd="10dp"
    android:paddingTop="10dp"
    android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:paddingStart="10dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <EditText
        android:id="@+id/et_email"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/authentication_email_placeholder"
        android:inputType="textEmailAddress"
        android:maxLines="1"
        android:textSize="16sp"
        tools:text="@string/placeholder_email"/>

</android.support.design.widget.TextInputLayout>

I try to do it like this:

onView(withId(R.id.et_email))
    .check(matches(hasErrorText(
        ctx.getString(R.string.authentication_error_empty_email))));
like image 854
RogerParis Avatar asked Dec 15 '15 09:12

RogerParis


4 Answers

If you don't want to use a custom matcher, in Kotlin you can get the same result by

    val expectedString = ctx.getString(R.string.authentication_error_empty_email)
    onView(ViewMatchers.withId(R.id.ti_email))
        .check { view, _ ->
            val actualError = (view as TextInputLayout).error
            assertEquals(actualError, expectedError)
        }

}

I like this way best because it allows flexibility with any view

like image 83
Stefan Indaco Avatar answered Sep 29 '22 18:09

Stefan Indaco


This works with a CustomMatcher:

public static Matcher<View> hasTextInputLayoutErrorText(final String expectedErrorText) {
    return new TypeSafeMatcher<View>() {

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

            CharSequence error = ((TextInputLayout) view).getError();

            if (error == null) {
                return false;
            }

            String hint = error.toString();

            return expectedErrorText.equals(hint);
        }

        @Override
        public void describeTo(Description description) {
        }
    };
}
like image 23
RogerParis Avatar answered Oct 19 '22 14:10

RogerParis


You could write a Custom Matcher:

public final class CustomItemMatchers {

private static class TextInputLayoutErrorMatcher extends BoundedMatcher<Object, Wrapper> {

  private final Matcher<String> itemTextMatcher;

  public TextInputLayoutErrorMatcher(final Matcher<String> itemTextMatcher){
     super(TextInputLayout.class);
     this.itemTextMatcher = itemTextMatcher;
  }

  @Override
  public void describeTo(Description description) {
     description.appendText("with error  content: ");
     itemTextMatcher.describeTo(description);
  }

  @Override
  protected boolean matchesSafely(TextInputLayout til) {
     if (til == null) {
        return false;
     }
     return itemTextMatcher.matches((til.getError());
  }
}

public static Matcher<Object> withErrorName(final Matcher<String> itemTextMatcher) {
  checkNotNull(itemTextMatcher);
  return new TextInputLayoutErrorMatcher(itemTextMatcher);
}
}

You can use it then with

matches(CustomItemMatchers.withErrorName(equalTo("My Error")))

This code was written with Espresso 1, but I hope it still works.

like image 4
Christopher Avatar answered Oct 19 '22 12:10

Christopher


I think that you would like to set error on TextInputLayout not on EditText. If it is correct, in the following way you could achieve this.

 onView(withId(R.id.ti_email)).check(matches(hasDescendant(
    withText(ctx.getString(R.string.authentication_error_empty_email))))
 )
like image 4
heronsanches Avatar answered Oct 19 '22 14:10

heronsanches