summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorŁukasz Paczos <lukas.paczos@gmail.com>2019-07-10 19:36:56 +0200
committerŁukasz Paczos <lukas.paczos@gmail.com>2019-07-10 19:47:27 +0200
commit613a7949857687007358f82fcc79ee768dbec6c8 (patch)
tree28dd2b78ee5514283a5cf682fbfab70f574357a5
parentb351cc7cec56cb91ca9992b3e6ac4988639a7c7f (diff)
downloadqtlocation-mapboxgl-upstream/lp-quick-zoom-move-15091.tar.gz
[android] add regression tests for recent quick zoom/double tap issuesupstream/lp-quick-zoom-move-15091
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/GesturesUiTestUtils.kt454
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapGestureDetectorTest.kt134
2 files changed, 588 insertions, 0 deletions
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/GesturesUiTestUtils.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/GesturesUiTestUtils.kt
new file mode 100644
index 0000000000..2f6346d37d
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/GesturesUiTestUtils.kt
@@ -0,0 +1,454 @@
+package com.mapbox.mapboxsdk.maps
+
+import android.graphics.PointF
+import android.os.SystemClock
+import android.support.test.espresso.Espresso
+import android.support.test.espresso.InjectEventSecurityException
+import android.support.test.espresso.UiController
+import android.support.test.espresso.ViewAction
+import android.support.test.espresso.matcher.ViewMatchers
+import android.view.MotionEvent
+import android.view.View
+
+import org.hamcrest.Matcher
+
+object GesturesUiTestUtils {
+
+ private const val DEFAULT_GESTURE_DURATION = 500L
+
+ fun pinch(startSpan: Float, endSpan: Float, center: PointF? = null, duration: Long = DEFAULT_GESTURE_DURATION): ViewAction {
+ return object : ViewAction {
+ override fun getConstraints(): Matcher<View> {
+ return ViewMatchers.isEnabled()
+ }
+
+ override fun getDescription(): String = "Pinch $startSpan -> $endSpan"
+
+ override fun perform(uiController: UiController, view: View) {
+ var middlePosition = center
+ if (middlePosition == null) {
+ middlePosition = getCenterPointF(view)
+ }
+
+ val startPoint1 = PointF(middlePosition.x - startSpan / 2f, middlePosition.y)
+ val startPoint2 = PointF(middlePosition.x + startSpan / 2f, middlePosition.y)
+ val endPoint1 = PointF(middlePosition.x - endSpan / 2f, middlePosition.y)
+ val endPoint2 = PointF(middlePosition.x + endSpan / 2f, middlePosition.y)
+
+ performPinch(uiController, startPoint1, startPoint2, endPoint1, endPoint2, duration)
+ }
+ }
+ }
+
+ fun quickScale(deltaY: Float, startPoint: PointF? = null, withVelocity: Boolean = true, duration: Long = DEFAULT_GESTURE_DURATION, interrupt: Boolean = false): ViewAction {
+ return object : ViewAction {
+ override fun getConstraints(): Matcher<View> = ViewMatchers.isEnabled()
+
+ override fun getDescription(): String = "quick scale ${deltaY}Y"
+
+ override fun perform(uiController: UiController, view: View) {
+ var middlePosition = startPoint
+ if (middlePosition == null) {
+ middlePosition = getCenterPointF(view)
+ }
+
+ val endPoint = PointF(middlePosition.x, middlePosition.y + deltaY)
+
+ performQuickScale(uiController, middlePosition, endPoint, withVelocity, duration, interrupt)
+ }
+ }
+ }
+
+ fun move(deltaX: Float, deltaY: Float, startPoint: PointF? = null, withVelocity: Boolean = true, duration: Long = DEFAULT_GESTURE_DURATION): ViewAction {
+ return object : ViewAction {
+ override fun getConstraints(): Matcher<View> = ViewMatchers.isEnabled()
+
+ override fun getDescription(): String = "move ${deltaX}X, ${deltaY}Y"
+
+ override fun perform(uiController: UiController, view: View) {
+ var middlePosition = startPoint
+ if (middlePosition == null) {
+ middlePosition = getCenterPointF(view)
+ }
+
+ val endPoint = PointF(middlePosition.x + deltaX, middlePosition.y + deltaY)
+
+ performMove(uiController, middlePosition, endPoint, withVelocity, duration)
+ }
+ }
+ }
+
+ private fun getCenterPointF(view: View): PointF {
+ val locationOnScreen = IntArray(2)
+ view.getLocationOnScreen(locationOnScreen)
+ val viewHeight = view.height * view.scaleY
+ val viewWidth = view.width * view.scaleX
+ return PointF(
+ (locationOnScreen[0] + viewWidth / 2).toInt().toFloat(),
+ (locationOnScreen[1] + viewHeight / 2).toInt().toFloat())
+ }
+
+ // https://stackoverflow.com/a/46443628/9126211
+ private fun performPinch(
+ uiController: UiController,
+ startPoint1: PointF,
+ startPoint2: PointF,
+ endPoint1: PointF,
+ endPoint2: PointF,
+ duration: Long
+ ) {
+ val eventMinInterval: Long = 10
+ val startTime = SystemClock.uptimeMillis()
+ var eventTime = startTime
+ var event: MotionEvent
+ var eventX1: Float = startPoint1.x
+ var eventY1: Float = startPoint1.y
+ var eventX2: Float = startPoint2.x
+ var eventY2: Float = startPoint2.y
+
+ // Specify the property for the two touch points
+ val properties = arrayOfNulls<MotionEvent.PointerProperties>(2)
+ val pp1 = MotionEvent.PointerProperties()
+ pp1.id = 0
+ pp1.toolType = MotionEvent.TOOL_TYPE_FINGER
+ val pp2 = MotionEvent.PointerProperties()
+ pp2.id = 1
+ pp2.toolType = MotionEvent.TOOL_TYPE_FINGER
+
+ properties[0] = pp1
+ properties[1] = pp2
+
+ // Specify the coordinations of the two touch points
+ // NOTE: you MUST set the pressure and size value, or it doesn't work
+ val pointerCoords = arrayOfNulls<MotionEvent.PointerCoords>(2)
+ val pc1 = MotionEvent.PointerCoords()
+ pc1.x = eventX1
+ pc1.y = eventY1
+ pc1.pressure = 1f
+ pc1.size = 1f
+ val pc2 = MotionEvent.PointerCoords()
+ pc2.x = eventX2
+ pc2.y = eventY2
+ pc2.pressure = 1f
+ pc2.size = 1f
+ pointerCoords[0] = pc1
+ pointerCoords[1] = pc2
+
+ /*
+ * Events sequence of zoom gesture:
+ *
+ * 1. Send ACTION_DOWN event of one start point
+ * 2. Send ACTION_POINTER_DOWN of two start points
+ * 3. Send ACTION_MOVE of two middle points
+ * 4. Repeat step 3 with updated middle points (x,y), until reach the end points
+ * 5. Send ACTION_POINTER_UP of two end points
+ * 6. Send ACTION_UP of one end point
+ */
+
+ try {
+ // Step 1
+ event = MotionEvent.obtain(startTime, eventTime,
+ MotionEvent.ACTION_DOWN, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0)
+ injectMotionEventToUiController(uiController, event)
+
+ // Step 2
+ event = MotionEvent.obtain(startTime, eventTime,
+ MotionEvent.ACTION_POINTER_DOWN + (pp2.id shl MotionEvent.ACTION_POINTER_INDEX_SHIFT), 2,
+ properties, pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0)
+ injectMotionEventToUiController(uiController, event)
+
+ // Step 3, 4
+ val moveEventNumber = duration / eventMinInterval
+
+ val stepX1: Float
+ val stepY1: Float
+ val stepX2: Float
+ val stepY2: Float
+
+ stepX1 = (endPoint1.x - startPoint1.x) / moveEventNumber
+ stepY1 = (endPoint1.y - startPoint1.y) / moveEventNumber
+ stepX2 = (endPoint2.x - startPoint2.x) / moveEventNumber
+ stepY2 = (endPoint2.y - startPoint2.y) / moveEventNumber
+
+ for (i in 0 until moveEventNumber) {
+ // Update the move events
+ eventTime += eventMinInterval
+ eventX1 += stepX1
+ eventY1 += stepY1
+ eventX2 += stepX2
+ eventY2 += stepY2
+
+ pc1.x = eventX1
+ pc1.y = eventY1
+ pc2.x = eventX2
+ pc2.y = eventY2
+
+ pointerCoords[0] = pc1
+ pointerCoords[1] = pc2
+
+ event = MotionEvent.obtain(startTime, eventTime,
+ MotionEvent.ACTION_MOVE, 2, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0)
+ injectMotionEventToUiController(uiController, event)
+ }
+
+ // Step 5
+ pc1.x = endPoint1.x
+ pc1.y = endPoint1.y
+ pc2.x = endPoint2.x
+ pc2.y = endPoint2.y
+ pointerCoords[0] = pc1
+ pointerCoords[1] = pc2
+
+ eventTime += eventMinInterval
+ event = MotionEvent.obtain(startTime, eventTime,
+ MotionEvent.ACTION_POINTER_UP + (pp2.id shl MotionEvent.ACTION_POINTER_INDEX_SHIFT), 2, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0)
+ injectMotionEventToUiController(uiController, event)
+
+ // Step 6
+ eventTime += eventMinInterval
+ event = MotionEvent.obtain(startTime, eventTime,
+ MotionEvent.ACTION_UP, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0)
+ injectMotionEventToUiController(uiController, event)
+ } catch (ex: InjectEventSecurityException) {
+ throw RuntimeException("Could not perform pinch", ex)
+ }
+ }
+
+ private fun performQuickScale(uiController: UiController, startPoint: PointF, endPoint: PointF, withVelocity: Boolean, duration: Long, interrupt: Boolean) {
+ val eventMinInterval: Long = 10
+ val tapDownMinInterval: Long = 40 // ViewConfiguration#DOUBLE_TAP_MIN_TIME = 40
+ val startTime = SystemClock.uptimeMillis()
+ var eventTime = startTime
+ var event: MotionEvent
+ var eventX1: Float = startPoint.x
+ var eventY1: Float = startPoint.y
+
+ var properties = arrayOfNulls<MotionEvent.PointerProperties>(1)
+ val pp1 = MotionEvent.PointerProperties()
+ pp1.id = 0
+ pp1.toolType = MotionEvent.TOOL_TYPE_FINGER
+ properties[0] = pp1
+
+ var pointerCoords = arrayOfNulls<MotionEvent.PointerCoords>(1)
+ val pc1 = MotionEvent.PointerCoords()
+ pc1.x = eventX1
+ pc1.y = eventY1
+ pc1.pressure = 1f
+ pc1.size = 1f
+ pointerCoords[0] = pc1
+
+ /*
+ * Events sequence of quick scale gesture:
+ *
+ * 1. Send ACTION_DOWN
+ * 2. Send ACTION_UP
+ * 3. Send ACTION_DOWN
+ * 4. Send ACTION_MOVE with updated middle points (x,y), until reach the end points
+ * 5. Send ACTION_UP of one end point
+ */
+ try {
+ // Step 1
+ event = MotionEvent.obtain(startTime, eventTime,
+ MotionEvent.ACTION_DOWN, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0)
+ injectMotionEventToUiController(uiController, event)
+
+ // Step 2
+ eventTime += eventMinInterval
+ event = MotionEvent.obtain(startTime, eventTime,
+ MotionEvent.ACTION_UP, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0)
+ injectMotionEventToUiController(uiController, event)
+
+ // Step 3
+ eventTime += tapDownMinInterval
+ event = MotionEvent.obtain(startTime, eventTime,
+ MotionEvent.ACTION_DOWN, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0)
+ injectMotionEventToUiController(uiController, event)
+
+ // Step 4
+ val moveEventNumber = duration / eventMinInterval
+
+ val stepX1: Float
+ val stepY1: Float
+
+ stepX1 = (endPoint.x - startPoint.x) / moveEventNumber
+ stepY1 = (endPoint.y - startPoint.y) / moveEventNumber
+
+ var interrupted = false
+
+ for (i in 0 until moveEventNumber) {
+ // Update the move events
+ eventTime += eventMinInterval
+ eventX1 += stepX1
+ eventY1 += stepY1
+
+ pc1.x = eventX1
+ pc1.y = eventY1
+
+ pointerCoords[0] = pc1
+
+ event = MotionEvent.obtain(startTime, eventTime,
+ MotionEvent.ACTION_MOVE, if (interrupted) 2 else 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0)
+ injectMotionEventToUiController(uiController, event)
+
+ if (interrupt && i == moveEventNumber / 2) {
+ // Specify the property for the two touch points
+ properties = arrayOfNulls<MotionEvent.PointerProperties>(2)
+ val pp2 = MotionEvent.PointerProperties()
+ pp2.id = 1
+ pp2.toolType = MotionEvent.TOOL_TYPE_FINGER
+
+ properties[0] = pp1
+ properties[1] = pp2
+
+ // Specify the coordinations of the two touch points
+ // NOTE: you MUST set the pressure and size value, or it doesn't work
+ pointerCoords = arrayOfNulls<MotionEvent.PointerCoords>(2)
+ val pc2 = MotionEvent.PointerCoords()
+ pc2.x = startPoint.x
+ pc2.y = startPoint.y
+ pc2.pressure = 1f
+ pc2.size = 1f
+ pointerCoords[0] = pc1
+ pointerCoords[1] = pc2
+
+ eventTime += eventMinInterval
+ event = MotionEvent.obtain(startTime, eventTime,
+ MotionEvent.ACTION_POINTER_DOWN + (pp2.id shl MotionEvent.ACTION_POINTER_INDEX_SHIFT), 2,
+ properties, pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0)
+ injectMotionEventToUiController(uiController, event)
+ interrupted = true
+ }
+ }
+
+ if (!withVelocity) {
+ eventTime += eventMinInterval
+ event = MotionEvent.obtain(startTime, eventTime,
+ MotionEvent.ACTION_MOVE, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0)
+ injectMotionEventToUiController(uiController, event)
+ }
+
+ // Step 5
+ eventTime += eventMinInterval
+ event = MotionEvent.obtain(startTime, eventTime,
+ MotionEvent.ACTION_UP, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0)
+ injectMotionEventToUiController(uiController, event)
+ } catch (ex: InjectEventSecurityException) {
+ throw RuntimeException("Could not perform quick scale", ex)
+ }
+ }
+
+ private fun performMove(uiController: UiController, startPoint: PointF, endPoint: PointF, withVelocity: Boolean, duration: Long) {
+ val eventMinInterval: Long = 10
+ val startTime = SystemClock.uptimeMillis()
+ var eventTime = startTime
+ var event: MotionEvent
+ var eventX1: Float = startPoint.x
+ var eventY1: Float = startPoint.y
+
+ val properties = arrayOfNulls<MotionEvent.PointerProperties>(1)
+ val pp1 = MotionEvent.PointerProperties()
+ pp1.id = 0
+ pp1.toolType = MotionEvent.TOOL_TYPE_FINGER
+ properties[0] = pp1
+
+ val pointerCoords = arrayOfNulls<MotionEvent.PointerCoords>(1)
+ val pc1 = MotionEvent.PointerCoords()
+ pc1.x = eventX1
+ pc1.y = eventY1
+ pc1.pressure = 1f
+ pc1.size = 1f
+ pointerCoords[0] = pc1
+
+ /*
+ * Events sequence of move gesture:
+ *
+ * 1. Send ACTION_DOWN
+ * 2. Send ACTION_MOVE with updated middle points (x,y), until reach the end points
+ * 3. Send ACTION_UP
+ */
+ try {
+ // Step 1
+ event = MotionEvent.obtain(startTime, eventTime,
+ MotionEvent.ACTION_DOWN, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0)
+ injectMotionEventToUiController(uiController, event)
+
+ // Step 2
+ val moveEventNumber = duration / eventMinInterval
+
+ val stepX1: Float
+ val stepY1: Float
+
+ stepX1 = (endPoint.x - startPoint.x) / moveEventNumber
+ stepY1 = (endPoint.y - startPoint.y) / moveEventNumber
+
+ for (i in 0 until moveEventNumber) {
+ // Update the move events
+ eventTime += eventMinInterval
+ eventX1 += stepX1
+ eventY1 += stepY1
+
+ pc1.x = eventX1
+ pc1.y = eventY1
+
+ pointerCoords[0] = pc1
+
+ event = MotionEvent.obtain(startTime, eventTime,
+ MotionEvent.ACTION_MOVE, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0)
+ injectMotionEventToUiController(uiController, event)
+ }
+
+ if (!withVelocity) {
+ eventTime += eventMinInterval
+ event = MotionEvent.obtain(startTime, eventTime,
+ MotionEvent.ACTION_MOVE, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0)
+ injectMotionEventToUiController(uiController, event)
+ }
+
+ // Step 3
+ eventTime += eventMinInterval
+ event = MotionEvent.obtain(startTime, eventTime,
+ MotionEvent.ACTION_UP, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0)
+ injectMotionEventToUiController(uiController, event)
+ } catch (ex: InjectEventSecurityException) {
+ throw RuntimeException("Could not perform quick scale", ex)
+ }
+ }
+
+ /**
+ * Safely call uiController.injectMotionEvent(event): Detect any error and "convert" it to an
+ * IllegalStateException
+ */
+ @Throws(InjectEventSecurityException::class)
+ private fun injectMotionEventToUiController(uiController: UiController, event: MotionEvent) {
+ val injectEventSucceeded = uiController.injectMotionEvent(event)
+ if (!injectEventSucceeded) {
+ throw IllegalStateException("Error performing event $event")
+ }
+ }
+}
+
+fun Int.loopFor(millis: Long) {
+ Espresso.onView(ViewMatchers.withId(this)).perform(object : ViewAction {
+ override fun getDescription(): String = "waiting for $millis"
+
+ override fun getConstraints(): Matcher<View> = ViewMatchers.isEnabled()
+
+ override fun perform(uiController: UiController?, view: View?) {
+ uiController?.loopMainThreadForAtLeast(millis)
+ }
+ })
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapGestureDetectorTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapGestureDetectorTest.kt
new file mode 100644
index 0000000000..3ef5921b8e
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapGestureDetectorTest.kt
@@ -0,0 +1,134 @@
+package com.mapbox.mapboxsdk.maps
+
+import android.graphics.PointF
+import android.support.test.espresso.Espresso.onView
+import android.support.test.espresso.matcher.ViewMatchers.withId
+import com.mapbox.mapboxsdk.camera.CameraPosition
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory
+import com.mapbox.mapboxsdk.constants.MapboxConstants
+import com.mapbox.mapboxsdk.geometry.LatLng
+import com.mapbox.mapboxsdk.maps.GesturesUiTestUtils.move
+import com.mapbox.mapboxsdk.maps.GesturesUiTestUtils.quickScale
+import com.mapbox.mapboxsdk.testapp.R
+import com.mapbox.mapboxsdk.testapp.activity.BaseTest
+import com.mapbox.mapboxsdk.testapp.activity.espresso.DeviceIndependentTestActivity
+import junit.framework.Assert
+import org.junit.Test
+
+class MapGestureDetectorTest : BaseTest() {
+ override fun getActivityClass() = DeviceIndependentTestActivity::class.java
+
+ @Test
+ fun sanity_quickZoom() {
+ validateTestSetup()
+ var initialZoom: Double? = null
+ rule.runOnUiThread {
+ initialZoom = mapboxMap.cameraPosition.zoom
+ }
+ onView(withId(R.id.mapView)).perform(quickScale(350f, withVelocity = false))
+ rule.runOnUiThread {
+ Assert.assertTrue(mapboxMap.cameraPosition.zoom > initialZoom!!)
+ Assert.assertEquals(2.77, mapboxMap.cameraPosition.zoom, 0.5)
+ }
+ }
+
+ @Test
+ fun quickZoomDisabled_phantomQuickZoom_moveStillEnabled_15091() {
+ // regression test for https://github.com/mapbox/mapbox-gl-native/issues/15091
+ validateTestSetup()
+ var initialCameraPosition: CameraPosition? = null
+ rule.runOnUiThread {
+ // zoom in so we can move vertically
+ mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4.0))
+ initialCameraPosition = mapboxMap.cameraPosition
+ mapboxMap.uiSettings.isQuickZoomGesturesEnabled = false
+ }
+
+ onView(withId(R.id.mapView)).perform(quickScale(300f))
+ rule.runOnUiThread {
+ // camera did not move
+ Assert.assertEquals(initialCameraPosition!!, mapboxMap.cameraPosition)
+ }
+
+ var expectedTarget: LatLng? = null
+ rule.runOnUiThread {
+ val currentPoint = mapboxMap.projection.toScreenLocation(initialCameraPosition!!.target)
+ val resultingPoint = PointF(currentPoint.x + 300f, currentPoint.y + 300f)
+ expectedTarget = mapboxMap.projection.fromScreenLocation(resultingPoint)
+ }
+
+ // move to expected target
+ onView(withId(R.id.mapView)).perform(move(-300f, -300f, withVelocity = false))
+ rule.runOnUiThread {
+ Assert.assertEquals(expectedTarget!!.latitude, mapboxMap.cameraPosition.target.latitude, 1.0)
+ Assert.assertEquals(expectedTarget!!.longitude, mapboxMap.cameraPosition.target.longitude, 1.0)
+ }
+ }
+
+ @Test
+ fun quickZoom_doNotMove_14227() {
+ // test for https://github.com/mapbox/mapbox-gl-native/issues/14227
+ validateTestSetup()
+ var initialTarget: LatLng? = null
+ rule.runOnUiThread {
+ initialTarget = mapboxMap.cameraPosition.target
+ }
+
+ onView(withId(R.id.mapView)).perform(quickScale(300f))
+ rule.runOnUiThread {
+ // camera did not move
+ Assert.assertEquals(initialTarget!!.latitude, mapboxMap.cameraPosition.target.latitude, 0.5)
+ Assert.assertEquals(initialTarget!!.longitude, mapboxMap.cameraPosition.target.longitude, 0.5)
+ }
+ }
+
+ @Test
+ fun quickZoom_interrupted_moveStillEnabled_14598() {
+ // test for https://github.com/mapbox/mapbox-gl-native/issues/14598
+ validateTestSetup()
+ onView(withId(R.id.mapView)).perform(quickScale(300f, interrupt = true))
+
+ var expectedTarget: LatLng? = null
+ rule.runOnUiThread {
+ val currentPoint = mapboxMap.projection.toScreenLocation(mapboxMap.cameraPosition.target)
+ val resultingPoint = PointF(currentPoint.x + 300f, currentPoint.y + 300f)
+ expectedTarget = mapboxMap.projection.fromScreenLocation(resultingPoint)
+ }
+
+ // move to expected target
+ onView(withId(R.id.mapView)).perform(move(-300f, -300f, withVelocity = false))
+ rule.runOnUiThread {
+ Assert.assertEquals(expectedTarget!!.latitude, mapboxMap.cameraPosition.target.latitude, 1.0)
+ Assert.assertEquals(expectedTarget!!.longitude, mapboxMap.cameraPosition.target.longitude, 1.0)
+ }
+ }
+
+ @Test
+ fun doubleTap_minimalMovement() {
+ validateTestSetup()
+ var initialZoom: Double? = null
+ rule.runOnUiThread {
+ initialZoom = mapboxMap.cameraPosition.zoom
+ }
+ onView(withId(R.id.mapView)).perform(quickScale(mapboxMap.gesturesManager.standardScaleGestureDetector.spanSinceStartThreshold / 2, withVelocity = false, duration = 50L))
+ R.id.mapView.loopFor(MapboxConstants.ANIMATION_DURATION.toLong())
+ rule.runOnUiThread {
+ Assert.assertEquals(initialZoom!! + 1, mapboxMap.cameraPosition.zoom, 0.1)
+ }
+ }
+
+ @Test
+ fun doubleTap_overMaxThreshold_ignore_14013() {
+ // test for https://github.com/mapbox/mapbox-gl-native/issues/14013
+ validateTestSetup()
+ var initialZoom: Double? = null
+ rule.runOnUiThread {
+ initialZoom = mapboxMap.cameraPosition.zoom
+ }
+ onView(withId(R.id.mapView)).perform(quickScale(mapboxMap.gesturesManager.standardScaleGestureDetector.spanSinceStartThreshold, withVelocity = false, duration = 50L))
+ R.id.mapView.loopFor(MapboxConstants.ANIMATION_DURATION.toLong())
+ rule.runOnUiThread {
+ Assert.assertEquals(initialZoom!!, mapboxMap.cameraPosition.zoom, 0.01)
+ }
+ }
+} \ No newline at end of file