Skip to content

RecyclerView

Aleksei Tiurin edited this page Mar 8, 2021 · 7 revisions

Terms

Before we go forward we need to define some terms:

  • RecyclerView - list of some items (a standard Android framework class). Ultron has a class that wraps an interaction with RecyclerView - UltronRecyclerView.
  • RecyclerViewItem - single item of RecyclerView list (there is a class UltronRecyclerViewItem)
  • RecyclerViewItem.child - child element of RecyclerViewItem (just a term, there is no special class to work with child elements). So RecyclerViewItem.child could be considered as a simple android View.

Screenshot 2021-02-14 at 19 43 50

UltronRecyclerView

Create an instance of UltronRecyclerView by calling a method withRecyclerView(..)

withRecyclerView(R.id.recycler_friends).assertSize(CONTACTS.size)

There is a list of methods to interact with RecyclerView and it could be extended.

Best practice - save UltronRecyclerView as page class properties

object FriendsListPage : Page<FriendsListPage>() {
    val recycler = withRecyclerView(R.id.recycler_friends)
    fun someStep(){
        recycler.assertEmpty()
        recycler.hasContentDescription("Description")
    }
}

UltronRecyclerViewItem

UltronRecyclerView provides an access to UltronRecyclerViewItem.

Simple Item

If you don't need to interact with item child just use methods like item, firstItem, lastItem, itemMatched and etc

recycler.item(position = 10, autoScroll = true).click() // find item at position 10 and scroll to this item 
recycler.item(matcher = hasDescendant(withText("Janice"))).isDisplayed()
recycler.firstItem().click() //take first RecyclerView item
recycler.lastItem().isCompletelyDisplayed()

// if it's impossible to specify unique matcher for target item
val matcher = hasDescendant(withText("Friend"))
recycler.itemMatched(matcher, index = 2).click() //return 3rd matched item, because index starts from zero
recycler.firstItemMatched(matcher).isDisplayed()
recycler.lastItemMatched(matcher).isDisplayed()
recycler.getItemsAdapterPositionList(matcher) // return positions of all matched items

You don't need to worry about scroll to item. By default autoscroll in all item accessor method equals true.

Complex item with children

It's often required to interact with item child. The best solution will be to describe children as properties of UltronRecyclerViewItem subclass.

class FriendRecyclerItem : UltronRecyclerViewItem() {
    val avatar by lazy { getChild(withId(R.id.avatar)) }
    val name by lazy { getChild(withId(R.id.tv_name)) }
    val status by lazy { getChild(withId(R.id.tv_status)) }
}

Note: you have to use lazy initialisation here.

Now you're able to get FriendRecyclerItem object using methods getItem, getFirstItem, getLastItem etc

recycler.getItem<FriendRecyclerItem>(position = 10, autoScroll = true).status.hasText("UNAGI")
recycler.getItem<FriendRecyclerItem>(matcher = hasDescendant(withText("Janice"))).status.textContains("Oh. My")
recycler.getFirstItem<FriendRecyclerItem>().avatar.click() //take first RecyclerView item
recycler.getLastItem<FriendRecyclerItem>().isCompletelyDisplayed()

// if it's impossible to specify unique matcher for target item
val matcher = hasDescendant(withText(containsString("Friend")))
recycler.getItemMatched<FriendRecyclerItem>(matcher, index = 2).name.click() //return 3rd matched item, because index starts from zero
recycler.getFirstItemMatched<FriendRecyclerItem>(matcher).name.hasText("Friend1")
recycler.getLastItemMatched<FriendRecyclerItem>(matcher).avatar.isDisplayed()

Best practice - add a method to Page class that returns FriendRecyclerItem

object FriendsListPage : Page<FriendsListPage>() {
    val recycler = withRecyclerView(R.id.recycler_friends)
    fun getListItem(contactName: String): FriendRecyclerItem {
        return recycler.getItem(hasDescendant(allOf(withId(R.id.tv_name), withText(contactName))))
    }
    fun getListItem(positions: Int): FriendRecyclerItem {
        return recycler.getItem(positions)
    }
}

use getListItem inside FriendsListPage steps

object FriendsListPage : Page<FriendsListPage>() {
    ...
    fun assertStatus(name: String, status: String) = apply {
        getListItem(name).status.hasText(status).isDisplayed()
    }
}