Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test TextInputLayout values (hint, error, etc.) using Android Espresso?

I am trying to test using Espresso if my TextInputLayout views have specific hint. I'd used a code as below:

Espresso.onView(ViewMatchers.withId(R.id.edit_text_email))
    .check(ViewAssertions.matches(
        ViewMatchers.withHint(R.string.edit_text_email_hint)))

This works fine for the normal EditText views, not wrapped in TextInputLayout. However when it wraps around, it no longer works.

I tried to use solution from Android Espresso - How to check EditText hint?, but it still does not working.

I also looked into: https://code.google.com/p/android/issues/detail?id=191261 that reported the issue, it says the workaround is quite easy by pointing to the current withHint code, but I can't get it to work.

Any ideas to fix this issue?

like image 684
Elye Avatar asked Aug 09 '16 04:08

Elye


4 Answers

Here's my custom matcher:

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

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

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

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

                String hint = error.toString();

                return expectedErrorText.equals(hint);
            }

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

and here's how to use:

@RunWith(AndroidJUnit4.class)
public class MainActivityTest {

    @Rule
    public ActivityTestRule<MainActivity> mRule = new ActivityTestRule<>(MainActivity.class);

    @Test
    public void testMyApp() {
        onView(withId(R.id.textInputLayout)).check
                (matches(hasTextInputLayoutErrorText(mRule.getActivity().getString(R.string
                        .app_name))));

    }

If you would like to check errorText of TextInputLayout, change this line:

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

with

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

Hope it will help

like image 162
piotrek1543 Avatar answered Nov 16 '22 06:11

piotrek1543


Kotlin version of piotrek1543's answer:

fun hasTextInputLayoutHintText(expectedErrorText: String): Matcher<View> = object : TypeSafeMatcher<View>() {

    override fun describeTo(description: Description?) { }

    override fun matchesSafely(item: View?): Boolean {
        if (item !is TextInputLayout) return false
        val error = item.hint ?: return false
        val hint = error.toString()
        return expectedErrorText == hint
    }
}
like image 30
Phil Avatar answered Nov 16 '22 06:11

Phil


More generic solution that would work with any View that has "getHint" method:

public static Matcher<View> withCustomHint(final Matcher<String> stringMatcher) {
    return new BaseMatcher<View>() {
        @Override
        public void describeTo(Description description) {
        }

        @Override
        public boolean matches(Object item) {
            try {
                Method method = item.getClass().getMethod("getHint");
                return stringMatcher.matches(method.invoke(item));
            } catch (NoSuchMethodException e) {
            } catch (InvocationTargetException e) {
            } catch (IllegalAccessException e) {
            }
            return false;
        }
    };
}

Usage:

onView(withId(R.id.SomeLayout)).check(matches(withCustomHint(is("SomeString"))));
like image 3
Anton Tananaev Avatar answered Nov 16 '22 05:11

Anton Tananaev


A much more simple solution is to check if the error text is visible, for example:

val text = mTestRule.getActivity().getString(R.string.error_text)
onView(withText(text)).check(matches(isDisplayed()))
like image 2
RobertoAllende Avatar answered Nov 16 '22 06:11

RobertoAllende