Issue #26097: use mock location in UI tests

This commit is contained in:
sv-ohorvath 2022-07-19 17:59:51 +03:00 committed by mergify[bot]
parent f3ef15800c
commit 3111c8bf8b
2 changed files with 122 additions and 8 deletions

View File

@ -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)
}
}

View File

@ -15,12 +15,12 @@ import androidx.test.rule.GrantPermissionRule
import org.junit.After
import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.customannotations.SmokeTest
import org.mozilla.fenix.helpers.FeatureSettingsHelper
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.helpers.MockLocationUpdatesRule
import org.mozilla.fenix.helpers.RetryTestRule
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.ui.robots.browserScreen
@ -44,11 +44,14 @@ class SitePermissionsTest {
@get:Rule
val grantPermissionRule: GrantPermissionRule = GrantPermissionRule.grant(
Manifest.permission.RECORD_AUDIO,
Manifest.permission.CAMERA
Manifest.permission.CAMERA,
Manifest.permission.ACCESS_COARSE_LOCATION
)
@Rule
@JvmField
@get: Rule
val mockLocationUpdatesRule = MockLocationUpdatesRule()
@get: Rule
val retryTestRule = RetryTestRule(3)
@Before
@ -282,20 +285,20 @@ class SitePermissionsTest {
}
}
@Ignore("Needs mocking location for Firebase - to do: https://github.com/mozilla-mobile/mobile-test-eng/issues/585")
@Test
fun allowLocationPermissionsTest() {
mockLocationUpdatesRule.setMockLocation()
navigationToolbar {
}.enterURLAndEnterToBrowser(testPage.toUri()) {
}.clickGetLocationButton {
verifyLocationPermissionPrompt(testPageSubstring)
}.clickPagePermissionButton(true) {
verifyPageContent("longitude")
verifyPageContent("latitude")
verifyPageContent("${mockLocationUpdatesRule.latitude}")
verifyPageContent("${mockLocationUpdatesRule.longitude}")
}
}
@Ignore("Needs mocking location for Firebase - to do: https://github.com/mozilla-mobile/mobile-test-eng/issues/585")
@Test
fun blockLocationPermissionsTest() {
navigationToolbar {