Reputation: 11
I am new to Espresso tests and Android. I am trying to test if the correct Icon is shown next to the text. The icon is set with:
public void setLabelTextIcon(@DrawableRes int iconResId) {
txtLabel.setCompoundDrawablesRelativeWithIntrinsicBounds(iconResId, 0,0,0);
}
I found this online https://gist.github.com/frankiesardo/7490059 but it is not working for me. Due to my lack of background-knowledge I'm not able to change the code that it works. At the moment I try
onView(withId(R.id.blue_triple_stripe_txtLabel)).check(matches(withActionIconDrawable(R.drawable.ic_date_grey)));
and the withActionIconDrawable() is
public static Matcher<View> withActionIconDrawable(@DrawableRes final int resourceId) {
return new BoundedMatcher<View, ActionMenuItemView>(ActionMenuItemView.class) {
@Override
public void describeTo(final Description description) {
description.appendText("has image drawable resource " + resourceId);
}
@Override
public boolean matchesSafely(final ActionMenuItemView actionMenuItemView) {
return sameBitmap(actionMenuItemView.getContext(), actionMenuItemView.getItemData().getIcon(), resourceId);
}
};
}
The Error I get is
androidx.test.espresso.base.DefaultFailureHandler$AssertionFailedWithCauseError: 'has image drawable resource 2131230871' doesn't match the selected view.
Expected: has image drawable resource 2131230871
Got: "AppCompatTextView{id=2131296335, res-name=blue_triple_stripe_txtLabel, visibility=VISIBLE, width=342, height=72, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params=androidx.constraintlayout.widget.ConstraintLayout$LayoutParams@4d24b35, tag=null, root-is-layout-requested=false, has-input-connection=false, x=206.0, y=18.0, text=2019-04-12, input-type=0, ime-target=false, has-links=false}"
Thanks!
Upvotes: 1
Views: 1286
Reputation: 21
I was able to achieve this by adapting @Sam's answer into a matcher that I had for ImageView
drawables (in Kotlin):
class DrawableMatcher(
@DrawableRes private val id: Int,
@ColorRes private val tint: Int? = null,
private val tintMode: PorterDuff.Mode = PorterDuff.Mode.SRC_IN
) : TypeSafeMatcher<View>() {
override fun describeTo(description: Description) {
description.appendText("ImageView with drawable same as drawable with id $id")
tint?.let { description.appendText(", tint color id: $tint, mode: $tintMode") }
}
override fun matchesSafely(view: View): Boolean {
val context = view.context
val tintColor = tint?.toColor(context)
val expectedBitmap = context.getDrawable(id)!!.tinted(tintColor, tintMode).toBitmap()
if (view is TextView) {
for (d in view.compoundDrawables) {
if (d != null) {
if (d.toBitmap().sameAs(expectedBitmap)) {
return true
}
}
}
return false
}
return view is ImageView && view.drawable.toBitmap().sameAs(expectedBitmap)
}
private fun Drawable.tinted(
@ColorInt tintColor: Int? = null,
tintMode: PorterDuff.Mode = PorterDuff.Mode.SRC_IN
) : Drawable {
return this.apply {
setTintList(tintColor?.toColorStateList())
setTintMode(tintMode)
}
}
private fun Int.toColor(context: Context) = ContextCompat.getColor(context, this)
private fun Int.toColorStateList() = ColorStateList.valueOf(this)
companion object {
fun withDrawable(
@DrawableRes id: Int,
@ColorRes tint: Int? = null,
tintMode: PorterDuff.Mode = PorterDuff.Mode.SRC_IN
): Matcher<View> {
return DrawableMatcher(id, tint, tintMode)
}
}
}
and to use it:
onView(withId(R.id.blue_triple_stripe_txtLabel)).check(
matches(
withDrawable(
R.drawable.ic_date_grey
)
)
)
Upvotes: 0
Reputation: 466
This works for me in Kotlin
fun withDrawableTextView(@DrawableRes id: Int) = object : TypeSafeMatcher<View>() {
override fun describeTo(description: Description) {
description.appendText("ImageView with drawable same as drawable with id $id")
}
override fun matchesSafely(tv: View?): Boolean {
if (tv is TextView) {
if (tv.requestFocusFromTouch())
for (d in tv.compoundDrawables)
if (d != null) {
val context = tv.context
if (sameBitmap(tv.getContext(), d, id)) {
return true
}
}
}
return false
}
}
Declare sameBitmap
same as here:
private fun sameBitmap(context: Context, drawable: Drawable, resourceId: Int): Boolean {
var drawable: Drawable? = drawable
var otherDrawable: Drawable = context.getResources().getDrawable(resourceId)
if (drawable == null || otherDrawable == null) {
return false
}
if (drawable is StateListDrawable && otherDrawable is StateListDrawable) {
drawable = drawable.current
otherDrawable = otherDrawable.current
}
if (drawable is BitmapDrawable) {
val bitmap: Bitmap = (drawable as BitmapDrawable).getBitmap()
val otherBitmap: Bitmap = (otherDrawable as BitmapDrawable).getBitmap()
return bitmap.sameAs(otherBitmap)
}
return false
}
Use it with the following code:
onView(withId(R.id.edit_txt_password)).check(matches(withDrawableTextView(R.drawable.view_password_xxxdp)))
Upvotes: 0