Merge branch 'main' into perf-mailbox-message-loading
This commit is contained in:
@@ -3,6 +3,7 @@ package org.libremail.ui.settings
|
||||
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||
import androidx.compose.ui.test.onAllNodesWithText
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performScrollTo
|
||||
@@ -14,7 +15,6 @@ import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.libremail.R
|
||||
import org.libremail.data.security.AppLockAvailability
|
||||
import org.libremail.data.security.AppLockManager
|
||||
import org.libremail.data.security.DatabaseKeyCipher
|
||||
import org.libremail.data.security.DatabaseKeyStore
|
||||
@@ -29,8 +29,10 @@ import org.libremail.ui.theme.LibreMailTheme
|
||||
import javax.inject.Provider
|
||||
|
||||
/**
|
||||
* End-to-end test for the top-level message-downloading setting: tapping a policy must round-trip
|
||||
* through the real [SettingsRepository] (DataStore), proving the UI → ViewModel → persistence wiring.
|
||||
* End-to-end tests for the global settings screen. Tapping a policy must round-trip through the real
|
||||
* [SettingsRepository] (DataStore), proving the UI → ViewModel → persistence wiring; and enabling
|
||||
* app-lock on a device with no secure lock must surface the rejection message via a snackbar — now
|
||||
* visible to Compose semantics, unlike the former Toast it replaced.
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class SettingsScreenTest {
|
||||
@@ -38,27 +40,28 @@ class SettingsScreenTest {
|
||||
@get:Rule
|
||||
val composeTestRule = createAndroidComposeRule<ComponentActivity>()
|
||||
|
||||
private val context = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext
|
||||
|
||||
// Device reports no secure lock, so enabling app-lock is rejected with a message.
|
||||
private val insecureDevice = object : AppLockManager {
|
||||
override fun isDeviceSecure() = false
|
||||
}
|
||||
|
||||
private fun string(resId: Int) = composeTestRule.activity.getString(resId)
|
||||
|
||||
@Test
|
||||
fun selectingFetchPolicy_persistsThroughTheRepository() {
|
||||
val context = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext
|
||||
val settingsRepository = SettingsRepository(context)
|
||||
runBlocking { settingsRepository.setFetchPolicy(FetchPolicy.ALWAYS) } // known starting state
|
||||
val appLockManager = object : AppLockManager {
|
||||
override fun isDeviceSecure() = false
|
||||
override fun availability() = AppLockAvailability.NONE_ENROLLED
|
||||
}
|
||||
private fun settingsViewModel(settingsRepository: SettingsRepository): SettingsViewModel {
|
||||
val keyStore = DatabaseKeyStore(context, KeystoreCrypto(), DatabaseKeyCipher(), PassphraseSession())
|
||||
val viewModel = SettingsViewModel(
|
||||
return SettingsViewModel(
|
||||
FakeAccountRepository(),
|
||||
settingsRepository,
|
||||
appLockManager,
|
||||
insecureDevice,
|
||||
keyStore,
|
||||
BatteryOptimizationManager(context),
|
||||
SyncScheduler(Provider { WorkManager.getInstance(context) }),
|
||||
)
|
||||
}
|
||||
|
||||
private fun setContent(viewModel: SettingsViewModel) {
|
||||
composeTestRule.setContent {
|
||||
LibreMailTheme(darkTheme = false, dynamicColor = false) {
|
||||
SettingsScreen(
|
||||
@@ -70,6 +73,13 @@ class SettingsScreenTest {
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun selectingFetchPolicy_persistsThroughTheRepository() {
|
||||
val settingsRepository = SettingsRepository(context)
|
||||
runBlocking { settingsRepository.setFetchPolicy(FetchPolicy.ALWAYS) } // known starting state
|
||||
setContent(settingsViewModel(settingsRepository))
|
||||
|
||||
composeTestRule.onNodeWithText(string(R.string.fetch_on_demand)).performScrollTo().performClick()
|
||||
|
||||
@@ -77,4 +87,20 @@ class SettingsScreenTest {
|
||||
runBlocking { settingsRepository.fetchPolicy() } == FetchPolicy.ON_DEMAND
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun enablingAppLockWithoutSecureDevice_showsRejectionSnackbar() {
|
||||
val settingsRepository = SettingsRepository(context)
|
||||
runBlocking { settingsRepository.setAppLock(false) } // known starting state: off
|
||||
setContent(settingsViewModel(settingsRepository))
|
||||
|
||||
// App-lock lives under the collapsed "Advanced" section: expand it, then toggle the switch on.
|
||||
composeTestRule.onNodeWithText(string(R.string.settings_advanced)).performScrollTo().performClick()
|
||||
composeTestRule.onNodeWithText(string(R.string.settings_adv_app_lock)).performScrollTo().performClick()
|
||||
|
||||
val message = string(R.string.app_lock_needs_device_lock)
|
||||
composeTestRule.waitUntil(5_000) {
|
||||
composeTestRule.onAllNodesWithText(message).fetchSemanticsNodes().isNotEmpty()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user