1c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov/*
2c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov * Copyright (C) 2015 The Android Open Source Project
3c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov *
4c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov * Licensed under the Apache License, Version 2.0 (the "License");
5c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov * you may not use this file except in compliance with the License.
6c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov * You may obtain a copy of the License at
7c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov *
8c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov *      http://www.apache.org/licenses/LICENSE-2.0
9c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov *
10c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov * Unless required by applicable law or agreed to in writing, software
11c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov * distributed under the License is distributed on an "AS IS" BASIS,
12c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov * See the License for the specific language governing permissions and
14c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov * limitations under the License.
15c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov */
16c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov
17c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikovpackage android.support.design.testutils;
18c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov
19ee63e6890156724477092fbfaba18b726a47710eChris Banesimport static org.junit.Assert.assertEquals;
20ee63e6890156724477092fbfaba18b726a47710eChris Banes
218ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikovimport android.graphics.Color;
2288f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikovimport android.graphics.Rect;
238ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikovimport android.graphics.drawable.Drawable;
248ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikovimport android.support.annotation.ColorInt;
25d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banesimport android.support.design.widget.FloatingActionButton;
26c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikovimport android.support.test.espresso.matcher.BoundedMatcher;
27ee63e6890156724477092fbfaba18b726a47710eChris Banesimport android.support.v4.view.GravityCompat;
288ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikovimport android.support.v4.view.ViewCompat;
2946c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banesimport android.support.v4.widget.TextViewCompat;
30ee63e6890156724477092fbfaba18b726a47710eChris Banesimport android.view.Gravity;
31c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikovimport android.view.View;
32ee63e6890156724477092fbfaba18b726a47710eChris Banesimport android.view.ViewGroup;
338ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikovimport android.view.ViewParent;
34910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport android.widget.ImageView;
358ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikovimport android.widget.TextView;
36d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes
37c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikovimport org.hamcrest.Description;
38c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikovimport org.hamcrest.Matcher;
398ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikovimport org.hamcrest.TypeSafeMatcher;
40c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov
41c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikovpublic class TestUtilsMatchers {
42c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov    /**
43c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov     * Returns a matcher that matches Views that are not narrower than specified width in pixels.
44c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov     */
45c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov    public static Matcher<View> isNotNarrowerThan(final int minWidth) {
46c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov        return new BoundedMatcher<View, View>(View.class) {
47c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov            private String failedCheckDescription;
48c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov
49c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov            @Override
50c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov            public void describeTo(final Description description) {
51c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov                description.appendText(failedCheckDescription);
52c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov            }
53c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov
54c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov            @Override
55c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov            public boolean matchesSafely(final View view) {
56c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov                final int viewWidth = view.getWidth();
57c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov                if (viewWidth < minWidth) {
58c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov                    failedCheckDescription =
59c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov                            "width " + viewWidth + " is less than minimum " + minWidth;
60c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov                    return false;
61c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov                }
62c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov                return true;
63c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov            }
64c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov        };
65c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov    }
66c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov
67c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov    /**
68c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov     * Returns a matcher that matches Views that are not wider than specified width in pixels.
69c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov     */
70c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov    public static Matcher<View> isNotWiderThan(final int maxWidth) {
71c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov        return new BoundedMatcher<View, View>(View.class) {
72c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov            private String failedCheckDescription;
73c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov
74c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov            @Override
75c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov            public void describeTo(final Description description) {
76c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov                description.appendText(failedCheckDescription);
77c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov            }
78c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov
79c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov            @Override
80c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov            public boolean matchesSafely(final View view) {
81c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov                final int viewWidth = view.getWidth();
82c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov                if (viewWidth > maxWidth) {
83c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov                    failedCheckDescription =
84c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov                            "width " + viewWidth + " is more than maximum " + maxWidth;
85c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov                    return false;
86c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov                }
87c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov                return true;
88c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov            }
89c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov        };
90c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov    }
918ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov
928ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov    /**
938ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov     * Returns a matcher that matches TextViews with the specified text size.
948ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov     */
958ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov    public static Matcher withTextSize(final float textSize) {
968ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov        return new BoundedMatcher<View, TextView>(TextView.class) {
978ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            private String failedCheckDescription;
988ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov
998ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            @Override
1008ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            public void describeTo(final Description description) {
1018ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                description.appendText(failedCheckDescription);
1028ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            }
1038ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov
1048ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            @Override
1058ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            public boolean matchesSafely(final TextView view) {
1068ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                final float ourTextSize = view.getTextSize();
1078ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                if (Math.abs(textSize - ourTextSize) > 1.0f) {
1088ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    failedCheckDescription =
1098ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                            "text size " + ourTextSize + " is different than expected " + textSize;
1108ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    return false;
1118ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                }
1128ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                return true;
1138ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            }
1148ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov        };
1158ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov    }
1168ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov
1178ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov    /**
1188ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov     * Returns a matcher that matches TextViews with the specified text color.
1198ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov     */
1208ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov    public static Matcher withTextColor(final @ColorInt int textColor) {
1218ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov        return new BoundedMatcher<View, TextView>(TextView.class) {
1228ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            private String failedCheckDescription;
1238ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov
1248ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            @Override
1258ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            public void describeTo(final Description description) {
1268ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                description.appendText(failedCheckDescription);
1278ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            }
1288ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov
1298ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            @Override
1308ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            public boolean matchesSafely(final TextView view) {
131a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov                final @ColorInt int ourTextColor = view.getCurrentTextColor();
1328ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                if (ourTextColor != textColor) {
1338ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    int ourAlpha = Color.alpha(ourTextColor);
1348ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    int ourRed = Color.red(ourTextColor);
1358ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    int ourGreen = Color.green(ourTextColor);
1368ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    int ourBlue = Color.blue(ourTextColor);
1378ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov
1388ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    int expectedAlpha = Color.alpha(textColor);
1398ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    int expectedRed = Color.red(textColor);
1408ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    int expectedGreen = Color.green(textColor);
1418ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    int expectedBlue = Color.blue(textColor);
1428ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov
1438ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    failedCheckDescription =
1448ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                            "expected color to be ["
1458ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                                    + expectedAlpha + "," + expectedRed + ","
1468ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                                    + expectedGreen + "," + expectedBlue
1478ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                                    + "] but found ["
1488ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                                    + ourAlpha + "," + ourRed + ","
1498ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                                    + ourGreen + "," + ourBlue + "]";
1508ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    return false;
1518ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                }
1528ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                return true;
1538ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            }
1548ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov        };
1558ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov    }
1568ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov
1578ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov    /**
1588ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov     * Returns a matcher that matches TextViews whose start drawable is filled with the specified
1598ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov     * fill color.
1608ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov     */
1618ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov    public static Matcher withStartDrawableFilledWith(final @ColorInt int fillColor,
1628ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            final int allowedComponentVariance) {
1638ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov        return new BoundedMatcher<View, TextView>(TextView.class) {
1648ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            private String failedCheckDescription;
1658ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov
1668ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            @Override
1678ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            public void describeTo(final Description description) {
1688ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                description.appendText(failedCheckDescription);
1698ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            }
1708ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov
1718ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            @Override
1728ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            public boolean matchesSafely(final TextView view) {
17388f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov                final Drawable[] compoundDrawables = view.getCompoundDrawables();
17488f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov                final boolean isRtl =
1758ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                        (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_RTL);
17688f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov                final Drawable startDrawable = isRtl ? compoundDrawables[2] : compoundDrawables[0];
1778ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                if (startDrawable == null) {
1788ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    failedCheckDescription = "no start drawable";
1798ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    return false;
1808ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                }
1818ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                try {
18288f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov                    final Rect bounds = startDrawable.getBounds();
1838ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    TestUtils.assertAllPixelsOfColor("",
18488f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov                            startDrawable, bounds.width(), bounds.height(), true,
1858ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                            fillColor, allowedComponentVariance, true);
1868ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                } catch (Throwable t) {
1878ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    failedCheckDescription = t.getMessage();
1888ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    return false;
1898ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                }
1908ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                return true;
1918ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            }
1928ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov        };
1938ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov    }
1948ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov
1958ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov    /**
196910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas     * Returns a matcher that matches <code>ImageView</code>s which have drawable flat-filled
197910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas     * with the specific color.
198910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas     */
199910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas    public static Matcher drawable(@ColorInt final int color, final int allowedComponentVariance) {
200910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        return new BoundedMatcher<View, ImageView>(ImageView.class) {
201910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas            private String mFailedComparisonDescription;
202910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas
203910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas            @Override
204910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas            public void describeTo(final Description description) {
205910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                description.appendText("with drawable of color: ");
206910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas
207910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                description.appendText(mFailedComparisonDescription);
208910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas            }
209910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas
210910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas            @Override
211910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas            public boolean matchesSafely(final ImageView view) {
212910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                Drawable drawable = view.getDrawable();
213910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                if (drawable == null) {
214910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                    return false;
215910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                }
216910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas
217910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                // One option is to check if we have a ColorDrawable and then call getColor
218910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                // but that API is v11+. Instead, we call our helper method that checks whether
219910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                // all pixels in a Drawable are of the same specified color.
220910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                try {
221910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                    TestUtils.assertAllPixelsOfColor("", drawable, view.getWidth(),
222910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                            view.getHeight(), true, color, allowedComponentVariance, true);
223910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                    // If we are here, the color comparison has passed.
224910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                    mFailedComparisonDescription = null;
225910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                    return true;
226910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                } catch (Throwable t) {
227910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                    // If we are here, the color comparison has failed.
228910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                    mFailedComparisonDescription = t.getMessage();
229910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                    return false;
230910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                }
231910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas            }
232910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        };
233910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas    }
234910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas
235910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas    /**
2368ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov     * Returns a matcher that matches Views with the specified background fill color.
2378ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov     */
2388ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov    public static Matcher withBackgroundFill(final @ColorInt int fillColor) {
2398ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov        return new BoundedMatcher<View, View>(View.class) {
2408ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            private String failedCheckDescription;
2418ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov
2428ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            @Override
2438ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            public void describeTo(final Description description) {
2448ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                description.appendText(failedCheckDescription);
2458ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            }
2468ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov
2478ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            @Override
2488ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            public boolean matchesSafely(final View view) {
2498ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                Drawable background = view.getBackground();
2508ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                try {
2518ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    TestUtils.assertAllPixelsOfColor("",
2528ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                            background, view.getWidth(), view.getHeight(), true,
2538ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                            fillColor, 0, true);
2548ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                } catch (Throwable t) {
2558ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    failedCheckDescription = t.getMessage();
2568ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    return false;
257d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                }
258d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                return true;
259d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes            }
260d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes        };
261d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes    }
262d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes
263d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes    /**
264d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes     * Returns a matcher that matches FloatingActionButtons with the specified background
265d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes     * fill color.
266d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes     */
267d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes    public static Matcher withFabBackgroundFill(final @ColorInt int fillColor) {
268d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes        return new BoundedMatcher<View, View>(View.class) {
269d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes            private String failedCheckDescription;
270d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes
271d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes            @Override
272d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes            public void describeTo(final Description description) {
273d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                description.appendText(failedCheckDescription);
274d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes            }
275d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes
276d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes            @Override
277d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes            public boolean matchesSafely(final View view) {
278d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                if (!(view instanceof FloatingActionButton)) {
279d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                    return false;
280d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                }
281d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes
282d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                final FloatingActionButton fab = (FloatingActionButton) view;
283d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes
284d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                // Since the FAB background is round, and may contain the shadow, we'll look at
285d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                // just the center half rect of the content area
286d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                final Rect area = new Rect();
287d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                fab.getContentRect(area);
288d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes
289d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                final int rectHeightQuarter = area.height() / 4;
290d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                final int rectWidthQuarter = area.width() / 4;
291d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                area.left += rectWidthQuarter;
292d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                area.top += rectHeightQuarter;
293d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                area.right -= rectWidthQuarter;
294d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                area.bottom -= rectHeightQuarter;
295d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes
296d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                try {
297d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                    TestUtils.assertAllPixelsOfColor("",
298d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                            fab.getBackground(), view.getWidth(), view.getHeight(), false,
299d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                            fillColor, area, 0, true);
300d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                } catch (Throwable t) {
301d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                    failedCheckDescription = t.getMessage();
302d95e0bb0271ae59387dd9d2ca402ad6f39d789d2Chris Banes                    return false;
3038ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                }
3048ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                return true;
3058ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            }
3068ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov        };
3078ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov    }
3088ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov
3098ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov    /**
3108ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov     * Returns a matcher that matches {@link View}s based on the given parent type.
3118ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov     *
3128ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov     * @param parentMatcher the type of the parent to match on
3138ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov     */
3148ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov    public static Matcher<View> isChildOfA(final Matcher<View> parentMatcher) {
3158ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov        return new TypeSafeMatcher<View>() {
3168ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            @Override
3178ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            public void describeTo(Description description) {
3188ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                description.appendText("is child of a: ");
3198ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                parentMatcher.describeTo(description);
3208ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            }
3218ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov
3228ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            @Override
3238ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            public boolean matchesSafely(View view) {
3248ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                final ViewParent viewParent = view.getParent();
3258ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                if (!(viewParent instanceof View)) {
3268ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    return false;
3278ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                }
3288ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                if (parentMatcher.matches(viewParent)) {
3298ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                    return true;
3308ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                }
3318ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov                return false;
3328ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov            }
3338ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov        };
3348ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov    }
3358ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov
336a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes    /**
337a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes     * Returns a matcher that matches FloatingActionButtons with the specified content height
338a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes     */
339a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes    public static Matcher withFabContentHeight(final int size) {
340a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes        return new BoundedMatcher<View, View>(View.class) {
341a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes            private String failedCheckDescription;
342a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes
343a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes            @Override
344a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes            public void describeTo(final Description description) {
345a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes                description.appendText(failedCheckDescription);
346a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes            }
347a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes
348a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes            @Override
349a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes            public boolean matchesSafely(final View view) {
350a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes                if (!(view instanceof FloatingActionButton)) {
351a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes                    return false;
352a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes                }
353a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes
354a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes                final FloatingActionButton fab = (FloatingActionButton) view;
355a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes                final Rect area = new Rect();
356a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes                fab.getContentRect(area);
357a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes
358a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes                return area.height() == size;
359a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes            }
360a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes        };
361a1de3eef9bb5ef90d00a23c65f13e1fc83254455Chris Banes    }
362ee63e6890156724477092fbfaba18b726a47710eChris Banes
363ee63e6890156724477092fbfaba18b726a47710eChris Banes    /**
364ee63e6890156724477092fbfaba18b726a47710eChris Banes     * Returns a matcher that matches FloatingActionButtons with the specified gravity.
365ee63e6890156724477092fbfaba18b726a47710eChris Banes     */
366ee63e6890156724477092fbfaba18b726a47710eChris Banes    public static Matcher withFabContentAreaOnMargins(final int gravity) {
367ee63e6890156724477092fbfaba18b726a47710eChris Banes        return new BoundedMatcher<View, View>(View.class) {
368ee63e6890156724477092fbfaba18b726a47710eChris Banes            private String failedCheckDescription;
369ee63e6890156724477092fbfaba18b726a47710eChris Banes
370ee63e6890156724477092fbfaba18b726a47710eChris Banes            @Override
371ee63e6890156724477092fbfaba18b726a47710eChris Banes            public void describeTo(final Description description) {
372ee63e6890156724477092fbfaba18b726a47710eChris Banes                description.appendText(failedCheckDescription);
373ee63e6890156724477092fbfaba18b726a47710eChris Banes            }
374ee63e6890156724477092fbfaba18b726a47710eChris Banes
375ee63e6890156724477092fbfaba18b726a47710eChris Banes            @Override
376ee63e6890156724477092fbfaba18b726a47710eChris Banes            public boolean matchesSafely(final View view) {
377ee63e6890156724477092fbfaba18b726a47710eChris Banes                if (!(view instanceof FloatingActionButton)) {
378ee63e6890156724477092fbfaba18b726a47710eChris Banes                    return false;
379ee63e6890156724477092fbfaba18b726a47710eChris Banes                }
380ee63e6890156724477092fbfaba18b726a47710eChris Banes
381ee63e6890156724477092fbfaba18b726a47710eChris Banes                final FloatingActionButton fab = (FloatingActionButton) view;
382ee63e6890156724477092fbfaba18b726a47710eChris Banes                final ViewGroup.MarginLayoutParams lp =
383ee63e6890156724477092fbfaba18b726a47710eChris Banes                        (ViewGroup.MarginLayoutParams) fab.getLayoutParams();
384ee63e6890156724477092fbfaba18b726a47710eChris Banes                final ViewGroup parent = (ViewGroup) view.getParent();
385ee63e6890156724477092fbfaba18b726a47710eChris Banes
386ee63e6890156724477092fbfaba18b726a47710eChris Banes                final Rect area = new Rect();
387ee63e6890156724477092fbfaba18b726a47710eChris Banes                fab.getContentRect(area);
388ee63e6890156724477092fbfaba18b726a47710eChris Banes
389ee63e6890156724477092fbfaba18b726a47710eChris Banes                final int absGravity = GravityCompat.getAbsoluteGravity(gravity,
390ee63e6890156724477092fbfaba18b726a47710eChris Banes                        ViewCompat.getLayoutDirection(view));
391ee63e6890156724477092fbfaba18b726a47710eChris Banes
392ee63e6890156724477092fbfaba18b726a47710eChris Banes                try {
393ee63e6890156724477092fbfaba18b726a47710eChris Banes                    switch (absGravity & Gravity.VERTICAL_GRAVITY_MASK) {
394ee63e6890156724477092fbfaba18b726a47710eChris Banes                        case Gravity.TOP:
395ee63e6890156724477092fbfaba18b726a47710eChris Banes                            assertEquals(lp.topMargin, fab.getTop() + area.top);
396ee63e6890156724477092fbfaba18b726a47710eChris Banes                            break;
397ee63e6890156724477092fbfaba18b726a47710eChris Banes                        case Gravity.BOTTOM:
398ee63e6890156724477092fbfaba18b726a47710eChris Banes                            assertEquals(parent.getHeight() - lp.bottomMargin,
399ee63e6890156724477092fbfaba18b726a47710eChris Banes                                    fab.getTop() + area.bottom);
400ee63e6890156724477092fbfaba18b726a47710eChris Banes                            break;
401ee63e6890156724477092fbfaba18b726a47710eChris Banes                    }
402ee63e6890156724477092fbfaba18b726a47710eChris Banes                    switch (absGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
403ee63e6890156724477092fbfaba18b726a47710eChris Banes                        case Gravity.LEFT:
404ee63e6890156724477092fbfaba18b726a47710eChris Banes                            assertEquals(lp.leftMargin, fab.getLeft() + area.left);
405ee63e6890156724477092fbfaba18b726a47710eChris Banes                            break;
406ee63e6890156724477092fbfaba18b726a47710eChris Banes                        case Gravity.RIGHT:
407ee63e6890156724477092fbfaba18b726a47710eChris Banes                            assertEquals(parent.getWidth() - lp.rightMargin,
408ee63e6890156724477092fbfaba18b726a47710eChris Banes                                    fab.getLeft() + area.right);
409ee63e6890156724477092fbfaba18b726a47710eChris Banes                            break;
410ee63e6890156724477092fbfaba18b726a47710eChris Banes                    }
411ee63e6890156724477092fbfaba18b726a47710eChris Banes                    return true;
412ee63e6890156724477092fbfaba18b726a47710eChris Banes                } catch (Throwable t) {
413ee63e6890156724477092fbfaba18b726a47710eChris Banes                    failedCheckDescription = t.getMessage();
414ee63e6890156724477092fbfaba18b726a47710eChris Banes                    return false;
415ee63e6890156724477092fbfaba18b726a47710eChris Banes                }
416ee63e6890156724477092fbfaba18b726a47710eChris Banes            }
417ee63e6890156724477092fbfaba18b726a47710eChris Banes        };
418ee63e6890156724477092fbfaba18b726a47710eChris Banes    }
41946c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes
42046c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes    /**
42146c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes     * Returns a matcher that matches FloatingActionButtons with the specified content height
42246c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes     */
42346c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes    public static Matcher withCompoundDrawable(final int index, final Drawable expected) {
42446c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes        return new BoundedMatcher<View, View>(View.class) {
42546c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes            private String failedCheckDescription;
42646c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes
42746c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes            @Override
42846c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes            public void describeTo(final Description description) {
42946c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes                description.appendText(failedCheckDescription);
43046c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes            }
43146c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes
43246c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes            @Override
43346c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes            public boolean matchesSafely(final View view) {
43446c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes                if (!(view instanceof TextView)) {
43546c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes                    return false;
43646c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes                }
43746c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes
43846c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes                final TextView textView = (TextView) view;
43946c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes                return expected == TextViewCompat.getCompoundDrawablesRelative(textView)[index];
44046c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes            }
44146c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes        };
44246c7710bb85caf75eb26940d82ece7797f1fc8d7Chris Banes    }
443c7f2aad754af4373c32fcab613de0ba164ada2a2Kirill Grouchnikov}
444