[fenix] Closes https://github.com/mozilla-mobile/fenix/issues/10924 - Cleanup SavedLoginsAuthFragment (https://github.com/mozilla-mobile/fenix/pull/10930)
parent
81c0ec9d4b
commit
5b7d951590
@ -0,0 +1,105 @@
|
||||
/* 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.settings.logins
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.navigation.NavController
|
||||
import androidx.preference.Preference
|
||||
import mozilla.components.concept.sync.AccountObserver
|
||||
import mozilla.components.concept.sync.AuthType
|
||||
import mozilla.components.concept.sync.OAuthAccount
|
||||
import mozilla.components.service.fxa.SyncEngine
|
||||
import mozilla.components.service.fxa.manager.FxaAccountManager
|
||||
import mozilla.components.service.fxa.manager.SyncEnginesStorage
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.settings.logins.fragment.SavedLoginsAuthFragmentDirections
|
||||
|
||||
/**
|
||||
* Helper to manage the [R.string.pref_key_password_sync_logins] preference.
|
||||
*/
|
||||
class SyncLoginsPreferenceView(
|
||||
private val syncLoginsPreference: Preference,
|
||||
lifecycleOwner: LifecycleOwner,
|
||||
accountManager: FxaAccountManager,
|
||||
private val navController: NavController
|
||||
) {
|
||||
|
||||
init {
|
||||
accountManager.register(object : AccountObserver {
|
||||
override fun onAuthenticated(account: OAuthAccount, authType: AuthType) =
|
||||
updateSyncPreferenceStatus()
|
||||
override fun onLoggedOut() = updateSyncPreferenceNeedsLogin()
|
||||
override fun onAuthenticationProblems() = updateSyncPreferenceNeedsReauth()
|
||||
}, owner = lifecycleOwner)
|
||||
|
||||
val accountExists = accountManager.authenticatedAccount() != null
|
||||
val needsReauth = accountManager.accountNeedsReauth()
|
||||
when {
|
||||
needsReauth -> updateSyncPreferenceNeedsReauth()
|
||||
accountExists -> updateSyncPreferenceStatus()
|
||||
!accountExists -> updateSyncPreferenceNeedsLogin()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the current status of the sync preference (on/off) for the logged in user.
|
||||
*/
|
||||
private fun updateSyncPreferenceStatus() {
|
||||
syncLoginsPreference.apply {
|
||||
val syncEnginesStatus = SyncEnginesStorage(context).getStatus()
|
||||
val loginsSyncStatus = syncEnginesStatus.getOrElse(SyncEngine.Passwords) { false }
|
||||
summary = context.getString(
|
||||
if (loginsSyncStatus) R.string.preferences_passwords_sync_logins_on
|
||||
else R.string.preferences_passwords_sync_logins_off
|
||||
)
|
||||
setOnPreferenceClickListener {
|
||||
navigateToAccountSettingsFragment()
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the user can sign in to turn on sync.
|
||||
*/
|
||||
private fun updateSyncPreferenceNeedsLogin() {
|
||||
syncLoginsPreference.apply {
|
||||
summary = context.getString(R.string.preferences_passwords_sync_logins_sign_in)
|
||||
setOnPreferenceClickListener {
|
||||
navigateToTurnOnSyncFragment()
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the user can fix their account problems to turn on sync.
|
||||
*/
|
||||
private fun updateSyncPreferenceNeedsReauth() {
|
||||
syncLoginsPreference.apply {
|
||||
summary = context.getString(R.string.preferences_passwords_sync_logins_reconnect)
|
||||
setOnPreferenceClickListener {
|
||||
navigateToAccountProblemFragment()
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateToAccountSettingsFragment() {
|
||||
val directions =
|
||||
SavedLoginsAuthFragmentDirections.actionGlobalAccountSettingsFragment()
|
||||
navController.navigate(directions)
|
||||
}
|
||||
|
||||
private fun navigateToAccountProblemFragment() {
|
||||
val directions = SavedLoginsAuthFragmentDirections.actionGlobalAccountProblemFragment()
|
||||
navController.navigate(directions)
|
||||
}
|
||||
|
||||
private fun navigateToTurnOnSyncFragment() {
|
||||
val directions = SavedLoginsAuthFragmentDirections.actionSavedLoginsAuthFragmentToTurnOnSyncFragment()
|
||||
navController.navigate(directions)
|
||||
}
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
package org.mozilla.fenix.settings.logins
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.navigation.NavController
|
||||
import androidx.preference.Preference
|
||||
import io.mockk.CapturingSlot
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.Runs
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.mockk.just
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkConstructor
|
||||
import io.mockk.slot
|
||||
import io.mockk.unmockkConstructor
|
||||
import io.mockk.verify
|
||||
import mozilla.components.concept.sync.AccountObserver
|
||||
import mozilla.components.service.fxa.SyncEngine
|
||||
import mozilla.components.service.fxa.manager.FxaAccountManager
|
||||
import mozilla.components.service.fxa.manager.SyncEnginesStorage
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.settings.logins.fragment.SavedLoginsAuthFragmentDirections
|
||||
|
||||
class SyncLoginsPreferenceViewTest {
|
||||
|
||||
@MockK private lateinit var syncLoginsPreference: Preference
|
||||
@MockK private lateinit var lifecycleOwner: LifecycleOwner
|
||||
@MockK private lateinit var accountManager: FxaAccountManager
|
||||
@MockK(relaxed = true) private lateinit var navController: NavController
|
||||
private lateinit var accountObserver: CapturingSlot<AccountObserver>
|
||||
private lateinit var clickListener: CapturingSlot<Preference.OnPreferenceClickListener>
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
MockKAnnotations.init(this)
|
||||
mockkConstructor(SyncEnginesStorage::class)
|
||||
|
||||
accountObserver = slot()
|
||||
clickListener = slot()
|
||||
val context = mockk<Context> {
|
||||
every { getString(R.string.preferences_passwords_sync_logins_reconnect) } returns "Reconnect"
|
||||
every { getString(R.string.preferences_passwords_sync_logins_sign_in) } returns "Sign in to Sync"
|
||||
every { getString(R.string.preferences_passwords_sync_logins_on) } returns "On"
|
||||
every { getString(R.string.preferences_passwords_sync_logins_off) } returns "Off"
|
||||
}
|
||||
|
||||
every { syncLoginsPreference.summary = any() } just Runs
|
||||
every { syncLoginsPreference.onPreferenceClickListener = capture(clickListener) } just Runs
|
||||
every { syncLoginsPreference.context } returns context
|
||||
every { accountManager.register(capture(accountObserver), owner = lifecycleOwner) } just Runs
|
||||
every { anyConstructed<SyncEnginesStorage>().getStatus() } returns emptyMap()
|
||||
}
|
||||
|
||||
@After
|
||||
fun teardown() {
|
||||
unmockkConstructor(SyncEnginesStorage::class)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `needs reauth ui on init`() {
|
||||
every { accountManager.authenticatedAccount() } returns mockk()
|
||||
every { accountManager.accountNeedsReauth() } returns true
|
||||
createView()
|
||||
|
||||
verify { syncLoginsPreference.summary = "Reconnect" }
|
||||
assertTrue(clickListener.captured.onPreferenceClick(syncLoginsPreference))
|
||||
|
||||
verify {
|
||||
navController.navigate(
|
||||
SavedLoginsAuthFragmentDirections.actionGlobalAccountProblemFragment()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `needs reauth ui on init even if null account`() {
|
||||
every { accountManager.authenticatedAccount() } returns null
|
||||
every { accountManager.accountNeedsReauth() } returns true
|
||||
createView()
|
||||
|
||||
verify { syncLoginsPreference.summary = "Reconnect" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `needs login if account does not exist`() {
|
||||
every { accountManager.authenticatedAccount() } returns null
|
||||
every { accountManager.accountNeedsReauth() } returns false
|
||||
createView()
|
||||
|
||||
verify { syncLoginsPreference.summary = "Sign in to Sync" }
|
||||
assertTrue(clickListener.captured.onPreferenceClick(syncLoginsPreference))
|
||||
|
||||
verify {
|
||||
navController.navigate(
|
||||
SavedLoginsAuthFragmentDirections.actionSavedLoginsAuthFragmentToTurnOnSyncFragment()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `show status for existing account`() {
|
||||
every { accountManager.authenticatedAccount() } returns mockk()
|
||||
every { accountManager.accountNeedsReauth() } returns false
|
||||
createView()
|
||||
|
||||
verify { syncLoginsPreference.summary = "Off" }
|
||||
assertTrue(clickListener.captured.onPreferenceClick(syncLoginsPreference))
|
||||
|
||||
verify {
|
||||
navController.navigate(
|
||||
SavedLoginsAuthFragmentDirections.actionGlobalAccountSettingsFragment()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `show status for existing account with passwords`() {
|
||||
every { anyConstructed<SyncEnginesStorage>().getStatus() } returns mapOf(
|
||||
SyncEngine.Passwords to true
|
||||
)
|
||||
every { accountManager.authenticatedAccount() } returns mockk()
|
||||
every { accountManager.accountNeedsReauth() } returns false
|
||||
createView()
|
||||
|
||||
verify { syncLoginsPreference.summary = "On" }
|
||||
assertTrue(clickListener.captured.onPreferenceClick(syncLoginsPreference))
|
||||
|
||||
verify {
|
||||
navController.navigate(
|
||||
SavedLoginsAuthFragmentDirections.actionGlobalAccountSettingsFragment()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createView() = SyncLoginsPreferenceView(
|
||||
syncLoginsPreference,
|
||||
lifecycleOwner,
|
||||
accountManager,
|
||||
navController
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue