Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Espresso: How check "drawableStart" of EditText?

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?

like image 965
Alexei Avatar asked Oct 16 '25 10:10

Alexei


2 Answers

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)));
like image 125
Anatolii Avatar answered Oct 19 '25 13:10

Anatolii


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)
like image 33
haroldolivieri Avatar answered Oct 19 '25 12:10

haroldolivieri



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!