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