1 /*
2  * Copyright 2017 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 
17 package androidx.recyclerview.selection;
18 
19 import static org.mockito.Matchers.any;
20 import static org.mockito.Matchers.anyFloat;
21 import static org.mockito.Mockito.never;
22 import static org.mockito.Mockito.verify;
23 
24 import android.support.test.filters.SmallTest;
25 import android.support.test.runner.AndroidJUnit4;
26 import android.view.GestureDetector.OnDoubleTapListener;
27 import android.view.GestureDetector.OnGestureListener;
28 import android.view.MotionEvent;
29 
30 import androidx.recyclerview.selection.testing.TestEvents.Mouse;
31 import androidx.recyclerview.selection.testing.TestEvents.Touch;
32 
33 import org.junit.Before;
34 import org.junit.Test;
35 import org.junit.runner.RunWith;
36 import org.mockito.Mockito;
37 
38 @RunWith(AndroidJUnit4.class)
39 @SmallTest
40 public final class GestureRouterTest {
41 
42     private TestHandler mHandler;
43     private TestHandler mAlt;
44     private GestureRouter<TestHandler> mRouter;
45 
46     @Before
setUp()47     public void setUp() {
48         mAlt = new TestHandler();
49         mHandler = new TestHandler();
50     }
51 
52     @Test
testDelegates()53     public void testDelegates() {
54         mRouter = new GestureRouter<>();
55         mRouter.register(MotionEvent.TOOL_TYPE_MOUSE, mHandler);
56         mRouter.register(MotionEvent.TOOL_TYPE_FINGER, mAlt);
57 
58         mRouter.onDown(Mouse.CLICK);
59         mHandler.assertCalled_onDown(Mouse.CLICK);
60         mAlt.assertNotCalled_onDown();
61 
62         mRouter.onShowPress(Mouse.CLICK);
63         mHandler.assertCalled_onShowPress(Mouse.CLICK);
64         mAlt.assertNotCalled_onShowPress();
65 
66         mRouter.onSingleTapUp(Mouse.CLICK);
67         mHandler.assertCalled_onSingleTapUp(Mouse.CLICK);
68         mAlt.assertNotCalled_onSingleTapUp();
69 
70         mRouter.onScroll(null, Mouse.CLICK, -1, -1);
71         mHandler.assertCalled_onScroll(null, Mouse.CLICK, -1, -1);
72         mAlt.assertNotCalled_onScroll();
73 
74         mRouter.onLongPress(Mouse.CLICK);
75         mHandler.assertCalled_onLongPress(Mouse.CLICK);
76         mAlt.assertNotCalled_onLongPress();
77 
78         mRouter.onFling(null, Mouse.CLICK, -1, -1);
79         mHandler.assertCalled_onFling(null, Mouse.CLICK, -1, -1);
80         mAlt.assertNotCalled_onFling();
81 
82         mRouter.onSingleTapConfirmed(Mouse.CLICK);
83         mHandler.assertCalled_onSingleTapConfirmed(Mouse.CLICK);
84         mAlt.assertNotCalled_onSingleTapConfirmed();
85 
86         mRouter.onDoubleTap(Mouse.CLICK);
87         mHandler.assertCalled_onDoubleTap(Mouse.CLICK);
88         mAlt.assertNotCalled_onDoubleTap();
89 
90         mRouter.onDoubleTapEvent(Mouse.CLICK);
91         mHandler.assertCalled_onDoubleTapEvent(Mouse.CLICK);
92         mAlt.assertNotCalled_onDoubleTapEvent();
93     }
94 
95     @Test
testFallsback()96     public void testFallsback() {
97         mRouter = new GestureRouter<>(mAlt);
98         mRouter.register(MotionEvent.TOOL_TYPE_MOUSE, mHandler);
99 
100         mRouter.onDown(Touch.TAP);
101         mAlt.assertCalled_onDown(Touch.TAP);
102 
103         mRouter.onShowPress(Touch.TAP);
104         mAlt.assertCalled_onShowPress(Touch.TAP);
105 
106         mRouter.onSingleTapUp(Touch.TAP);
107         mAlt.assertCalled_onSingleTapUp(Touch.TAP);
108 
109         mRouter.onScroll(null, Touch.TAP, -1, -1);
110         mAlt.assertCalled_onScroll(null, Touch.TAP, -1, -1);
111 
112         mRouter.onLongPress(Touch.TAP);
113         mAlt.assertCalled_onLongPress(Touch.TAP);
114 
115         mRouter.onFling(null, Touch.TAP, -1, -1);
116         mAlt.assertCalled_onFling(null, Touch.TAP, -1, -1);
117 
118         mRouter.onSingleTapConfirmed(Touch.TAP);
119         mAlt.assertCalled_onSingleTapConfirmed(Touch.TAP);
120 
121         mRouter.onDoubleTap(Touch.TAP);
122         mAlt.assertCalled_onDoubleTap(Touch.TAP);
123 
124         mRouter.onDoubleTapEvent(Touch.TAP);
125         mAlt.assertCalled_onDoubleTapEvent(Touch.TAP);
126     }
127 
128     @Test
testEatsEventsWhenNoFallback()129     public void testEatsEventsWhenNoFallback() {
130         mRouter = new GestureRouter<>();
131         // Register the the delegate on mouse so touch events don't get handled.
132         mRouter.register(MotionEvent.TOOL_TYPE_MOUSE, mHandler);
133 
134         mRouter.onDown(Touch.TAP);
135         mAlt.assertNotCalled_onDown();
136 
137         mRouter.onShowPress(Touch.TAP);
138         mAlt.assertNotCalled_onShowPress();
139 
140         mRouter.onSingleTapUp(Touch.TAP);
141         mAlt.assertNotCalled_onSingleTapUp();
142 
143         mRouter.onScroll(null, Touch.TAP, -1, -1);
144         mAlt.assertNotCalled_onScroll();
145 
146         mRouter.onLongPress(Touch.TAP);
147         mAlt.assertNotCalled_onLongPress();
148 
149         mRouter.onFling(null, Touch.TAP, -1, -1);
150         mAlt.assertNotCalled_onFling();
151 
152         mRouter.onSingleTapConfirmed(Touch.TAP);
153         mAlt.assertNotCalled_onSingleTapConfirmed();
154 
155         mRouter.onDoubleTap(Touch.TAP);
156         mAlt.assertNotCalled_onDoubleTap();
157 
158         mRouter.onDoubleTapEvent(Touch.TAP);
159         mAlt.assertNotCalled_onDoubleTapEvent();
160     }
161 
162     private static final class TestHandler implements OnGestureListener, OnDoubleTapListener {
163 
164         private final Spy mSpy = Mockito.mock(Spy.class);
165 
166         @Override
onDown(MotionEvent e)167         public boolean onDown(MotionEvent e) {
168             return mSpy.onDown(e);
169         }
170 
171         @Override
onShowPress(MotionEvent e)172         public void onShowPress(MotionEvent e) {
173             mSpy.onShowPress(e);
174         }
175 
176         @Override
onSingleTapUp(MotionEvent e)177         public boolean onSingleTapUp(MotionEvent e) {
178             return mSpy.onSingleTapUp(e);
179         }
180 
181         @Override
onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)182         public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
183             return mSpy.onScroll(e1, e2, distanceX, distanceY);
184         }
185 
186         @Override
onLongPress(MotionEvent e)187         public void onLongPress(MotionEvent e) {
188             mSpy.onLongPress(e);
189         }
190 
191         @Override
onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)192         public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
193             return mSpy.onFling(e1, e2, velocityX, velocityY);
194         }
195 
196         @Override
onSingleTapConfirmed(MotionEvent e)197         public boolean onSingleTapConfirmed(MotionEvent e) {
198             return mSpy.onSingleTapConfirmed(e);
199         }
200 
201         @Override
onDoubleTap(MotionEvent e)202         public boolean onDoubleTap(MotionEvent e) {
203             return mSpy.onDoubleTap(e);
204         }
205 
206         @Override
onDoubleTapEvent(MotionEvent e)207         public boolean onDoubleTapEvent(MotionEvent e) {
208             return mSpy.onDoubleTapEvent(e);
209         }
210 
assertCalled_onDown(MotionEvent e)211         void assertCalled_onDown(MotionEvent e) {
212             verify(mSpy).onDown(e);
213         }
214 
assertCalled_onShowPress(MotionEvent e)215         void assertCalled_onShowPress(MotionEvent e) {
216             verify(mSpy).onShowPress(e);
217         }
218 
assertCalled_onSingleTapUp(MotionEvent e)219         void assertCalled_onSingleTapUp(MotionEvent e) {
220             verify(mSpy).onSingleTapUp(e);
221         }
222 
assertCalled_onScroll(MotionEvent e1, MotionEvent e2, float x, float y)223         void assertCalled_onScroll(MotionEvent e1, MotionEvent e2, float x, float y) {
224             verify(mSpy).onScroll(e1, e2, x, y);
225         }
226 
assertCalled_onLongPress(MotionEvent e)227         void assertCalled_onLongPress(MotionEvent e) {
228             verify(mSpy).onLongPress(e);
229         }
230 
assertCalled_onFling(MotionEvent e1, MotionEvent e2, float x, float y)231         void assertCalled_onFling(MotionEvent e1, MotionEvent e2, float x, float y) {
232             Mockito.verify(mSpy).onFling(e1, e2, x, y);
233         }
234 
assertCalled_onSingleTapConfirmed(MotionEvent e)235         void assertCalled_onSingleTapConfirmed(MotionEvent e) {
236             Mockito.verify(mSpy).onSingleTapConfirmed(e);
237         }
238 
assertCalled_onDoubleTap(MotionEvent e)239         void assertCalled_onDoubleTap(MotionEvent e) {
240             Mockito.verify(mSpy).onDoubleTap(e);
241         }
242 
assertCalled_onDoubleTapEvent(MotionEvent e)243         void assertCalled_onDoubleTapEvent(MotionEvent e) {
244             Mockito.verify(mSpy).onDoubleTapEvent(e);
245         }
246 
assertNotCalled_onDown()247         void assertNotCalled_onDown() {
248             verify(mSpy, never()).onDown((MotionEvent) any());
249         }
250 
assertNotCalled_onShowPress()251         void assertNotCalled_onShowPress() {
252             verify(mSpy, never()).onShowPress((MotionEvent) any());
253         }
254 
assertNotCalled_onSingleTapUp()255         void assertNotCalled_onSingleTapUp() {
256             verify(mSpy, never()).onSingleTapUp((MotionEvent) any());
257         }
258 
assertNotCalled_onScroll()259         void assertNotCalled_onScroll() {
260             verify(mSpy, never()).onScroll(
261                     (MotionEvent) any(), (MotionEvent) any(), anyFloat(), anyFloat());
262         }
263 
assertNotCalled_onLongPress()264         void assertNotCalled_onLongPress() {
265             verify(mSpy, never()).onLongPress((MotionEvent) any());
266         }
267 
assertNotCalled_onFling()268         void assertNotCalled_onFling() {
269             Mockito.verify(mSpy, never()).onFling(
270                     (MotionEvent) any(), (MotionEvent) any(), anyFloat(), anyFloat());
271         }
272 
assertNotCalled_onSingleTapConfirmed()273         void assertNotCalled_onSingleTapConfirmed() {
274             Mockito.verify(mSpy, never()).onSingleTapConfirmed((MotionEvent) any());
275         }
276 
assertNotCalled_onDoubleTap()277         void assertNotCalled_onDoubleTap() {
278             Mockito.verify(mSpy, never()).onDoubleTap((MotionEvent) any());
279         }
280 
assertNotCalled_onDoubleTapEvent()281         void assertNotCalled_onDoubleTapEvent() {
282             Mockito.verify(mSpy, never()).onDoubleTapEvent((MotionEvent) any());
283         }
284     }
285 
286     private interface Spy extends OnGestureListener, OnDoubleTapListener {
287     }
288 }
289