'How to test(tdd) an element inside child recycler view?
add to cart errorI've used a recycler view inside another recycler view. While using test-driven development, I was trying to test the click functionality of add to cart button code as follows: MenuDishAdapter- child recycler view MenuAdapter- parent recycler view
class MenuAdapter(private val context: Context, val menuList:List<MenuData>, val menuActivity: MenuActivity):RecyclerView.Adapter<MenuAdapter.MenuViewHolder>() {
class MenuViewHolder(private val itemBinding:RvDishGroupBinding):RecyclerView.ViewHolder(itemBinding.root) {
val dishGroupBinding:RvDishGroupBinding = itemBinding
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MenuViewHolder = MenuViewHolder(
RvDishGroupBinding.inflate(LayoutInflater.from(parent.context), parent, false))
@SuppressLint("CutPasteId")
override fun onBindViewHolder(holder: MenuViewHolder, position: Int) {
val getPos= menuList[position]
holder.dishGroupBinding.dishCatgTypeMtv.text=getPos.categoryType
val adapter = MenuDishAdapter(context, menuList[position].categoryDish, menuActivity, )
holder.dishGroupBinding.dishLl.adapter= adapter
/*Logger.i("Menu list size ${menuList.size}")
Logger.i("Menu list $menuList")*/
if(position==menuList.size-1)
{
holder.dishGroupBinding.rvGroupSeparatorVw.visibility= View.GONE
}
}
override fun getItemCount(): Int = menuList.size
}
class MenuDishAdapter(
private val context: Context,
val menuList: List<DishData>,
val menuActivity: MenuActivity
) :
RecyclerView.Adapter<MenuDishAdapter.MenuDishViewHolder>() {
class MenuDishViewHolder(private val dishItem: RvDishItemBinding) :
RecyclerView.ViewHolder(dishItem.root) {
val dishItemBinding = dishItem
}
var isFavourite: Boolean = false
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MenuDishViewHolder =
MenuDishViewHolder(
RvDishItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
override fun onBindViewHolder(holder: MenuDishViewHolder, position: Int) {
val getPos= menuList[position]
Glide.with(context).load(getPos.dishImage).placeholder(R.drawable.img_dessert).into( holder.dishItemBinding.rvDishImgIv)
holder.dishItemBinding.rvDishNameMtv.text= getPos.dishName
if(getPos.dishDescription.isNullOrEmpty())
{
holder.dishItemBinding.rvDishDescriptionMtv.visibility=View.GONE
}
else
{
holder.dishItemBinding.rvDishDescriptionMtv.text= getPos.dishDescription
}
holder.dishItemBinding.rvDishPriceMtv.text= "$"+ getPos.dishPrice
if(!getPos.isVeg)
{
holder.dishItemBinding.rvDishTypeIv.backgroundTintList=
ContextCompat.getColorStateList(menuActivity, R.color.red)
}
holder.dishItemBinding.rvDishCustomizationMtv.text= context.getString(R.string.your_customisations_are)+" Radish, Mushroom, carrots, turnip, radish"
holder.dishItemBinding.rvDishFavMarkIb.setOnClickListener {
if(isFavourite)
{
holder.dishItemBinding.rvDishFavMarkIb.setBackgroundResource(R.drawable.ic_unfav)
Toast.makeText(context, "${getPos.dishName} removed from Favourite. ", Toast.LENGTH_SHORT).show()
notifyDataSetChanged()
isFavourite= false
}
else
{
holder.dishItemBinding.rvDishFavMarkIb.setBackgroundResource(R.drawable.ic_fav)
Toast.makeText(context, "${getPos.dishName} marked Favourite. ", Toast.LENGTH_SHORT).show()
notifyDataSetChanged()
isFavourite=true
}
}
holder.dishItemBinding.rvAddToCartBtn.setOnClickListener {
Utils.printShortToast(context, "${getPos.dishName} added to the cart")
}
holder.dishItemBinding.rvDishCustomizeBtn.setOnClickListener {
Utils.printShortToast(context, "${getPos.dishName} customised")
}
}
override fun getItemCount(): Int = menuList.size
}
XML for MenuDishAdapter
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="133dp"
android:layout_marginStart="6dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="6dp"
android:id="@+id/rv_dish_item_ll">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/detail_parent_cl"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:id="@+id/rv_dish_img_cv"
android:layout_width="109dp"
android:layout_height="104dp"
android:elevation="5dp"
app:cardCornerRadius="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/rv_dish_img_iv"
android:layout_width="109dp"
android:layout_height="104dp"
android:scaleType="fitXY"
tools:src="@drawable/img_fav_2" />
</androidx.cardview.widget.CardView>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/dish_details_ll"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="0dp"
android:orientation="vertical"
android:weightSum="5"
app:layout_constraintBottom_toBottomOf="@id/rv_dish_img_cv"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/rv_dish_img_cv"
app:layout_constraintTop_toTopOf="@id/rv_dish_img_cv">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/dish_name_cl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:layout_weight="1"
android:orientation="horizontal">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/rv_dish_name_mtv"
style="@style/TextAppearance.MdcTypographyStyles.Body22"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:layout_marginEnd="8dp"
android:ellipsize="end"
android:gravity="start"
android:maxLines="1"
android:textColor="@color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/rv_dish_type_iv"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Masala Noodles" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/rv_dish_type_iv"
android:layout_width="21dp"
android:layout_height="18dp"
android:layout_gravity="end"
android:background="@drawable/ic_veg_dish"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/detail_middle_cl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/text_ll"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/rv_dish_fav_mark_ib"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/rv_dish_description__mtv"
style="@style/TextAppearance.MdcTypographyStyles.Body12"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="2"
android:layout_marginEnd="2dp"
android:layout_marginStart="0dp"
android:textAlignment="textStart"
android:textColor="@color/black"
tools:text="@string/description" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/rv_dish_price_mtv"
style="@style/TextAppearance.MdcTypographyStyles.Body22"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:textAlignment="textStart"
tools:text="$10.5" />
</LinearLayout>
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/rv_dish_fav_mark_ib"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:clickable="true"
android:elevation="5dp"
android:focusable="true"
android:paddingStart="10dp"
android:paddingTop="0dp"
android:paddingEnd="0dp"
android:paddingBottom="5dp"
android:background="@drawable/ic_unfav"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/buttons_cl"
android:layout_width="match_parent"
android:layout_height="23dp"
android:layout_marginTop="2dp"
android:paddingBottom="1dp"
android:paddingTop="0dp"
android:layout_weight="1"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/rv_add_to_cart_btn"
style="@style/TextAppearance.MdcTypographyStyles.Button1"
android:layout_width="109dp"
android:layout_height="0dp"
android:layout_marginStart="0dp"
android:layout_marginEnd="2dp"
android:background="@drawable/bg_button"
android:backgroundTint="@color/primaryColor"
android:drawableStart="@drawable/ic_button_cart"
android:drawablePadding="0dp"
android:focusable="true"
android:padding="2dp"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:text="@string/add_to_cart"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/rv_dish_customize_btn"
style="@style/TextAppearance.MdcTypographyStyles.Button1"
android:layout_width="109dp"
android:layout_height="0dp"
android:layout_marginStart="2dp"
android:layout_marginEnd="0dp"
android:background="@drawable/bg_button"
android:backgroundTint="@color/black"
android:focusable="true"
android:padding="2dp"
android:text="@string/customize"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
<com.google.android.material.textview.MaterialTextView
android:id="@+id/rv_dish_customization_mtv"
style="@style/TextAppearance.MdcTypographyStyles.Body12"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="3dp"
android:ellipsize="end"
android:maxLines="1"
android:text="@string/your_customisations_are"
android:textAlignment="textStart"
android:textColor="@color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@id/dish_details_ll"
app:layout_constraintStart_toStartOf="@id/rv_dish_img_cv"
app:layout_constraintTop_toBottomOf="@id/rv_dish_img_cv"
tools:text="Your customisations are - Onion, Tomato, Mushroom, cucumber, radish" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
Now while testing the add to cart button the test case is as follows: **Class name: MenuActivityTest see code commented in testingMenuList() **
@RunWith(AndroidJUnit4::class)
@LargeTest
class MenuActivityTest {
@get:Rule
var rule = ActivityScenarioRule(MenuActivity::class.java)
//test to check the visibility of the menu screen layout on the device
@Test
fun checkScreenDisplay() {
onView(withId(R.id.menu_cl))
.check(matches(isDisplayed()))
}
@Test
fun testingMenuList() {
//testing whether the recycler view is displayed for not
onView(withId(R.id.menu_rv)).check(matches(isDisplayed()))
onView(allOf(withId(R.id.dish_ll), isDisplayed()))
//testing the scroll to position to 3rd position
onView(withId(R.id.menu_rv)).perform(
RecyclerViewActions
.scrollToPosition<RecyclerView.ViewHolder>(3)
)
//testing a particular item of the list
onView(allOf(withId(R.id.dish_catg_type_mtv), withText("Beverages")))
onView(allOf(withId(R.id.rv_dish_name_mtv), withText("Coffee")))
onView(allOf(withId(R.id.rv_dish_price_mtv), withText("0")))
onView(
allOf(
withId(R.id.rv_dish_description__mtv),
withText("Because ground coffee beans, coffee roasts, and brewing methods vary, so do coffee drinks. They come in so many different varieties and flavors, such as black coffee, espresso, latte, cappuccino, or mocha.")
)
)
/*onView(allOf(isDisplayed(), withId(R.id.rv_add_to_cart_btn)))
.perform(RecyclerViewActions.actionOnItemAtPosition<MenuDishAdapter.MenuDishViewHolder>(2, click()));
*/
/*val result = onView(
allOf(
withId(R.id.rv_add_to_cart_btn),
withText("Coffee")
)
).perform(
click()
)
Utils.printErrorLog("Result is: $result")*/
onView(allOf(withId(R.id.rv_add_to_cart_btn), isDescendantOfA(allOf(withId(R.id.buttons_cl))))).check(matches(isFocusable()))
*/
/* onData(allOf(withId(R.id.rv_add_to_cart_btn)))
.inAdapterView(allOf(withId(R.id.rv_dish_item_ll)))
.atPosition(1)
.perform(click())*/
}
}
Each and every time in running the testingMenuList I'm getting the error(screenshot attached). What is the correct method to check the add to cart button click functionality? The flow is as: MenuActivity has a recycler view menu_rv and this menu_rv contains another recycler view name dish_ll. Inside dish_ll, rv_add_to_cart_btn is the button that is being tested using the TDD approach.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
