1 /* 2 * Copyright (C) 2018 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 com.android.setupwizardlib.gesture; 18 19 import static org.mockito.Matchers.eq; 20 import static org.mockito.Mockito.inOrder; 21 import static org.robolectric.RuntimeEnvironment.application; 22 23 import android.view.MotionEvent; 24 import android.view.View; 25 import android.view.ViewConfiguration; 26 import org.junit.Before; 27 import org.junit.Test; 28 import org.junit.runner.RunWith; 29 import org.mockito.InOrder; 30 import org.mockito.Mock; 31 import org.mockito.MockitoAnnotations; 32 import org.robolectric.RobolectricTestRunner; 33 import org.robolectric.annotation.Config; 34 35 @Config(sdk = {Config.OLDEST_SDK, Config.NEWEST_SDK}) 36 @RunWith(RobolectricTestRunner.class) 37 public class ConsecutiveTapsGestureDetectorTest { 38 39 @Mock private ConsecutiveTapsGestureDetector.OnConsecutiveTapsListener listener; 40 41 private ConsecutiveTapsGestureDetector detector; 42 private int slop; 43 private int tapTimeout; 44 45 @Before setUp()46 public void setUp() { 47 MockitoAnnotations.initMocks(this); 48 49 View view = new View(application); 50 view.measure(500, 500); 51 view.layout(0, 0, 500, 500); 52 detector = new ConsecutiveTapsGestureDetector(listener, view); 53 54 slop = ViewConfiguration.get(application).getScaledDoubleTapSlop(); 55 tapTimeout = ViewConfiguration.getDoubleTapTimeout(); 56 } 57 58 @Test onTouchEvent_shouldTriggerCallbackOnFourTaps()59 public void onTouchEvent_shouldTriggerCallbackOnFourTaps() { 60 InOrder inOrder = inOrder(listener); 61 62 tap(0, 25f, 25f); 63 inOrder.verify(listener).onConsecutiveTaps(eq(1)); 64 65 tap(100, 25f, 25f); 66 inOrder.verify(listener).onConsecutiveTaps(eq(2)); 67 68 tap(200, 25f, 25f); 69 inOrder.verify(listener).onConsecutiveTaps(eq(3)); 70 71 tap(300, 25f, 25f); 72 inOrder.verify(listener).onConsecutiveTaps(eq(4)); 73 } 74 75 @Test onTouchEvent_tapOnDifferentLocation_shouldResetCounter()76 public void onTouchEvent_tapOnDifferentLocation_shouldResetCounter() { 77 InOrder inOrder = inOrder(listener); 78 79 tap(0, 25f, 25f); 80 inOrder.verify(listener).onConsecutiveTaps(eq(1)); 81 82 tap(100, 25f, 25f); 83 inOrder.verify(listener).onConsecutiveTaps(eq(2)); 84 85 tap(200, 25f + slop * 2, 25f); 86 inOrder.verify(listener).onConsecutiveTaps(eq(1)); 87 88 tap(300, 25f + slop * 2, 25f); 89 inOrder.verify(listener).onConsecutiveTaps(eq(2)); 90 } 91 92 @Test onTouchEvent_tapAfterTimeout_shouldResetCounter()93 public void onTouchEvent_tapAfterTimeout_shouldResetCounter() { 94 InOrder inOrder = inOrder(listener); 95 96 tap(0, 25f, 25f); 97 inOrder.verify(listener).onConsecutiveTaps(eq(1)); 98 99 tap(100, 25f, 25f); 100 inOrder.verify(listener).onConsecutiveTaps(eq(2)); 101 102 tap(200 + tapTimeout, 25f, 25f); 103 inOrder.verify(listener).onConsecutiveTaps(eq(1)); 104 105 tap(300 + tapTimeout, 25f, 25f); 106 inOrder.verify(listener).onConsecutiveTaps(eq(2)); 107 } 108 tap(int timeMillis, float x, float y)109 private void tap(int timeMillis, float x, float y) { 110 detector.onTouchEvent( 111 MotionEvent.obtain(timeMillis, timeMillis, MotionEvent.ACTION_DOWN, x, y, 0)); 112 detector.onTouchEvent( 113 MotionEvent.obtain(timeMillis, timeMillis + 10, MotionEvent.ACTION_UP, x, y, 0)); 114 } 115 } 116