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