it-roy-ru.com

Как проверить значения TextInputLayout (подсказка, ошибка и т.д.) С помощью Android Espresso?

Я пытаюсь проверить с помощью Espresso, есть ли в моих представлениях TextInputLayout особая подсказка. Я использовал код, как показано ниже:

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

Это нормально работает для обычных представлений EditText, а не в TextInputLayout. Однако, когда это оборачивается, это больше не работает.

Я пытался использовать решение из Android Espresso - Как проверить подсказку EditText? , но все равно не работает.

Я также изучил: https://code.google.com/p/Android/issues/detail?id=191261 который сообщил о проблеме, он говорит, что обходной путь довольно прост, указав на текущий код withHint, но я не могу заставить его работать. 

Есть идеи, чтобы решить эту проблему?

14
Elye

Вот мой пользовательский сопоставитель:

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) {
            }
        };
    }
}

и вот как использовать:

@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))));

    }

Если вы хотите проверить errorText из TextInputLayout, измените эту строку:

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

с

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

Надеюсь, это поможет

28
piotrek1543

Более общее решение, которое будет работать с любым View, у которого есть метод "getHint":

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;
        }
    };
}

Использование:

onView(withId(R.id.SomeLayout)).check(matches(withCustomHint(is("SomeString"))));
1
Anton Tananaev

Гораздо более простое решение - проверить, виден ли текст ошибки, например:

val text = mTestRule.getActivity().getString(R.string.error_text)
onView(withText(text)).check(matches(isDisplayed()))
0
RobertoAllende

Вышеуказанные решения не сработали для моего варианта использования. Я хотел найти TextInputEditText и ввести в него текст. Вот мое решение:

    @VisibleForTesting
class WithTextInputLayoutHintMatcher @RemoteMsgConstructor
constructor(@field:RemoteMsgField(order = 0)
            private val stringMatcher: Matcher<String>) : TypeSafeMatcher<View>() {

    override fun describeTo(description: Description) {
        description.appendText("with TextInputLayout hint: ")
        stringMatcher.describeTo(description)
    }

    public override fun matchesSafely(textInputEditText: View): Boolean {
        if (textInputEditText !is TextInputEditText) return false

        return stringMatcher.matches((textInputEditText.parent.parent as? TextInputLayout)?.hint)
    }
}

/**
 * Returns a matcher that matches [TextInputEditText] based on it's hint property value.
 *
 *
 * **Note:** View's sugar for `withHint(is("string"))`.
 *
 * @param hintText [String] with the hint text to match
 */
fun withTextInputHint(hintText: String): Matcher<View> {
    return withTextInputHint(Matchers.`is`(checkNotNull(hintText)))
}

/**
 * Returns a matcher that matches a descendant of [TextInputEditText] that is displaying the hint
 * associated with the given resource id.
 *
 * @param resourceId the string resource the text view is expected to have as a hint.
 */
fun withTextInputHint(resourceId: Int): Matcher<View> {
    return withTextInputHint(getString(resourceId))
}

/**
 * Returns a matcher that matches [TextView]s based on hint property value.
 *
 *
 * **Note:** View's hint property can be `null`, to match against it use `
 * withHint(nullValue(String.class)`
 *
 * @param stringMatcher [`Matcher
`](http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matcher.html) *  of [String] with text to match
 */
fun withTextInputHint(stringMatcher: Matcher<String>): Matcher<View> {
    return WithTextInputLayoutHintMatcher(checkNotNull(stringMatcher))
}

Использование:

onView(withTextInputHint(R.string.hint)).perform(ViewActions.typeText("Type text here"))

0
Peter Keefe