1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package androidx.wear.widget.util;
18
19import static android.support.test.espresso.matcher.ViewMatchers.assertThat;
20
21import android.support.test.espresso.NoMatchingViewException;
22import android.support.test.espresso.ViewAssertion;
23import android.support.test.espresso.util.HumanReadables;
24import android.view.View;
25
26import androidx.recyclerview.widget.RecyclerView;
27
28import org.hamcrest.Description;
29import org.hamcrest.Matcher;
30import org.hamcrest.TypeSafeMatcher;
31
32public class MoreViewAssertions {
33
34    public static ViewAssertion left(final Matcher<Integer> matcher) {
35        return new ViewAssertion() {
36            @Override
37            public void check(View view, NoMatchingViewException noViewException) {
38                assertThat("View left: " + HumanReadables.describe(view), view.getLeft(), matcher);
39            }
40        };
41    }
42
43    public static ViewAssertion approximateTop(final Matcher<Double> matcher) {
44        return new ViewAssertion() {
45            @Override
46            public void check(View view, NoMatchingViewException noViewException) {
47                assertThat("View top: " + HumanReadables.describe(view), ((double) view.getTop()),
48                        matcher);
49            }
50        };
51    }
52
53    public static ViewAssertion top(final Matcher<Integer> matcher) {
54        return new ViewAssertion() {
55            @Override
56            public void check(View view, NoMatchingViewException noViewException) {
57                assertThat("View top: " + HumanReadables.describe(view), view.getTop(), matcher);
58            }
59        };
60    }
61
62    public static ViewAssertion right(final Matcher<Integer> matcher) {
63        return new ViewAssertion() {
64            @Override
65            public void check(View view, NoMatchingViewException noViewException) {
66                assertThat("View right: " + HumanReadables.describe(view), view.getRight(),
67                        matcher);
68            }
69        };
70    }
71
72    public static ViewAssertion bottom(final Matcher<Integer> matcher) {
73        return new ViewAssertion() {
74            @Override
75            public void check(View view, NoMatchingViewException noViewException) {
76                assertThat("View bottom: " + HumanReadables.describe(view), view.getBottom(),
77                        matcher);
78            }
79        };
80    }
81
82    public static ViewAssertion approximateBottom(final Matcher<Double> matcher) {
83        return new ViewAssertion() {
84            @Override
85            public void check(View view, NoMatchingViewException noViewException) {
86                assertThat("View bottom: " + HumanReadables.describe(view), ((double) view
87                        .getBottom()), matcher);
88            }
89        };
90    }
91
92    /**
93     * Returns a new ViewAssertion against a match of the view's left position, relative to the
94     * left
95     * edge of the containing window.
96     *
97     * @param matcher matcher for the left position
98     */
99    public static ViewAssertion screenLeft(final Matcher<Integer> matcher) {
100        return new ViewAssertion() {
101            @Override
102            public void check(View view, NoMatchingViewException noViewException) {
103                int[] screenXy = {0, 0};
104                view.getLocationInWindow(screenXy);
105                assertThat("View screenLeft: " + HumanReadables.describe(view), screenXy[0],
106                        matcher);
107            }
108        };
109    }
110
111    /**
112     * Returns a new ViewAssertion against a match of the view's top position, relative to the top
113     * edge of the containing window.
114     *
115     * @param matcher matcher for the top position
116     */
117    public static ViewAssertion screenTop(final Matcher<Integer> matcher) {
118        return new ViewAssertion() {
119            @Override
120            public void check(View view, NoMatchingViewException noViewException) {
121                int[] screenXy = {0, 0};
122                view.getLocationInWindow(screenXy);
123                assertThat("View screenTop: " + HumanReadables.describe(view), screenXy[1],
124                        matcher);
125            }
126        };
127    }
128
129    /**
130     * Returns a new ViewAssertion against a match of the view's right position, relative to the
131     * left
132     * edge of the containing window.
133     *
134     * @param matcher matcher for the right position
135     */
136    public static ViewAssertion screenRight(final Matcher<Integer> matcher) {
137        return new ViewAssertion() {
138            @Override
139            public void check(View view, NoMatchingViewException noViewException) {
140                int[] screenXy = {0, 0};
141                view.getLocationInWindow(screenXy);
142                assertThat("View screenRight: " + HumanReadables.describe(view),
143                        screenXy[0] + view.getWidth(), matcher);
144            }
145        };
146    }
147
148    /**
149     * Returns a new ViewAssertion against a match of the view's bottom position, relative to the
150     * top
151     * edge of the containing window.
152     *
153     * @param matcher matcher for the bottom position
154     */
155    public static ViewAssertion screenBottom(final Matcher<Integer> matcher) {
156        return new ViewAssertion() {
157            @Override
158            public void check(View view, NoMatchingViewException noViewException) {
159                int[] screenXy = {0, 0};
160                view.getLocationInWindow(screenXy);
161                assertThat("View screenBottom: " + HumanReadables.describe(view),
162                        screenXy[1] + view.getHeight(), matcher);
163            }
164        };
165    }
166
167    public static Matcher<View> withTranslationX(final int xTranslation) {
168        return new TypeSafeMatcher<View>() {
169            @Override
170            public void describeTo(Description description) {
171                description.appendText("with x translation == " + xTranslation);
172            }
173
174            @Override
175            public boolean matchesSafely(View view) {
176                return view.getTranslationX() == xTranslation;
177            }
178        };
179    }
180
181    public static Matcher<RecyclerView> withPositiveVerticalScrollOffset() {
182        return new TypeSafeMatcher<RecyclerView>() {
183            @Override
184            public void describeTo(Description description) {
185                description.appendText("with positive y scroll offset");
186            }
187
188            @Override
189            public boolean matchesSafely(RecyclerView view) {
190                return view.computeVerticalScrollOffset() > 0;
191            }
192        };
193    }
194
195    public static Matcher<RecyclerView> withNoVerticalScrollOffset() {
196        return new TypeSafeMatcher<RecyclerView>() {
197            @Override
198            public void describeTo(Description description) {
199                description.appendText("with no y scroll offset");
200            }
201
202            @Override
203            public boolean matchesSafely(RecyclerView view) {
204                return view.computeVerticalScrollOffset() == 0;
205            }
206        };
207    }
208}
209