From 4369c0b92075c995b4e30154679d77335cda4f82 Mon Sep 17 00:00:00 2001 From: mcarare Date: Fri, 29 Apr 2022 16:35:53 +0300 Subject: [PATCH] For #24855: Allow updating info for an existing address. --- .../settings/address/AddressEditorFragment.kt | 17 +++++- .../controller/AddressEditorController.kt | 15 +++++ .../controller/AddressManagementController.kt | 8 ++- .../interactor/AddressEditorInteractor.kt | 12 ++++ .../address/view/AddressEditorView.kt | 57 +++++++++++++------ app/src/main/res/navigation/nav_graph.xml | 8 ++- app/src/main/res/values/strings.xml | 2 + .../settings/address/AddressEditorViewTest.kt | 42 ++++++++++++++ .../DefaultAddressEditorControllerTest.kt | 17 ++++++ .../DefaultAddressManagementControllerTest.kt | 4 +- 10 files changed, 159 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/settings/address/AddressEditorFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/address/AddressEditorFragment.kt index 5f716afd9..7f4569d0e 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/address/AddressEditorFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/address/AddressEditorFragment.kt @@ -8,6 +8,7 @@ import android.os.Bundle import android.view.View import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController +import androidx.navigation.fragment.navArgs import mozilla.components.support.ktx.android.view.hideKeyboard import org.mozilla.fenix.R import org.mozilla.fenix.SecureFragment @@ -27,6 +28,14 @@ class AddressEditorFragment : SecureFragment(R.layout.fragment_address_editor) { private lateinit var addressEditorView: AddressEditorView private lateinit var interactor: AddressEditorInteractor + private val args by navArgs() + + /** + * Returns true if an existing address is being edited, and false otherwise. + */ + private val isEditing: Boolean + get() = args.address != null + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -42,13 +51,17 @@ class AddressEditorFragment : SecureFragment(R.layout.fragment_address_editor) { val binding = FragmentAddressEditorBinding.bind(view) - addressEditorView = AddressEditorView(binding, interactor) + addressEditorView = AddressEditorView(binding, interactor, args.address) addressEditorView.bind() } override fun onResume() { super.onResume() - showToolbar(getString(R.string.addresses_add_address)) + if (isEditing) { + showToolbar(getString(R.string.addresses_edit_address)) + } else { + showToolbar(getString(R.string.addresses_add_address)) + } } override fun onStop() { diff --git a/app/src/main/java/org/mozilla/fenix/settings/address/controller/AddressEditorController.kt b/app/src/main/java/org/mozilla/fenix/settings/address/controller/AddressEditorController.kt index 2e69e49c4..f7fe27223 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/address/controller/AddressEditorController.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/address/controller/AddressEditorController.kt @@ -28,6 +28,11 @@ interface AddressEditorController { * @see [AddressEditorInteractor.onSaveAddress] */ fun handleSaveAddress(addressFields: UpdatableAddressFields) + + /** + * @see [AddressEditorInteractor.onUpdateAddress] + */ + fun handleUpdateAddress(guid: String, addressFields: UpdatableAddressFields) } /** @@ -57,4 +62,14 @@ class DefaultAddressEditorController( } } } + + override fun handleUpdateAddress(guid: String, addressFields: UpdatableAddressFields) { + lifecycleScope.launch { + storage.updateAddress(guid, addressFields) + + lifecycleScope.launch(Dispatchers.Main) { + navController.popBackStack() + } + } + } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/address/controller/AddressManagementController.kt b/app/src/main/java/org/mozilla/fenix/settings/address/controller/AddressManagementController.kt index b7ef02c40..cbf87b532 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/address/controller/AddressManagementController.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/address/controller/AddressManagementController.kt @@ -37,17 +37,19 @@ class DefaultAddressManagementController( ) : AddressManagementController { override fun handleAddressClicked(address: Address) { - navigateToAddressEditor() + navigateToAddressEditor(address) } override fun handleAddAddressButtonClicked() { navigateToAddressEditor() } - private fun navigateToAddressEditor() { + private fun navigateToAddressEditor(address: Address? = null) { navController.navigate( AddressManagementFragmentDirections - .actionAddressManagementFragmentToAddressEditorFragment() + .actionAddressManagementFragmentToAddressEditorFragment( + address = address + ) ) } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/address/interactor/AddressEditorInteractor.kt b/app/src/main/java/org/mozilla/fenix/settings/address/interactor/AddressEditorInteractor.kt index 17c30ea95..942c0c72d 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/address/interactor/AddressEditorInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/address/interactor/AddressEditorInteractor.kt @@ -25,6 +25,14 @@ interface AddressEditorInteractor { * @param addressFields A [UpdatableAddressFields] record to add. */ fun onSaveAddress(addressFields: UpdatableAddressFields) + + /** + * Updates the provided address in the autofill storage. Called when a user + * taps on the update menu item or "Update" button. + * + * @param addressFields A [UpdatableAddressFields] record to add. + */ + fun onUpdateAddress(guid: String, addressFields: UpdatableAddressFields) } /** @@ -44,4 +52,8 @@ class DefaultAddressEditorInteractor( override fun onSaveAddress(addressFields: UpdatableAddressFields) { controller.handleSaveAddress(addressFields) } + + override fun onUpdateAddress(guid: String, addressFields: UpdatableAddressFields) { + controller.handleUpdateAddress(guid, addressFields) + } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/address/view/AddressEditorView.kt b/app/src/main/java/org/mozilla/fenix/settings/address/view/AddressEditorView.kt index fe2363b4f..0e627a01f 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/address/view/AddressEditorView.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/address/view/AddressEditorView.kt @@ -4,9 +4,15 @@ package org.mozilla.fenix.settings.address.view +import android.content.Context +import android.content.DialogInterface +import androidx.appcompat.app.AlertDialog +import androidx.core.view.isVisible +import mozilla.components.concept.storage.Address import mozilla.components.concept.storage.UpdatableAddressFields import mozilla.components.support.ktx.android.view.hideKeyboard import mozilla.components.support.ktx.android.view.showKeyboard +import org.mozilla.fenix.R import org.mozilla.fenix.databinding.FragmentAddressEditorBinding import org.mozilla.fenix.ext.placeCursorAtEnd import org.mozilla.fenix.settings.address.interactor.AddressEditorInteractor @@ -16,7 +22,8 @@ import org.mozilla.fenix.settings.address.interactor.AddressEditorInteractor */ class AddressEditorView( private val binding: FragmentAddressEditorBinding, - private val interactor: AddressEditorInteractor + private val interactor: AddressEditorInteractor, + private val address: Address? = null ) { /** @@ -36,26 +43,44 @@ class AddressEditorView( binding.saveButton.setOnClickListener { saveAddress() } + + address?.let { address -> + binding.emailInput.setText(address.email) + binding.phoneInput.setText(address.tel) + + binding.firstNameInput.setText(address.givenName) + binding.middleNameInput.setText(address.additionalName) + binding.lastNameInput.setText(address.familyName) + + binding.streetAddressInput.setText(address.streetAddress) + binding.cityInput.setText(address.addressLevel2) + binding.stateInput.setText(address.addressLevel1) + binding.zipInput.setText(address.postalCode) + } } internal fun saveAddress() { binding.root.hideKeyboard() - interactor.onSaveAddress( - UpdatableAddressFields( - givenName = binding.firstNameInput.text.toString(), - additionalName = binding.middleNameInput.text.toString(), - familyName = binding.lastNameInput.text.toString(), - organization = "", - streetAddress = binding.streetAddressInput.text.toString(), - addressLevel3 = "", - addressLevel2 = "", - addressLevel1 = "", - postalCode = binding.zipInput.text.toString(), - country = "", - tel = binding.phoneInput.text.toString(), - email = binding.emailInput.text.toString() - ) + val addressFields = UpdatableAddressFields( + givenName = binding.firstNameInput.text.toString(), + additionalName = binding.middleNameInput.text.toString(), + familyName = binding.lastNameInput.text.toString(), + organization = "", + streetAddress = binding.streetAddressInput.text.toString(), + addressLevel3 = "", + addressLevel2 = "", + addressLevel1 = "", + postalCode = binding.zipInput.text.toString(), + country = "", + tel = binding.phoneInput.text.toString(), + email = binding.emailInput.text.toString() ) + + if (address != null) { + interactor.onUpdateAddress(address.guid, addressFields) + } else { + interactor.onSaveAddress(addressFields) + } } } diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index c594faa2b..4d847f29f 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -1258,7 +1258,13 @@ + android:label="@string/addresses_add_address"> + + Unlock to use stored credit card information Add address + + Edit address Manage addresses diff --git a/app/src/test/java/org/mozilla/fenix/settings/address/AddressEditorViewTest.kt b/app/src/test/java/org/mozilla/fenix/settings/address/AddressEditorViewTest.kt index e57cbe081..b0811b93e 100644 --- a/app/src/test/java/org/mozilla/fenix/settings/address/AddressEditorViewTest.kt +++ b/app/src/test/java/org/mozilla/fenix/settings/address/AddressEditorViewTest.kt @@ -6,10 +6,13 @@ package org.mozilla.fenix.settings.address import android.view.LayoutInflater import android.view.View +import io.mockk.every import io.mockk.mockk import io.mockk.spyk import io.mockk.verify +import mozilla.components.concept.storage.Address import mozilla.components.support.test.robolectric.testContext +import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -26,12 +29,15 @@ class AddressEditorViewTest { private lateinit var interactor: AddressEditorInteractor private lateinit var addressEditorView: AddressEditorView private lateinit var binding: FragmentAddressEditorBinding + private lateinit var address: Address @Before fun setup() { view = LayoutInflater.from(testContext).inflate(R.layout.fragment_address_editor, null) binding = FragmentAddressEditorBinding.bind(view) interactor = mockk(relaxed = true) + address = mockk(relaxed = true) + every { address.guid } returns "123" addressEditorView = spyk(AddressEditorView(binding, interactor)) } @@ -44,4 +50,40 @@ class AddressEditorViewTest { verify { interactor.onCancelButtonClicked() } } + + @Test + fun `GIVEN an existing address WHEN editor is opened THEN the form fields are correctly mapped to the address fields`() { + val address = Address( + guid = "123", + givenName = "Given", + additionalName = "Additional", + familyName = "Family", + organization = "Organization", + streetAddress = "Street", + addressLevel3 = "Suburb", + addressLevel2 = "City", + addressLevel1 = "State", + postalCode = "PostalCode", + country = "Country", + tel = "Telephone", + email = "email@mozilla.com", + timeCreated = 0L, + timeLastUsed = 1L, + timeLastModified = 1L, + timesUsed = 2L + ) + + val addressEditorView = spyk(AddressEditorView(binding, interactor, address)) + addressEditorView.bind() + + assertEquals("PostalCode", binding.zipInput.text.toString()) + assertEquals("State", binding.stateInput.text.toString()) + assertEquals("City", binding.cityInput.text.toString()) + assertEquals("Street", binding.streetAddressInput.text.toString()) + assertEquals("Family", binding.lastNameInput.text.toString()) + assertEquals("Given", binding.firstNameInput.text.toString()) + assertEquals("Additional", binding.middleNameInput.text.toString()) + assertEquals("email@mozilla.com", binding.emailInput.text.toString()) + assertEquals("Telephone", binding.phoneInput.text.toString()) + } } diff --git a/app/src/test/java/org/mozilla/fenix/settings/address/controller/DefaultAddressEditorControllerTest.kt b/app/src/test/java/org/mozilla/fenix/settings/address/controller/DefaultAddressEditorControllerTest.kt index 10fa0059b..aad0d4c1f 100644 --- a/app/src/test/java/org/mozilla/fenix/settings/address/controller/DefaultAddressEditorControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/settings/address/controller/DefaultAddressEditorControllerTest.kt @@ -6,11 +6,14 @@ package org.mozilla.fenix.settings.address.controller import androidx.navigation.NavController import io.mockk.coVerify +import io.mockk.coVerifySequence +import io.mockk.every import io.mockk.mockk import io.mockk.spyk import io.mockk.verify import kotlinx.coroutines.test.TestCoroutineScope import kotlinx.coroutines.test.runBlockingTest +import mozilla.components.concept.storage.Address import mozilla.components.concept.storage.UpdatableAddressFields import mozilla.components.service.sync.autofill.AutofillCreditCardsAddressesStorage import mozilla.components.support.test.rule.MainCoroutineRule @@ -73,4 +76,18 @@ class DefaultAddressEditorControllerTest { navController.popBackStack() } } + + @Test + fun `GIVEN an existing address record WHEN save address is called THEN update the address record to storage`() = runBlockingTest { + val address: Address = mockk() + val addressFields: UpdatableAddressFields = mockk() + every { address.guid } returns "123" + + controller.handleUpdateAddress(address.guid, addressFields) + + coVerifySequence { + storage.updateAddress("123", addressFields) + navController.popBackStack() + } + } } diff --git a/app/src/test/java/org/mozilla/fenix/settings/address/controller/DefaultAddressManagementControllerTest.kt b/app/src/test/java/org/mozilla/fenix/settings/address/controller/DefaultAddressManagementControllerTest.kt index d6a806a94..70d24b7c8 100644 --- a/app/src/test/java/org/mozilla/fenix/settings/address/controller/DefaultAddressManagementControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/settings/address/controller/DefaultAddressManagementControllerTest.kt @@ -37,7 +37,9 @@ class DefaultAddressManagementControllerTest { verify { navController.navigate( AddressManagementFragmentDirections - .actionAddressManagementFragmentToAddressEditorFragment() + .actionAddressManagementFragmentToAddressEditorFragment( + address = address + ) ) } }