Bug 1882777 - Request permission to reset locale in UI tests

fenix/125.0
oana.horvath 3 months ago committed by mergify[bot]
parent 216c8cfdb2
commit affd8204e5

@ -356,64 +356,60 @@ object AppAndSystemHelper {
/** /**
* Changes the default language of the entire device, not just the app. * Changes the default language of the entire device, not just the app.
* Runs on Debug variant as we don't want to adjust Release permission manifests
* Runs the test in its testBlock. * Runs the test in its testBlock.
* Cleans up and sets the default locale after it's done. * Cleans up and sets the default locale after it's done.
* As a safety measure, always add the resetSystemLocaleToEnUS() method in the tearDown method of your Class.
*/ */
fun runWithSystemLocaleChanged(locale: Locale, testRule: ActivityTestRule<HomeActivity>, testBlock: () -> Unit) { fun runWithSystemLocaleChanged(locale: Locale, testRule: ActivityTestRule<HomeActivity>, testBlock: () -> Unit) {
val defaultLocale = Locale.getDefault()
try {
setSystemLocale(locale)
testBlock()
ThreadUtils.runOnUiThread { testRule.activity.recreate() }
} catch (e: Exception) {
e.printStackTrace()
} finally {
setSystemLocale(defaultLocale)
}
}
/**
* Changes the default language of the entire device, not just the app.
* We can only use this if we're running on a debug build, otherwise it will change the permission manifests in release builds.
*/
fun setSystemLocale(locale: Locale) {
if (Config.channel.isDebug) { if (Config.channel.isDebug) {
/* Sets permission to change device language */ /* Sets permission to change device language */
Log.i(
TAG,
"setSystemLocale: Requesting permission to change system locale to $locale.",
)
PermissionRequester().apply { PermissionRequester().apply {
addPermissions( addPermissions(
Manifest.permission.CHANGE_CONFIGURATION, Manifest.permission.CHANGE_CONFIGURATION,
) )
requestPermissions() requestPermissions()
} }
Log.i(
val defaultLocale = Locale.getDefault() TAG,
"setSystemLocale: Received permission to change system locale to $locale.",
try { )
setSystemLocale(locale) val activityManagerNative = Class.forName("android.app.ActivityManagerNative")
testBlock() val am = activityManagerNative.getMethod("getDefault", *arrayOfNulls(0))
ThreadUtils.runOnUiThread { testRule.activity.recreate() } .invoke(activityManagerNative, *arrayOfNulls(0))
} catch (e: Exception) { val config =
e.printStackTrace() InstrumentationRegistry.getInstrumentation().context.resources.configuration
} finally { config.javaClass.getDeclaredField("locale")[config] = locale
setSystemLocale(defaultLocale) config.javaClass.getDeclaredField("userSetLocale").setBoolean(config, true)
} am.javaClass.getMethod(
} "updateConfiguration",
} Configuration::class.java,
).invoke(am, config)
/**
* Resets the default language of the entire device back to EN-US.
* In case of a test instrumentation crash, the finally statement in the
* runWithSystemLocaleChanged(locale: Locale) method, will not be reached.
* Add this method inside the tearDown method of your test class, where the above method is used.
* Note: If set inside the ActivityTestRule's afterActivityFinished() method, this also won't work,
* as the methods inside it are not always executed: https://github.com/android/android-test/issues/498
*/
fun resetSystemLocaleToEnUS() {
if (Locale.getDefault() != Locale.US) {
Log.i(TAG, "Resetting system locale to EN US")
setSystemLocale(Locale.US)
} }
} Log.i(
TAG,
/** "setSystemLocale: Changed system locale to $locale.",
* Changes the default language of the entire device, not just the app. )
*/
fun setSystemLocale(locale: Locale) {
val activityManagerNative = Class.forName("android.app.ActivityManagerNative")
val am = activityManagerNative.getMethod("getDefault", *arrayOfNulls(0))
.invoke(activityManagerNative, *arrayOfNulls(0))
val config = InstrumentationRegistry.getInstrumentation().context.resources.configuration
config.javaClass.getDeclaredField("locale")[config] = locale
config.javaClass.getDeclaredField("userSetLocale").setBoolean(config, true)
am.javaClass.getMethod(
"updateConfiguration",
Configuration::class.java,
).invoke(am, config)
} }
fun putAppToBackground() { fun putAppToBackground() {

@ -11,8 +11,8 @@ import org.junit.After
import org.junit.Before import org.junit.Before
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.Constants.TAG
import org.mozilla.fenix.helpers.TestHelper.appContext
import org.mozilla.fenix.ui.robots.notificationShade import org.mozilla.fenix.ui.robots.notificationShade
import java.util.Locale
/** /**
* Standard Test setup and tear down methods to run before each test. * Standard Test setup and tear down methods to run before each test.
@ -26,19 +26,12 @@ open class TestSetup {
@Before @Before
open fun setUp() { open fun setUp() {
Log.i(TAG, "TestSetup: Starting the @Before setup") Log.i(TAG, "TestSetup: Starting the @Before setup")
// Initializing this as part of class construction, below the rule would throw a NPE.
// So we are initializing this here instead of in all related tests.
Log.i(TAG, "TestSetup: Trying to initialize the browserStore instance")
browserStore = appContext.components.core.store
Log.i(TAG, "TestSetup: Initialized the browserStore instance")
// Clear pre-existing notifications.
notificationShade {
cancelAllShownNotifications()
}
runBlocking { runBlocking {
// Reset locale to EN-US if needed. // Reset locale to EN-US if needed.
AppAndSystemHelper.resetSystemLocaleToEnUS() // Because of https://bugzilla.mozilla.org/show_bug.cgi?id=1812183, some items might not be updated.
if (Locale.getDefault() != Locale.US) {
AppAndSystemHelper.setSystemLocale(Locale.US)
}
// Check and clear the downloads folder, in case the tearDown method is not executed. // Check and clear the downloads folder, in case the tearDown method is not executed.
// This will only work in case of a RetryTestRule execution. // This will only work in case of a RetryTestRule execution.
AppAndSystemHelper.clearDownloadsFolder() AppAndSystemHelper.clearDownloadsFolder()
@ -52,6 +45,16 @@ open class TestSetup {
AppAndSystemHelper.deletePermissionsStorage() AppAndSystemHelper.deletePermissionsStorage()
} }
// Initializing this as part of class construction, below the rule would throw a NPE.
// So we are initializing this here instead of in all related tests.
Log.i(TAG, "TestSetup: Trying to initialize the browserStore instance")
browserStore = TestHelper.appContext.components.core.store
Log.i(TAG, "TestSetup: Initialized the browserStore instance")
// Clear pre-existing notifications.
notificationShade {
cancelAllShownNotifications()
}
mockWebServer = MockWebServer().apply { mockWebServer = MockWebServer().apply {
dispatcher = AndroidAssetDispatcher() dispatcher = AndroidAssetDispatcher()
} }
@ -68,7 +71,16 @@ open class TestSetup {
@After @After
open fun tearDown() { open fun tearDown() {
Log.i(TAG, "TestSetup: Starting the @After tearDown methods.") Log.i(TAG, "TestSetup: Starting the @After tearDown methods.")
// Check and clear the downloads folder. runBlocking {
AppAndSystemHelper.clearDownloadsFolder() // Check and clear the downloads folder.
AppAndSystemHelper.clearDownloadsFolder()
// Reset locale to EN-US if needed.
// This method is only here temporarily, to set the language before a new activity is started.
// TODO: When https://bugzilla.mozilla.org/show_bug.cgi?id=1812183 is fixed, it should be removed.
if (Locale.getDefault() != Locale.US) {
AppAndSystemHelper.setSystemLocale(Locale.US)
}
}
} }
} }

Loading…
Cancel
Save