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 android.support.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.support.v7.widget.RecyclerView;
25import android.view.View;
26
27import org.hamcrest.Description;
28import org.hamcrest.Matcher;
29import org.hamcrest.TypeSafeMatcher;
30
31public class MoreViewAssertions {
32
33    public static ViewAssertion left(final Matcher<Integer> matcher) {
34        return new ViewAssertion() {
35            @Override
36            public void check(View view, NoMatchingViewException noViewException) {
37                assertThat("View left: " + HumanReadables.describe(view), view.getLeft(), matcher);
38            }
39        };
40    }
41
42    public static ViewAssertion approximateTop(final Matcher<Double> matcher) {
43        return new ViewAssertion() {
44            @Override
45            public void check(View view, NoMatchingViewException noViewException) {
46                assertThat("View top: " + HumanReadables.describe(view), ((double) view.getTop()),
47                        matcher);
48            }
49        };
50    }
51
52    public static ViewAssertion top(final Matcher<Integer> matcher) {
53        return new ViewAssertion() {
54            @Override
55            public void check(View view, NoMatchingViewException noViewException) {
56                assertThat("View top: " + HumanReadables.describe(view), view.getTop(), matcher);
57            }
58        };
59    }
60
61    public static ViewAssertion right(final Matcher<Integer> matcher) {
62        return new ViewAssertion() {
63            @Override
64            public void check(View view, NoMatchingViewException noViewException) {
65                assertThat("View right: " + HumanReadables.describe(view), view.getRight(),
66                        matcher);
67            }
68        };
69    }
70
71    public static ViewAssertion bottom(final Matcher<Integer> matcher) {
72        return new ViewAssertion() {
73            @Override
74            public void check(View view, NoMatchingViewException noViewException) {
75                assertThat("View bottom: " + HumanReadables.describe(view), view.getBottom(),
76                        matcher);
77            }
78        };
79    }
80
81    public static ViewAssertion approximateBottom(final Matcher<Double> matcher) {
82        return new ViewAssertion() {
83            @Override
84            public void check(View view, NoMatchingViewException noViewException) {
85                assertThat("View bottom: " + HumanReadables.describe(view), ((double) view
86                        .getBottom()), matcher);
87            }
88        };
89    }
90
91    /**
92     * Returns a new ViewAssertion against a match of the view's left position, relative to the
93     * left
94     * edge of the containing window.
95     *
96     * @param matcher matcher for the left position
97     */
98    public static ViewAssertion screenLeft(final Matcher<Integer> matcher) {
99        return new ViewAssertion() {
100            @Override
101            public void check(View view, NoMatchingViewException noViewException) {
102                int[] screenXy = {0, 0};
103                view.getLocationInWindow(screenXy);
104                assertThat("View screenLeft: " + HumanReadables.describe(view), screenXy[0],
105                        matcher);
106            }
107        };
108    }
109
110    /**
111     * Returns a new ViewAssertion against a match of the view's top position, relative to the top
112     * edge of the containing window.
113     *
114     * @param matcher matcher for the top position
115     */
116    public static ViewAssertion screenTop(final Matcher<Integer> matcher) {
117        return new ViewAssertion() {
118            @Override
119            public void check(View view, NoMatchingViewException noViewException) {
120                int[] screenXy = {0, 0};
121                view.getLocationInWindow(screenXy);
122                assertThat("View screenTop: " + HumanReadables.describe(view), screenXy[1],
123                        matcher);
124            }
125        };
126    }
127
128    /**
129     * Returns a new ViewAssertion against a match of the view's right position, relative to the
130     * left
131     * edge of the containing window.
132     *
133     * @param matcher matcher for the right position
134     */
135    public static ViewAssertion screenRight(final Matcher<Integer> matcher) {
136        return new ViewAssertion() {
137            @Override
138            public void check(View view, NoMatchingViewException noViewException) {
139                int[] screenXy = {0, 0};
140                view.getLocationInWindow(screenXy);
141                assertThat("View screenRight: " + HumanReadables.describe(view),
142                        screenXy[0] + view.getWidth(), matcher);
143            }
144        };
145    }
146
147    /**
148     * Returns a new ViewAssertion against a match of the view's bottom position, relative to the
149     * top
150     * edge of the containing window.
151     *
152     * @param matcher matcher for the bottom position
153     */
154    public static ViewAssertion screenBottom(final Matcher<Integer> matcher) {
155        return new ViewAssertion() {
156            @Override
157            public void check(View view, NoMatchingViewException noViewException) {
158                int[] screenXy = {0, 0};
159                view.getLocationInWindow(screenXy);
160                assertThat("View screenBottom: " + HumanReadables.describe(view),
161                        screenXy[1] + view.getHeight(), matcher);
162            }
163        };
164    }
165
166    public static Matcher<View> withTranslationX(final int xTranslation) {
167        return new TypeSafeMatcher<View>() {
168            @Override
169            public void describeTo(Description description) {
170                description.appendText("with x translation == " + xTranslation);
171            }
172
173            @Override
174            public boolean matchesSafely(View view) {
175                return view.getTranslationX() == xTranslation;
176            }
177        };
178    }
179
180    public static Matcher<RecyclerView> withPositiveVerticalScrollOffset() {
181        return new TypeSafeMatcher<RecyclerView>() {
182            @Override
183            public void describeTo(Description description) {
184                description.appendText("with positive y scroll offset");
185            }
186
187            @Override
188            public boolean matchesSafely(RecyclerView view) {
189                return view.computeVerticalScrollOffset() > 0;
190            }
191        };
192    }
193
194    public static Matcher<RecyclerView> withNoVerticalScrollOffset() {
195        return new TypeSafeMatcher<RecyclerView>() {
196            @Override
197            public void describeTo(Description description) {
198                description.appendText("with no y scroll offset");
199            }
200
201            @Override
202            public boolean matchesSafely(RecyclerView view) {
203                return view.computeVerticalScrollOffset() == 0;
204            }
205        };
206    }
207}
208