[go: nahoru, domu]

blob: cc272a8d683ed421b3cbfe4f0b2e1caac4603314 [file] [log] [blame]
shepshapardd9f05232019-08-08 10:21:47 -07001/*
2 * Copyright 2019 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 */
16package androidx.ui.core.gesture
17
18import android.view.MotionEvent
19import android.view.View
20import android.view.ViewGroup
Shep Shapardbf513c52019-12-16 17:06:51 -080021import androidx.test.filters.LargeTest
shepshapardd9f05232019-08-08 10:21:47 -070022import androidx.test.rule.ActivityTestRule
Shep Shapardbf513c52019-12-16 17:06:51 -080023import androidx.ui.core.Layout
24import androidx.ui.core.PxPosition
shepshapardd9f05232019-08-08 10:21:47 -070025import androidx.ui.core.ipx
26import androidx.ui.core.setContent
27import androidx.ui.framework.test.TestActivity
28import com.nhaarman.mockitokotlin2.any
Shep Shapardbf513c52019-12-16 17:06:51 -080029import com.nhaarman.mockitokotlin2.inOrder
30import com.nhaarman.mockitokotlin2.spy
31import com.nhaarman.mockitokotlin2.times
shepshapardd9f05232019-08-08 10:21:47 -070032import com.nhaarman.mockitokotlin2.verify
33import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
34import org.junit.Assert.assertTrue
35import org.junit.Before
36import org.junit.Rule
37import org.junit.Test
38import org.junit.runner.RunWith
39import org.junit.runners.JUnit4
40import java.util.concurrent.CountDownLatch
41import java.util.concurrent.TimeUnit
Shep Shapardbf513c52019-12-16 17:06:51 -080042
43// TODO(shepshapard): Figure out how to test composite gesture detectors better. There should be
44// more tests, but hopefully they can also be easier to write then what is currently available.
45// Should possibly wait till we have host side testing that does not require the Android runtime.
shepshapardd9f05232019-08-08 10:21:47 -070046
47@LargeTest
48@RunWith(JUnit4::class)
49class LongPressDragGestureDetectorTest {
50 @get:Rule
51 val activityTestRule = ActivityTestRule<TestActivity>(TestActivity::class.java)
52 private lateinit var longPressDragObserver: LongPressDragObserver
53 private lateinit var longPressCountDownLatch: CountDownLatch
54 private lateinit var view: View
55
56 @Before
57 fun setup() {
58 longPressDragObserver = spy(MyLongPressDragObserver {
59 longPressCountDownLatch.countDown()
60 })
61
62 val activity = activityTestRule.activity
63 assertTrue(activity.hasFocusLatch.await(5, TimeUnit.SECONDS))
64
65 val setupLatch = CountDownLatch(2)
66 activityTestRule.runOnUiThreadIR {
67 activity.setContent {
68 LongPressDragGestureDetector(longPressDragObserver) {
69 Layout(
70 measureBlock = { _, _ ->
71 layout(100.ipx, 100.ipx) {
72 setupLatch.countDown()
73 }
74 }, children = {}
75 )
76 }
77 }
78
79 view = activity.findViewById<ViewGroup>(android.R.id.content)
80 setupLatch.countDown()
81 }
82 assertTrue(setupLatch.await(1000, TimeUnit.SECONDS))
83 }
84
shepshapardd9f05232019-08-08 10:21:47 -070085 @Test
86 fun ui_downMoveUpBeforeLongPressTimeout_noCallbacksCalled() {
87
88 val down = MotionEvent(
89 0,
90 MotionEvent.ACTION_DOWN,
91 1,
92 0,
93 arrayOf(PointerProperties(0)),
94 arrayOf(PointerCoords(50f, 50f))
95 )
96 val move = MotionEvent(
97 0,
98 MotionEvent.ACTION_MOVE,
99 1,
100 0,
101 arrayOf(PointerProperties(0)),
102 arrayOf(PointerCoords(51f, 50f))
103 )
104 val up = MotionEvent(
105 0,
106 MotionEvent.ACTION_UP,
107 1,
108 0,
109 arrayOf(PointerProperties(0)),
110 arrayOf(PointerCoords(51f, 50f))
111 )
112 activityTestRule.runOnUiThreadIR {
113 view.dispatchTouchEvent(down)
114 view.dispatchTouchEvent(move)
115 view.dispatchTouchEvent(up)
116 }
117
118 verifyNoMoreInteractions(longPressDragObserver)
119 }
120
Shep Shapardbf513c52019-12-16 17:06:51 -0800121 @Test
122 fun ui_downMoveCancelBeforeLongPressTimeout_noCallbacksCalled() {
123
124 val down = MotionEvent(
125 0,
126 MotionEvent.ACTION_DOWN,
127 1,
128 0,
129 arrayOf(PointerProperties(0)),
130 arrayOf(PointerCoords(50f, 50f))
131 )
132 val move = MotionEvent(
133 0,
134 MotionEvent.ACTION_MOVE,
135 1,
136 0,
137 arrayOf(PointerProperties(0)),
138 arrayOf(PointerCoords(51f, 50f))
139 )
140 val cancel = MotionEvent(
141 0,
142 MotionEvent.ACTION_CANCEL,
143 1,
144 0,
145 arrayOf(PointerProperties(0)),
146 arrayOf(PointerCoords(51f, 50f))
147 )
148 activityTestRule.runOnUiThreadIR {
149 view.dispatchTouchEvent(down)
150 view.dispatchTouchEvent(move)
151 view.dispatchTouchEvent(cancel)
152 }
153
154 verifyNoMoreInteractions(longPressDragObserver)
155 }
shepshapardd9f05232019-08-08 10:21:47 -0700156
157 @Test
Shep Shapardbf513c52019-12-16 17:06:51 -0800158 fun ui_downWaitForLongPress_onlyOnLongPressCalled() {
shepshapardd9f05232019-08-08 10:21:47 -0700159
160 val down = MotionEvent(
161 0,
162 MotionEvent.ACTION_DOWN,
163 1,
164 0,
165 arrayOf(PointerProperties(0)),
166 arrayOf(PointerCoords(50f, 50f))
167 )
168 waitForLongPress {
169 view.dispatchTouchEvent(down)
170 }
171
172 verify(longPressDragObserver).onLongPress(any())
173 verifyNoMoreInteractions(longPressDragObserver)
174 }
175
shepshapardd9f05232019-08-08 10:21:47 -0700176 @Test
Shep Shapardbf513c52019-12-16 17:06:51 -0800177 fun ui_downWaitForLongPressMove_callbacksCorrect() {
shepshapardd9f05232019-08-08 10:21:47 -0700178
shepshapardd9f05232019-08-08 10:21:47 -0700179 val down = MotionEvent(
180 0,
181 MotionEvent.ACTION_DOWN,
182 1,
183 0,
184 arrayOf(PointerProperties(0)),
185 arrayOf(PointerCoords(50f, 50f))
186 )
187 waitForLongPress {
188 view.dispatchTouchEvent(down)
189 }
190 val move = MotionEvent(
191 0,
192 MotionEvent.ACTION_MOVE,
193 1,
194 0,
195 arrayOf(PointerProperties(0)),
196 arrayOf(PointerCoords(51f, 50f))
197 )
198 view.dispatchTouchEvent(move)
shepshapardd9f05232019-08-08 10:21:47 -0700199
Shep Shapardbf513c52019-12-16 17:06:51 -0800200 inOrder(longPressDragObserver) {
201 verify(longPressDragObserver).onLongPress(any())
202 verify(longPressDragObserver).onDragStart()
203 // Twice because DragGestureDetector dispatches onDrag during 2 passes.
204 verify(longPressDragObserver, times(2)).onDrag(any())
205 }
shepshapardd9f05232019-08-08 10:21:47 -0700206 verifyNoMoreInteractions(longPressDragObserver)
207 }
208
209 @Test
Shep Shapardbf513c52019-12-16 17:06:51 -0800210 fun ui_downWaitForLongPressUp_callbacksCorrect() {
shepshapardd9f05232019-08-08 10:21:47 -0700211
shepshapardd9f05232019-08-08 10:21:47 -0700212 val down = MotionEvent(
213 0,
214 MotionEvent.ACTION_DOWN,
215 1,
216 0,
217 arrayOf(PointerProperties(0)),
218 arrayOf(PointerCoords(50f, 50f))
219 )
220 waitForLongPress {
221 view.dispatchTouchEvent(down)
222 }
shepshapardd9f05232019-08-08 10:21:47 -0700223 val up = MotionEvent(
224 0,
225 MotionEvent.ACTION_UP,
226 1,
227 0,
228 arrayOf(PointerProperties(0)),
229 arrayOf(PointerCoords(51f, 50f))
230 )
231 view.dispatchTouchEvent(up)
232
233 // Assert.
Shep Shapardbf513c52019-12-16 17:06:51 -0800234 inOrder(longPressDragObserver) {
235 verify(longPressDragObserver).onLongPress(any())
236 verify(longPressDragObserver).onStop(any())
237 }
238 verifyNoMoreInteractions(longPressDragObserver)
239 }
240
241 @Test
242 fun ui_downWaitForLongPressMoveUp_callbacksCorrect() {
243
244 val down = MotionEvent(
245 0,
246 MotionEvent.ACTION_DOWN,
247 1,
248 0,
249 arrayOf(PointerProperties(0)),
250 arrayOf(PointerCoords(50f, 50f))
251 )
252 waitForLongPress {
253 view.dispatchTouchEvent(down)
254 }
255 val move = MotionEvent(
256 0,
257 MotionEvent.ACTION_MOVE,
258 1,
259 0,
260 arrayOf(PointerProperties(0)),
261 arrayOf(PointerCoords(51f, 50f))
262 )
263 view.dispatchTouchEvent(move)
264 val up = MotionEvent(
265 0,
266 MotionEvent.ACTION_UP,
267 1,
268 0,
269 arrayOf(PointerProperties(0)),
270 arrayOf(PointerCoords(51f, 50f))
271 )
272 view.dispatchTouchEvent(up)
273
274 inOrder(longPressDragObserver) {
275 verify(longPressDragObserver).onLongPress(any())
276 verify(longPressDragObserver).onDragStart()
277 // Twice because DragGestureDetector dispatches onDrag during 2 passes.
278 verify(longPressDragObserver, times(2)).onDrag(any())
279 verify(longPressDragObserver).onStop(any())
280 }
281 verifyNoMoreInteractions(longPressDragObserver)
282 }
283
284 @Test
285 fun ui_downWaitForLongPressCancel_callbacksCorrect() {
286
287 val down = MotionEvent(
288 0,
289 MotionEvent.ACTION_DOWN,
290 1,
291 0,
292 arrayOf(PointerProperties(0)),
293 arrayOf(PointerCoords(50f, 50f))
294 )
295 waitForLongPress {
296 view.dispatchTouchEvent(down)
297 }
298 val cancel = MotionEvent(
299 0,
300 MotionEvent.ACTION_CANCEL,
301 1,
302 0,
303 arrayOf(PointerProperties(0)),
304 arrayOf(PointerCoords(50f, 50f))
305 )
306 view.dispatchTouchEvent(cancel)
307
308 inOrder(longPressDragObserver) {
309 verify(longPressDragObserver).onLongPress(any())
310 verify(longPressDragObserver).onCancel()
311 }
312 verifyNoMoreInteractions(longPressDragObserver)
313 }
314
315 @Test
316 fun ui_downWaitForLongPressMoveCancel_callbacksCorrect() {
317
318 val down = MotionEvent(
319 0,
320 MotionEvent.ACTION_DOWN,
321 1,
322 0,
323 arrayOf(PointerProperties(0)),
324 arrayOf(PointerCoords(50f, 50f))
325 )
326 waitForLongPress {
327 view.dispatchTouchEvent(down)
328 }
329 val move = MotionEvent(
330 0,
331 MotionEvent.ACTION_MOVE,
332 1,
333 0,
334 arrayOf(PointerProperties(0)),
335 arrayOf(PointerCoords(51f, 50f))
336 )
337 view.dispatchTouchEvent(move)
338 val cancel = MotionEvent(
339 0,
340 MotionEvent.ACTION_CANCEL,
341 1,
342 0,
343 arrayOf(PointerProperties(0)),
344 arrayOf(PointerCoords(51f, 50f))
345 )
346 view.dispatchTouchEvent(cancel)
347
348 inOrder(longPressDragObserver) {
349 verify(longPressDragObserver).onLongPress(any())
350 verify(longPressDragObserver).onDragStart()
351 // Twice because DragGestureDetector dispatches onDrag during 2 passes.
352 verify(longPressDragObserver, times(2)).onDrag(any())
353 verify(longPressDragObserver).onCancel()
354 }
shepshapardd9f05232019-08-08 10:21:47 -0700355 verifyNoMoreInteractions(longPressDragObserver)
356 }
357
358 private fun waitForLongPress(block: () -> Unit) {
359 longPressCountDownLatch = CountDownLatch(1)
Louis Pullen-Freilich54b4c112019-10-23 19:05:56 +0100360 activityTestRule.runOnUiThreadIR(block)
shepshapardd9f05232019-08-08 10:21:47 -0700361 assertTrue(longPressCountDownLatch.await(750, TimeUnit.MILLISECONDS))
362 }
363}
364
365@Suppress("RedundantOverride")
366open class MyLongPressDragObserver(val onLongPress: () -> Unit) : LongPressDragObserver {
367 override fun onLongPress(pxPosition: PxPosition) {
368 onLongPress()
369 }
370
Shep Shapardbf513c52019-12-16 17:06:51 -0800371 override fun onDragStart() {}
shepshapardd9f05232019-08-08 10:21:47 -0700372
373 override fun onDrag(dragDistance: PxPosition): PxPosition {
374 return super.onDrag(dragDistance)
375 }
376
Shep Shapardbf513c52019-12-16 17:06:51 -0800377 override fun onStop(velocity: PxPosition) {}
shepshapardb14d6432019-08-05 17:13:22 -0700378}