Donal Rafferty
Donal Rafferty

Reputation: 19826

Android Espresso testing withHint doesn't work

I am currently trying to add Espresso UI testing to my Android application and I want to be able to target a TextInputEditText via it's Hint field and then click on it and enter in some text. (I know it's better practice to target ids but I need to target hint in this instance)

Here is how I have tried to do this:

Espresso.onView(Matchers.allOf(Matchers.instanceOf(TextInputEditText::class.java),
            ViewMatchers.withHint("My Hint"))).
            perform(ViewActions.click(), ViewActions.typeText("type this"))

However when trying to execute this I get the following error:

android.support.test.espresso.NoMatchingViewException: No views in hierarchy found matching: (an instance of android.support.design.widget.TextInputEditText and with hint: is "Old Password")

Even though the output shows that the hierarchy actually does hold this view as follows:

TextInputEditText{id=2131820762, res-name=input_data, visibility=VISIBLE, width=1328, height=168, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=true, is-focusable=true, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=true, editor-info=[inputType=0x80091 imeOptions=0x8000005 privateImeOptions=null actionLabel=null actionId=0 initialSelStart=0 initialSelEnd=0 initialCapsMode=0x0 hintText=My Hint label=null packageName=null fieldId=0 fieldName=null extras=null hintLocales=null contentMimeTypes=null ], x=0.0, y=0.0, text=, input-type=524433, ime-target=true, has-links=false}

Is the ViewMatchers.withHint method broken in Espresso or is there a particular way to use it? Why would it fail to find the view but then in the output actually show it is in the hierarchy?

Upvotes: 2

Views: 1273

Answers (3)

fikr4n
fikr4n

Reputation: 3420

I faced the same issue, and found no solution on stackoverflow. My hypothesis is that the hint is of a CharSequence that doesn't match the expected string. So that, I think the hint needs to be converted to string before matching. Using hasToString works for me.

    onView(allOf(
        instanceOf(TextInputEditText::class.java),
        withHint(hasToString("My Hint"))
    )).perform(click(), typeText("type this"))

Upvotes: 1

mark w.
mark w.

Reputation: 1097

There is a bug open for this already. See: https://issuetracker.google.com/issues/37139118

Upvotes: 2

Aaron
Aaron

Reputation: 3894

The printing in your Logcat may be misleading. If your TextInputEditText is a child view of TextInputLayout with hint is enabled, the TextInputLayout will set the same hint internally on itself via TextInputLayout.setHint, then set the hint on TextInputEditText to null.

You need to create a custom matcher to match hints of TextInputEditText as workaround:

fun withHint(title: String): Matcher<View> = withHint(equalTo(title))

fun withHint(matcher: Matcher<String>): Matcher<View> = object : BoundedMatcher<View, TextInputEditText>(TextInputEditText::class.java) {
    override fun describeTo(description: Description) {
        description.appendText("with hint: ")
        matcher.describeTo(description)
    }

    override fun matchesSafely(item: TextInputEditText): Boolean {
        val parent = item.parent.parent
        return if (parent is TextInputLayout) matcher.matches(parent.hint) else matcher.matches(item.hint)
    }
}

And just replace your ViewMatchers.withHint("My Hint") to TextInputEditTextCustomMatchers.withHint("My Hint").

Upvotes: 0

Related Questions