[fenix] Issue https://github.com/mozilla-mobile/fenix/issues/26097: use mock location in UI tests
parent
7d442af6d6
commit
c993d3de51
@ -0,0 +1,111 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.location.Location
|
||||
import android.location.LocationManager
|
||||
import android.os.Build
|
||||
import android.os.SystemClock
|
||||
import android.util.Log
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import org.junit.rules.ExternalResource
|
||||
import java.util.Date
|
||||
import kotlin.random.Random
|
||||
import org.mozilla.fenix.helpers.TestHelper.mDevice
|
||||
|
||||
private const val mockProviderName = LocationManager.GPS_PROVIDER
|
||||
|
||||
/**
|
||||
* Rule that sets up a mock location provider that can inject location samples
|
||||
* straight to the device that the test is running on.
|
||||
*
|
||||
* Credit to the mapbox team
|
||||
* https://github.com/mapbox/mapbox-navigation-android/blob/87fab7ea1152b29533ee121eaf6c05bc202adf02/libtesting-ui/src/main/java/com/mapbox/navigation/testing/ui/MockLocationUpdatesRule.kt
|
||||
*
|
||||
*/
|
||||
class MockLocationUpdatesRule : ExternalResource() {
|
||||
private val appContext = (ApplicationProvider.getApplicationContext() as Context)
|
||||
val latitude = Random.nextDouble(-90.0, 90.0)
|
||||
val longitude = Random.nextDouble(-180.0, 180.0)
|
||||
|
||||
private val locationManager: LocationManager by lazy {
|
||||
(appContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager)
|
||||
}
|
||||
|
||||
override fun before() {
|
||||
/* ADB command to enable the mock location setting on the device.
|
||||
* Will not be turned back off due to limitations on knowing its initial state.
|
||||
*/
|
||||
mDevice.executeShellCommand(
|
||||
"appops set " +
|
||||
appContext.packageName +
|
||||
" android:mock_location allow"
|
||||
)
|
||||
|
||||
// To mock locations we need a location provider, so we generate and set it here.
|
||||
try {
|
||||
locationManager.addTestProvider(
|
||||
mockProviderName,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
3,
|
||||
2
|
||||
)
|
||||
} catch (ex: Exception) {
|
||||
// unstable
|
||||
Log.w("MockLocationUpdatesRule", "addTestProvider failed")
|
||||
}
|
||||
locationManager.setTestProviderEnabled(mockProviderName, true)
|
||||
}
|
||||
|
||||
// Cleaning up the location provider after the test.
|
||||
override fun after() {
|
||||
locationManager.setTestProviderEnabled(mockProviderName, false)
|
||||
locationManager.removeTestProvider(mockProviderName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a valid mock location data and set with the help of a test provider.
|
||||
*
|
||||
* @param modifyLocation optional callback for modifying the constructed location before setting it.
|
||||
*/
|
||||
fun setMockLocation(modifyLocation: (Location.() -> Unit)? = null) {
|
||||
check(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
"MockLocationUpdatesRule is supported only on Android devices " +
|
||||
"running version >= Build.VERSION_CODES.M"
|
||||
}
|
||||
|
||||
val location = Location(mockProviderName)
|
||||
location.time = Date().time
|
||||
location.elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos()
|
||||
location.accuracy = 5f
|
||||
location.altitude = 0.0
|
||||
location.bearing = 0f
|
||||
location.speed = 5f
|
||||
location.latitude = latitude
|
||||
location.longitude = longitude
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
location.verticalAccuracyMeters = 5f
|
||||
location.bearingAccuracyDegrees = 5f
|
||||
location.speedAccuracyMetersPerSecond = 5f
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
location.elapsedRealtimeUncertaintyNanos = 0.0
|
||||
}
|
||||
|
||||
modifyLocation?.let {
|
||||
location.apply(it)
|
||||
}
|
||||
|
||||
locationManager.setTestProviderLocation(mockProviderName, location)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue