Android Espresso can't find a Edittext inside a custom view class

Viewed 322

Possible Duplicate 1

Possible Duplicate 2

I have a custom View which contains textview and edittext. I want to access the Edittext in my custom View for UI test. But I dont want to use custom ViewAction to setEdittext because in that case I wont be able to support the methods like typeText. Here is my test method

@RunWith(AndroidJUnit4::class)
class LoginFragmentTest : BaseTest() {
  @Test
  @Throws(InterruptedException::class)
  fun testLoginForm() {
    val navController = TestNavHostController(ApplicationProvider.getApplicationContext())
    val loginScenario = launchFragmentInContainer<LoginFragment>()
    loginScenario.onFragment { fragment ->
        navController.setGraph(R.navigation.nav_login)
        Navigation.setViewNavController(fragment.requireView(), navController)
    }
    onView(allOf(withId(R.id.etForm), isDescendantOfA(withId(R.id.email)))).perform(typeText("user@email.com"))
    onView(allOf(withId(R.id.etForm), isDescendantOfA(withId(R.id.password)))).perform(typeText("123456"))
    onView(withId(R.id.login)).perform(click())
  }
}

I am getting following error

androidx.test.espresso.NoMatchingViewException: No views in hierarchy found matching: (with id is <com.example.cicddemo:id/etForm> and is descendant of a: with id is <2131296433>)

Note: I have implemented it by custom ViewAction which is working fine. But I am not able to get typeText functionality.

ViewonView(withId(R.id.email)).perform(setTextEditText(newText = "user@email.com"))
onView(withId(R.id.password)).perform(setTextEditText(newText = "123456"))

Custom ViewAction:

fun setTextEditText(
newText: String ?
): ViewAction {
return object: ViewAction {

    override fun getConstraints(): Matcher < View > {
        return CoreMatchers.allOf(
            ViewMatchers.isDisplayed(),
            ViewMatchers.isAssignableFrom(FormView::class.java)
        )
    }

    override fun getDescription(): String {
        return "Update the text from the custom EditText"
    }

    override fun perform(uiController: UiController ? , view : View) {
        (view as FormView).setText(newText)
    }
}
}

Is it possible to access the actualy edittext inside the Custom view class and pass it for test?

2 Answers

I have solved my problem by retrieving views by tags without using any custom ViewActions. The issue was that in my custom view I was using

etForm.id = View.generateViewId()

As id was changing at runtime so I am setting tags and access by

withTagValue

Here is updated code

@Test
@Throws(InterruptedException::class)
fun testInvalidEmailPassword() {
    val emailViewInteraction = onView(allOf(withTagValue(`is`("email" as Any?)), isDescendantOfA(withId(R.id.email))))
    val passwordViewInteraction = onView(allOf(withTagValue(`is`("password" as Any?)), isDescendantOfA(withId(R.id.password))))
    emailViewInteraction.perform(typeText("user@email.com"))
    passwordViewInteraction.perform(typeText("123456"))
    onView(withId(R.id.login)).perform(click())
}

If this is AWS FormView, just match the LinearLayout, which it extends

...else you might eventually need to write a custom view-matcher.

Related