For #24855: Allow updating info for an existing address.

pull/543/head
mcarare 2 years ago committed by mergify[bot]
parent e5b0069791
commit 4369c0b920

@ -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<AddressEditorFragmentArgs>()
/**
* 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() {

@ -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()
}
}
}
}

@ -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
)
)
}
}

@ -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)
}
}

@ -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)
}
}
}

@ -1258,7 +1258,13 @@
<fragment
android:id="@+id/addressEditorFragment"
android:name="org.mozilla.fenix.settings.address.AddressEditorFragment"
android:label="@string/addresses_add_address" />
android:label="@string/addresses_add_address">
<argument
android:name="address"
android:defaultValue="@null"
app:argType="mozilla.components.concept.storage.Address"
app:nullable="true" />
</fragment>
<fragment
android:id="@+id/addressManagementFragment"
android:name="org.mozilla.fenix.settings.address.AddressManagementFragment"

@ -1546,6 +1546,8 @@
<string name="credit_cards_biometric_prompt_unlock_message">Unlock to use stored credit card information</string>
<!-- Title of the "Add address" screen -->
<string name="addresses_add_address">Add address</string>
<!-- Title of the "Edit address" screen -->
<string name="addresses_edit_address">Edit address</string>
<!-- Title of the "Manage addresses" screen -->
<string name="addresses_manage_addresses">Manage addresses</string>
<!-- The header for the full name of an address -->

@ -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())
}
}

@ -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()
}
}
}

@ -37,7 +37,9 @@ class DefaultAddressManagementControllerTest {
verify {
navController.navigate(
AddressManagementFragmentDirections
.actionAddressManagementFragmentToAddressEditorFragment()
.actionAddressManagementFragmentToAddressEditorFragment(
address = address
)
)
}
}

Loading…
Cancel
Save