For #24856 - Toggle the "Manage addresses" and "Add address" preference label depending on whether there are saved addresses
This commit is contained in:
parent
d1c43761eb
commit
aff4c03d53
|
@ -4,6 +4,7 @@
|
|||
|
||||
package org.mozilla.fenix.settings.autofill
|
||||
|
||||
import mozilla.components.concept.storage.Address
|
||||
import mozilla.components.concept.storage.CreditCard
|
||||
import mozilla.components.lib.state.Action
|
||||
import mozilla.components.lib.state.State
|
||||
|
@ -18,14 +19,16 @@ class AutofillFragmentStore(initialState: AutofillFragmentState) :
|
|||
)
|
||||
|
||||
/**
|
||||
* The state for [CreditCardsManagementFragment].
|
||||
* The state used for managing autofill data.
|
||||
*
|
||||
* @property addresses The list of [Address]es to display in the address list.
|
||||
* @property creditCards The list of [CreditCard]s to display in the credit card list.
|
||||
* @property isLoading True if the credit cards are still being loaded from storage,
|
||||
* @property isLoading True if the addresses or credit cards are still being loaded from storage,
|
||||
* otherwise false.
|
||||
*/
|
||||
data class AutofillFragmentState(
|
||||
val creditCards: List<CreditCard>,
|
||||
val addresses: List<Address> = emptyList(),
|
||||
val creditCards: List<CreditCard> = emptyList(),
|
||||
val isLoading: Boolean = true
|
||||
) : State
|
||||
|
||||
|
@ -34,6 +37,13 @@ data class AutofillFragmentState(
|
|||
* through the [autofillFragmentStateReducer].
|
||||
*/
|
||||
sealed class AutofillAction : Action {
|
||||
/**
|
||||
* Updates the list of addresses with the provided [addresses].
|
||||
*
|
||||
* @param addresses The list of [Address]es to display in the address list.
|
||||
*/
|
||||
data class UpdateAddresses(val addresses: List<Address>) : AutofillAction()
|
||||
|
||||
/**
|
||||
* Updates the list of credit cards with the provided [creditCards].
|
||||
*
|
||||
|
@ -54,6 +64,12 @@ private fun autofillFragmentStateReducer(
|
|||
action: AutofillAction
|
||||
): AutofillFragmentState {
|
||||
return when (action) {
|
||||
is AutofillAction.UpdateAddresses -> {
|
||||
state.copy(
|
||||
addresses = action.addresses,
|
||||
isLoading = false
|
||||
)
|
||||
}
|
||||
is AutofillAction.UpdateCreditCards -> {
|
||||
state.copy(
|
||||
creditCards = action.creditCards,
|
||||
|
|
|
@ -25,6 +25,7 @@ import kotlinx.coroutines.delay
|
|||
import kotlinx.coroutines.launch
|
||||
import mozilla.components.lib.state.ext.consumeFrom
|
||||
import mozilla.components.service.fxa.SyncEngine
|
||||
import mozilla.components.service.sync.autofill.AutofillCreditCardsAddressesStorage
|
||||
import org.mozilla.fenix.NavGraphDirections
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.StoreProvider
|
||||
|
@ -46,7 +47,8 @@ import org.mozilla.fenix.settings.requirePreference
|
|||
class AutofillSettingFragment : BiometricPromptPreferenceFragment() {
|
||||
|
||||
private lateinit var store: AutofillFragmentStore
|
||||
private var isCreditCardsListLoaded: Boolean = false
|
||||
|
||||
private var isAutofillStateLoaded: Boolean = false
|
||||
|
||||
/**
|
||||
* List of preferences to be enabled or disabled during authentication.
|
||||
|
@ -73,9 +75,9 @@ class AutofillSettingFragment : BiometricPromptPreferenceFragment() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
store = StoreProvider.get(this) {
|
||||
AutofillFragmentStore(AutofillFragmentState(creditCards = emptyList()))
|
||||
AutofillFragmentStore(AutofillFragmentState())
|
||||
}
|
||||
loadCreditCards()
|
||||
loadAutofillState()
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
|
@ -99,13 +101,17 @@ class AutofillSettingFragment : BiometricPromptPreferenceFragment() {
|
|||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
loadCreditCards()
|
||||
loadAutofillState()
|
||||
return super.onCreateView(inflater, container, savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
consumeFrom(store) { state ->
|
||||
if (requireComponents.settings.addressFeature) {
|
||||
updateAddressPreference(state.addresses.isNotEmpty())
|
||||
}
|
||||
updateCardManagementPreference(state.creditCards.isNotEmpty(), findNavController())
|
||||
}
|
||||
|
||||
|
@ -114,7 +120,7 @@ class AutofillSettingFragment : BiometricPromptPreferenceFragment() {
|
|||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
isCreditCardsListLoaded = false
|
||||
isAutofillStateLoaded = false
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
@ -150,6 +156,25 @@ class AutofillSettingFragment : BiometricPromptPreferenceFragment() {
|
|||
togglePrefsEnabled(creditCardPreferences, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates preferences visibility depending on addresses being already saved or not.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
internal fun updateAddressPreference(hasAddresses: Boolean) {
|
||||
val manageAddressesPreference =
|
||||
requirePreference<Preference>(R.string.pref_key_addresses_manage_addresses)
|
||||
|
||||
if (hasAddresses) {
|
||||
manageAddressesPreference.icon = null
|
||||
manageAddressesPreference.title =
|
||||
getString(R.string.preferences_addresses_manage_addresses)
|
||||
} else {
|
||||
manageAddressesPreference.setIcon(R.drawable.ic_new)
|
||||
manageAddressesPreference.title =
|
||||
getString(R.string.preferences_addresses_add_address)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates preferences visibility depending on credit cards being already saved or not.
|
||||
*/
|
||||
|
@ -185,22 +210,25 @@ class AutofillSettingFragment : BiometricPromptPreferenceFragment() {
|
|||
}
|
||||
|
||||
/**
|
||||
* Fetches all the credit cards from autofillStorage and updates the [AutofillFragmentState]
|
||||
* with the list of credit cards.
|
||||
* Fetches all the addresses and credit cards from [AutofillCreditCardsAddressesStorage] and
|
||||
* updates the [AutofillFragmentState].
|
||||
*/
|
||||
private fun loadCreditCards() {
|
||||
if (isCreditCardsListLoaded) {
|
||||
private fun loadAutofillState() {
|
||||
if (isAutofillStateLoaded) {
|
||||
return
|
||||
}
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val addresses = requireComponents.core.autofillStorage.getAllAddresses()
|
||||
val creditCards = requireComponents.core.autofillStorage.getAllCreditCards()
|
||||
|
||||
lifecycleScope.launch(Dispatchers.Main) {
|
||||
store.dispatch(AutofillAction.UpdateAddresses(addresses))
|
||||
store.dispatch(AutofillAction.UpdateCreditCards(creditCards))
|
||||
}
|
||||
}
|
||||
|
||||
isCreditCardsListLoaded = true
|
||||
isAutofillStateLoaded = true
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -45,7 +45,7 @@ class CreditCardsManagementFragment : SecureFragment() {
|
|||
val view = inflater.inflate(CreditCardsManagementView.LAYOUT_ID, container, false)
|
||||
|
||||
store = StoreProvider.get(this) {
|
||||
AutofillFragmentStore(AutofillFragmentState(creditCards = emptyList()))
|
||||
AutofillFragmentStore(AutofillFragmentState())
|
||||
}
|
||||
|
||||
interactor = DefaultCreditCardsManagementInteractor(
|
||||
|
|
|
@ -1499,6 +1499,8 @@
|
|||
<string name="preferences_credit_cards_add_credit_card">Add credit card</string>
|
||||
<!-- Preference option for managing saved credit cards -->
|
||||
<string name="preferences_credit_cards_manage_saved_cards">Manage saved cards</string>
|
||||
<!-- Preference option for adding an address -->
|
||||
<string name="preferences_addresses_add_address">Add address</string>
|
||||
<!-- Preference option for managing saved addresses -->
|
||||
<string name="preferences_addresses_manage_addresses">Manage addresses</string>
|
||||
<!-- Title of the "Add card" screen -->
|
||||
|
|
|
@ -6,6 +6,7 @@ package org.mozilla.fenix.settings.autofill
|
|||
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import mozilla.components.concept.storage.Address
|
||||
import mozilla.components.concept.storage.CreditCard
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
|
@ -20,7 +21,7 @@ class AutofillFragmentStoreTest {
|
|||
|
||||
@Before
|
||||
fun setup() {
|
||||
state = AutofillFragmentState(creditCards = emptyList())
|
||||
state = AutofillFragmentState()
|
||||
store = AutofillFragmentStore(state)
|
||||
}
|
||||
|
||||
|
@ -34,4 +35,15 @@ class AutofillFragmentStoreTest {
|
|||
assertEquals(creditCards, store.state.creditCards)
|
||||
assertFalse(store.state.isLoading)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN a list of addresses WHEN update addresses action is dispatched THEN addresses state is updated`() = runBlocking {
|
||||
assertTrue(store.state.isLoading)
|
||||
|
||||
val addresses: List<Address> = listOf(mockk(), mockk())
|
||||
store.dispatch(AutofillAction.UpdateAddresses(addresses)).join()
|
||||
|
||||
assertEquals(addresses, store.state.addresses)
|
||||
assertFalse(store.state.isLoading)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import io.mockk.every
|
|||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import kotlinx.coroutines.test.TestCoroutineDispatcher
|
||||
import mozilla.components.concept.storage.Address
|
||||
import mozilla.components.concept.storage.CreditCard
|
||||
import mozilla.components.support.test.robolectric.testContext
|
||||
import org.junit.Assert.assertEquals
|
||||
|
@ -35,6 +36,8 @@ class AutofillSettingFragmentTest {
|
|||
@Before
|
||||
fun setUp() {
|
||||
every { testContext.components.settings } returns mockk(relaxed = true)
|
||||
every { testContext.components.settings.addressFeature } returns true
|
||||
every { testContext.components.settings.shouldAutofillCreditCardDetails } returns true
|
||||
|
||||
autofillSettingFragment = AutofillSettingFragment()
|
||||
|
||||
|
@ -80,7 +83,7 @@ class AutofillSettingFragmentTest {
|
|||
AutofillSettingFragmentDirections
|
||||
.actionAutofillSettingFragmentToCreditCardEditorFragment()
|
||||
|
||||
val state = AutofillFragmentState(creditCards = emptyList())
|
||||
val state = AutofillFragmentState()
|
||||
val store = AutofillFragmentStore(state)
|
||||
|
||||
autofillSettingFragment.updateCardManagementPreference(
|
||||
|
@ -95,4 +98,44 @@ class AutofillSettingFragmentTest {
|
|||
|
||||
verify { navController.navigate(directions) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN the list of addresses is not empty WHEN fragment is displayed THEN the manage addresses preference label is 'Manage addresses'`() {
|
||||
val preferenceTitle =
|
||||
testContext.getString(R.string.preferences_addresses_manage_addresses)
|
||||
val manageCardsPreference = autofillSettingFragment.findPreference<Preference>(
|
||||
autofillSettingFragment.getPreferenceKey(R.string.pref_key_addresses_manage_addresses)
|
||||
)
|
||||
|
||||
val addresses: List<Address> = listOf(mockk(), mockk())
|
||||
|
||||
val state = AutofillFragmentState(addresses = addresses)
|
||||
val store = AutofillFragmentStore(state)
|
||||
|
||||
autofillSettingFragment.updateAddressPreference(
|
||||
store.state.addresses.isNotEmpty()
|
||||
)
|
||||
|
||||
assertNull(manageCardsPreference?.icon)
|
||||
assertEquals(preferenceTitle, manageCardsPreference?.title)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN the list of addresses is empty WHEN fragment is displayed THEN the manage addresses preference label is 'Add address'`() {
|
||||
val preferenceTitle =
|
||||
testContext.getString(R.string.preferences_addresses_add_address)
|
||||
val manageCardsPreference = autofillSettingFragment.findPreference<Preference>(
|
||||
autofillSettingFragment.getPreferenceKey(R.string.pref_key_addresses_manage_addresses)
|
||||
)
|
||||
|
||||
val state = AutofillFragmentState()
|
||||
val store = AutofillFragmentStore(state)
|
||||
|
||||
autofillSettingFragment.updateAddressPreference(
|
||||
store.state.addresses.isNotEmpty()
|
||||
)
|
||||
|
||||
assertNotNull(manageCardsPreference?.icon)
|
||||
assertEquals(preferenceTitle, manageCardsPreference?.title)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ class CreditCardsManagementViewTest {
|
|||
|
||||
@Test
|
||||
fun testUpdate() {
|
||||
creditCardsView.update(AutofillFragmentState(creditCards = emptyList()))
|
||||
creditCardsView.update(AutofillFragmentState())
|
||||
|
||||
assertTrue(componentCreditCardsBinding.progressBar.isVisible)
|
||||
assertFalse(componentCreditCardsBinding.creditCardsList.isVisible)
|
||||
|
|
Loading…
Reference in New Issue