1244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov/*
2244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov * Copyright (C) 2015 The Android Open Source Project
3244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov *
4244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov * Licensed under the Apache License, Version 2.0 (the "License");
5244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov * you may not use this file except in compliance with the License.
6244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov * You may obtain a copy of the License at
7244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov *
8244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov *      http://www.apache.org/licenses/LICENSE-2.0
9244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov *
10244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov * Unless required by applicable law or agreed to in writing, software
11244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov * distributed under the License is distributed on an "AS IS" BASIS,
12244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov * See the License for the specific language governing permissions and
14244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov * limitations under the License.
15244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov */
16244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov
17244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikovpackage android.support.v7.testutils;
18244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov
191d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikovimport android.database.sqlite.SQLiteCursor;
201d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikovimport android.graphics.Bitmap;
21244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikovimport android.graphics.drawable.Drawable;
22244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikovimport android.support.annotation.ColorInt;
23244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikovimport android.support.test.espresso.matcher.BoundedMatcher;
24ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikovimport android.support.v4.view.TintableBackgroundView;
251d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikovimport android.text.TextUtils;
26244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikovimport android.view.View;
271d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikovimport android.view.ViewGroup;
282d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikovimport android.widget.CheckedTextView;
29244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikovimport android.widget.ImageView;
3027644c071b7fc0e1e4f91194f2a08b4aa2cf1465Aurimas Liutikas
31244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikovimport org.hamcrest.Description;
32244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikovimport org.hamcrest.Matcher;
33ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikovimport org.hamcrest.TypeSafeMatcher;
34244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov
3521f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikovimport java.util.List;
3621f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov
37244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikovpublic class TestUtilsMatchers {
38244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov    /**
39244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov     * Returns a matcher that matches <code>ImageView</code>s which have drawable flat-filled
40244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov     * with the specific color.
41244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov     */
42244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov    public static Matcher drawable(@ColorInt final int color) {
43244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov        return new BoundedMatcher<View, ImageView>(ImageView.class) {
44244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov            private String failedComparisonDescription;
45244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov
46244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov            @Override
47244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov            public void describeTo(final Description description) {
48244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                description.appendText("with drawable of color: ");
49244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov
50244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                description.appendText(failedComparisonDescription);
51244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov            }
52244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov
53244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov            @Override
54244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov            public boolean matchesSafely(final ImageView view) {
55244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                Drawable drawable = view.getDrawable();
56244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                if (drawable == null) {
57244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                    return false;
58244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                }
59244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov
60244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                // One option is to check if we have a ColorDrawable and then call getColor
61244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                // but that API is v11+. Instead, we call our helper method that checks whether
62244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                // all pixels in a Drawable are of the same specified color.
63244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                try {
64244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                    TestUtils.assertAllPixelsOfColor("", drawable, view.getWidth(),
651b81f288853d60e25e870fd522c927fd72f2efb5Kirill Grouchnikov                            view.getHeight(), true, color, 0, true);
66244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                    // If we are here, the color comparison has passed.
67244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                    failedComparisonDescription = null;
68244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                    return true;
69244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                } catch (Throwable t) {
70244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                    // If we are here, the color comparison has failed.
71244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                    failedComparisonDescription = t.getMessage();
72244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                    return false;
73244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov                }
74244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov            }
75244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov        };
76244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov    }
772d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov
782d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov    /**
791d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov     * Returns a matcher that matches <code>View</code>s which have background flat-filled
801d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov     * with the specific color.
811d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov     */
821d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov    public static Matcher isBackground(@ColorInt final int color) {
831cd642752286e1fba44d8ec87e9793f116a22240Chris Banes        return isBackground(color, false);
841cd642752286e1fba44d8ec87e9793f116a22240Chris Banes    }
851cd642752286e1fba44d8ec87e9793f116a22240Chris Banes
861cd642752286e1fba44d8ec87e9793f116a22240Chris Banes    /**
871cd642752286e1fba44d8ec87e9793f116a22240Chris Banes     * Returns a matcher that matches <code>View</code>s which have background flat-filled
881cd642752286e1fba44d8ec87e9793f116a22240Chris Banes     * with the specific color.
891cd642752286e1fba44d8ec87e9793f116a22240Chris Banes     */
901cd642752286e1fba44d8ec87e9793f116a22240Chris Banes    public static Matcher isBackground(@ColorInt final int color, final boolean onlyTestCenter) {
911d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov        return new BoundedMatcher<View, View>(View.class) {
921d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            private String failedComparisonDescription;
931d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov
941d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            @Override
951d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            public void describeTo(final Description description) {
961d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                description.appendText("with background of color: ");
971d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov
981d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                description.appendText(failedComparisonDescription);
991d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            }
1001d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov
1011d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            @Override
1021d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            public boolean matchesSafely(final View view) {
1031d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                Drawable drawable = view.getBackground();
1041d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                if (drawable == null) {
1051d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                    return false;
1061d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                }
1071d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                try {
1081cd642752286e1fba44d8ec87e9793f116a22240Chris Banes                    if (onlyTestCenter) {
1091cd642752286e1fba44d8ec87e9793f116a22240Chris Banes                        TestUtils.assertCenterPixelOfColor("", drawable, view.getWidth(),
1101cd642752286e1fba44d8ec87e9793f116a22240Chris Banes                                view.getHeight(), false, color, 0, true);
1111cd642752286e1fba44d8ec87e9793f116a22240Chris Banes                    } else {
1121cd642752286e1fba44d8ec87e9793f116a22240Chris Banes                        TestUtils.assertAllPixelsOfColor("", drawable, view.getWidth(),
1131cd642752286e1fba44d8ec87e9793f116a22240Chris Banes                                view.getHeight(), false, color, 0, true);
1141cd642752286e1fba44d8ec87e9793f116a22240Chris Banes                    }
1151d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                    // If we are here, the color comparison has passed.
1161d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                    failedComparisonDescription = null;
1171d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                    return true;
1181d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                } catch (Throwable t) {
1191d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                    // If we are here, the color comparison has failed.
1201d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                    failedComparisonDescription = t.getMessage();
1211d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                    return false;
1221d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                }
1231d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            }
1241d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov        };
1251d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov    }
1261d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov
1271d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov    /**
1281d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov     * Returns a matcher that matches <code>View</code>s whose combined background starting
1291d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov     * from the view and up its ancestor chain matches the specified color.
1301d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov     */
1313ab41277a085b829e15eca69442cfe45cae58a8cKirill Grouchnikov    public static Matcher isCombinedBackground(@ColorInt final int color,
1323ab41277a085b829e15eca69442cfe45cae58a8cKirill Grouchnikov            final boolean onlyTestCenterPixel) {
1331d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov        return new BoundedMatcher<View, View>(View.class) {
1341d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            private String failedComparisonDescription;
1351d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov
1361d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            @Override
1371d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            public void describeTo(final Description description) {
1381d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                description.appendText("with ascendant background of color: ");
1391d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov
1401d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                description.appendText(failedComparisonDescription);
1411d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            }
1421d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov
1431d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            @Override
1441d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            public boolean matchesSafely(View view) {
1451d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                // Create a bitmap with combined backgrounds of the view and its ancestors.
1461d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                Bitmap combinedBackgroundBitmap = TestUtils.getCombinedBackgroundBitmap(view);
1471d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                try {
1483ab41277a085b829e15eca69442cfe45cae58a8cKirill Grouchnikov                    if (onlyTestCenterPixel) {
1493ab41277a085b829e15eca69442cfe45cae58a8cKirill Grouchnikov                        TestUtils.assertCenterPixelOfColor("", combinedBackgroundBitmap,
1503ab41277a085b829e15eca69442cfe45cae58a8cKirill Grouchnikov                                color, 0, true);
1513ab41277a085b829e15eca69442cfe45cae58a8cKirill Grouchnikov                    } else {
1523ab41277a085b829e15eca69442cfe45cae58a8cKirill Grouchnikov                        TestUtils.assertAllPixelsOfColor("", combinedBackgroundBitmap,
1533ab41277a085b829e15eca69442cfe45cae58a8cKirill Grouchnikov                                combinedBackgroundBitmap.getWidth(),
1543ab41277a085b829e15eca69442cfe45cae58a8cKirill Grouchnikov                                combinedBackgroundBitmap.getHeight(), color, 0, true);
1553ab41277a085b829e15eca69442cfe45cae58a8cKirill Grouchnikov                    }
1561d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                    // If we are here, the color comparison has passed.
1571d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                    failedComparisonDescription = null;
1581d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                    return true;
1591d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                } catch (Throwable t) {
1601d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                    failedComparisonDescription = t.getMessage();
1611d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                    return false;
1621d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                } finally {
1631d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                    combinedBackgroundBitmap.recycle();
1641d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                }
1651d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            }
1661d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov        };
1671d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov    }
1681d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov
1691d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov    /**
1702d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov     * Returns a matcher that matches <code>CheckedTextView</code>s which are in checked state.
1712d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov     */
1722d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov    public static Matcher isCheckedTextView() {
1732d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov        return new BoundedMatcher<View, CheckedTextView>(CheckedTextView.class) {
1742d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov            private String failedDescription;
1752d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov
1762d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov            @Override
1772d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov            public void describeTo(final Description description) {
1782d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov                description.appendText("checked text view: ");
1792d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov
1802d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov                description.appendText(failedDescription);
1812d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov            }
1822d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov
1832d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov            @Override
1842d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov            public boolean matchesSafely(final CheckedTextView view) {
1852d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov                if (view.isChecked()) {
1862d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov                    return true;
1872d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov                }
1882d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov
1892d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov                failedDescription = "not checked";
1902d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov                return false;
1912d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov            }
1922d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov        };
1932d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov    }
1942d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov
1952d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov    /**
1962d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov     * Returns a matcher that matches <code>CheckedTextView</code>s which are in checked state.
1972d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov     */
1982d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov    public static Matcher isNonCheckedTextView() {
1992d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov        return new BoundedMatcher<View, CheckedTextView>(CheckedTextView.class) {
2002d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov            private String failedDescription;
2012d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov
2022d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov            @Override
2032d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov            public void describeTo(final Description description) {
2042d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov                description.appendText("non checked text view: ");
2052d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov
2062d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov                description.appendText(failedDescription);
2072d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov            }
2082d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov
2092d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov            @Override
2102d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov            public boolean matchesSafely(final CheckedTextView view) {
2112d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov                if (!view.isChecked()) {
2122d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov                    return true;
2132d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov                }
2142d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov
2152d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov                failedDescription = "checked";
2162d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov                return false;
2172d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov            }
2182d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov        };
2192d18d3a4b92369971ed446cf54d98fb0fc55646aKirill Grouchnikov    }
2201d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov
2211d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov    /**
2221d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov     * Returns a matcher that matches data entry in <code>SQLiteCursor</code> that has
2231d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov     * the specified text in the specified column.
2241d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov     */
2251d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov    public static Matcher<Object> withCursorItemContent(final String columnName,
2261d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov            final String expectedText) {
2271d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov        return new BoundedMatcher<Object, SQLiteCursor>(SQLiteCursor.class) {
2281d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov            @Override
2291d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov            public void describeTo(Description description) {
2301d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov                description.appendText("doesn't match " + expectedText);
2311d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov            }
2321d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov
2331d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov            @Override
2341d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov            protected boolean matchesSafely(SQLiteCursor cursor) {
2351d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov                return TextUtils.equals(expectedText,
2361d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov                        cursor.getString(cursor.getColumnIndex(columnName)));
2371d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov            }
2381d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov        };
2391d8515a3b783e9b091bea2891606b466515b4fddKirill Grouchnikov    }
240ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikov
241ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikov    /**
242ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikov     * Returns a matcher that matches Views which implement TintableBackgroundView.
243ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikov     */
244ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikov    public static Matcher<View> isTintableBackgroundView() {
245ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikov        return new TypeSafeMatcher<View>() {
246ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikov            @Override
247ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikov            public void describeTo(Description description) {
248ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikov                description.appendText("is TintableBackgroundView");
249ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikov            }
250ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikov
251ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikov            @Override
252ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikov            public boolean matchesSafely(View view) {
253ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikov                return TintableBackgroundView.class.isAssignableFrom(view.getClass());
254ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikov            }
255ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikov        };
256ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikov    }
257ee9519c17254b5e992164ff278173c4b2c7c5fceKirill Grouchnikov
25821f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov    /**
25921f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov     * Returns a matcher that matches lists of float values that fall into the specified range.
26021f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov     */
26121f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov    public static Matcher<List<Float>> inRange(final float from, final float to) {
26221f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov        return new TypeSafeMatcher<List<Float>>() {
26321f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            private String mFailedDescription;
26421f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov
26521f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            @Override
26621f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            public void describeTo(Description description) {
26721f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                description.appendText(mFailedDescription);
26821f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            }
26921f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov
27021f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            @Override
27121f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            protected boolean matchesSafely(List<Float> item) {
27221f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                int itemCount = item.size();
27321f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov
27421f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                for (int i = 0; i < itemCount; i++) {
27521f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                    float curr = item.get(i);
27621f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov
27721f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                    if ((curr < from) || (curr > to)) {
27821f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                        mFailedDescription = "Value #" + i + ":" + curr + " should be between " +
27921f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                                from + " and " + to;
28021f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                        return false;
28121f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                    }
28221f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                }
28321f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov
28421f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                return true;
28521f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            }
28621f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov        };
28721f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov    }
28821f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov
28921f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov    /**
29021f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov     * Returns a matcher that matches lists of float values that are in ascending order.
29121f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov     */
29221f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov    public static Matcher<List<Float>> inAscendingOrder() {
29321f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov        return new TypeSafeMatcher<List<Float>>() {
29421f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            private String mFailedDescription;
29521f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov
29621f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            @Override
29721f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            public void describeTo(Description description) {
29821f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                description.appendText(mFailedDescription);
29921f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            }
30021f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov
30121f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            @Override
30221f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            protected boolean matchesSafely(List<Float> item) {
30321f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                int itemCount = item.size();
30421f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov
30521f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                if (itemCount >= 2) {
30621f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                    for (int i = 0; i < itemCount - 1; i++) {
30721f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                        float curr = item.get(i);
30821f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                        float next = item.get(i + 1);
30921f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov
31021f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                        if (curr > next) {
31121f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                            mFailedDescription = "Values should increase between #" + i +
31221f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                                    ":" + curr + " and #" + (i + 1) + ":" + next;
31321f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                            return false;
31421f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                        }
31521f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                    }
31621f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                }
31721f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov
31821f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                return true;
31921f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            }
32021f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov        };
32121f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov    }
32221f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov
32321f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov    /**
32421f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov     * Returns a matcher that matches lists of float values that are in descending order.
32521f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov     */
32621f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov    public static Matcher<List<Float>> inDescendingOrder() {
32721f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov        return new TypeSafeMatcher<List<Float>>() {
32821f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            private String mFailedDescription;
32921f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov
33021f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            @Override
33121f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            public void describeTo(Description description) {
33221f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                description.appendText(mFailedDescription);
33321f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            }
33421f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov
33521f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            @Override
33621f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            protected boolean matchesSafely(List<Float> item) {
33721f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                int itemCount = item.size();
33821f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov
33921f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                if (itemCount >= 2) {
34021f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                    for (int i = 0; i < itemCount - 1; i++) {
34121f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                        float curr = item.get(i);
34221f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                        float next = item.get(i + 1);
34321f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov
34421f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                        if (curr < next) {
34521f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                            mFailedDescription = "Values should decrease between #" + i +
34621f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                                    ":" + curr + " and #" + (i + 1) + ":" + next;
34721f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                            return false;
34821f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                        }
34921f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                    }
35021f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                }
35121f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov
35221f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov                return true;
35321f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov            }
35421f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov        };
35521f78eb90b3217aa5cf69c3ffd359506468b55f4Kirill Grouchnikov    }
3561d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov
3571d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov
3581d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov    /**
3591d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov     * Returns a matcher that matches {@link View}s based on the given child type.
3601d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov     *
3611d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov     * @param childMatcher the type of the child to match on
3621d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov     */
3631d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov    public static Matcher<ViewGroup> hasChild(final Matcher<View> childMatcher) {
3641d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov        return new TypeSafeMatcher<ViewGroup>() {
3651d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            @Override
3661d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            public void describeTo(Description description) {
3671d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                description.appendText("has child: ");
3681d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                childMatcher.describeTo(description);
3691d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            }
3701d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov
3711d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            @Override
3721d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            public boolean matchesSafely(ViewGroup view) {
3731d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                final int childCount = view.getChildCount();
3741d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                for (int i = 0; i < childCount; i++) {
3751d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                    if (childMatcher.matches(view.getChildAt(i))) {
3761d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                        return true;
3771d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                    }
3781d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                }
3791d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov                return false;
3801d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov            }
3811d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov        };
3821d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov    }
3831d6e3840486930e276d142861afb6c7e72d5ce72Kirill Grouchnikov
384244abf1fee3fe4fab72a1d8925407e29219940beKirill Grouchnikov}
385