I have my xml layout:
<EditText
android:id="@+id/passwordEditText"
android:layout_width="0dp"
android:layout_height="45dp"
android:layout_marginBottom="20dp"
android:drawableStart="@drawable/ic_sign_in_password"
android:drawablePadding="15dp"
android:hint="@string/password"
android:textSize="15sp"/>
I want to write Espresso test check that EditText has
android:drawableStart="@drawable/ic_sign_in_password".
How I can do this?
Create a helper method sameBitmap
comparing 2 drawables.
private static boolean sameBitmap(Drawable actualDrawable, Drawable expectedDrawable) {
if (actualDrawable == null || expectedDrawable == null) {
return false;
}
if (actualDrawable instanceof StateListDrawable && expectedDrawable instanceof StateListDrawable) {
actualDrawable = actualDrawable.getCurrent();
expectedDrawable = expectedDrawable.getCurrent();
}
if (actualDrawable instanceof BitmapDrawable) {
Bitmap bitmap = ((BitmapDrawable) actualDrawable).getBitmap();
Bitmap otherBitmap = ((BitmapDrawable) expectedDrawable).getBitmap();
return bitmap.sameAs(otherBitmap);
}
if (actualDrawable instanceof VectorDrawable ||
actualDrawable instanceof VectorDrawableCompat ||
actualDrawable instanceof GradientDrawable) {
Rect drawableRect = actualDrawable.getBounds();
Bitmap bitmap = Bitmap.createBitmap(drawableRect.width(), drawableRect.height(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
actualDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
actualDrawable.draw(canvas);
Bitmap otherBitmap = Bitmap.createBitmap(drawableRect.width(), drawableRect.height(), Bitmap.Config.ARGB_8888);
Canvas otherCanvas = new Canvas(otherBitmap);
expectedDrawable.setBounds(0, 0, otherCanvas.getWidth(), otherCanvas.getHeight());
expectedDrawable.draw(otherCanvas);
return bitmap.sameAs(otherBitmap);
}
return false;
}
Then, create a matcher that checks relative drawables. Here, it verifies only drawable start but you can extend it on our own if you'd like to verify drawable end or top or bottom:
private static Matcher<View> withRelativeDrawables(int expectedDrawableStart) {
return new TypeSafeMatcher<View>() {
@Override
protected boolean matchesSafely(View item) {
if (item instanceof TextView) {
TextView textView = (TextView) item;
//get an array of 4 relative drawables. The first one is drawable start
Drawable[] relativeDrawables = textView.getCompoundDrawablesRelative();
Drawable expectedDrawableStart = ContextCompat.getDrawable(context, expectedDrawableStart);
return sameBitmap(relativeDrawables[0], expectedDrawableStart);
}
return false;
}
@Override
public void describeTo(Description description) {
}
};
}
And then use it as below:
onView(withId(R.id.passwordEditText)).check(matches(withRelativeDrawables(R.drawable.ic_sign_in_password)));
Based on this article I made a small change to be able to check any compoundDrawables
inside a TextView
fun withDrawable(
@DrawableRes id: Int,
@ColorRes tint: Int? = null,
tintMode: PorterDuff.Mode = PorterDuff.Mode.SRC_IN,
drawablePosition: TextDrawablePosition = TextDrawablePosition.Left
) = object :
TypeSafeMatcher<View>() {
override fun describeTo(description: Description) {
description.appendText("View 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()
return when (view) {
is TextView -> view.compoundDrawables[drawablePosition.ordinal].toBitmap().sameAs(expectedBitmap)
is ImageView -> view.drawable.toBitmap().sameAs(expectedBitmap)
else -> false
}
}
}
enum class TextDrawablePosition {
Left, Top, Right, Bottom
}
private fun Int.toColor(context: Context) = ContextCompat.getColor(context, this)
private fun Drawable.tinted(@ColorInt tintColor: Int? = null, tintMode: PorterDuff.Mode = SRC_IN) =
apply {
setTintList(tintColor?.toColorStateList())
setTintMode(tintMode)
}
private fun Int.toColorStateList() = ColorStateList.valueOf(this)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With