For #18265 - [Add card] Integrate the credit card storage and handle adding a new credit card (#18719)

upstream-sync
Gabriel Luong 3 years ago committed by GitHub
parent 6e5b4b3ce6
commit 1008ca2b4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -5,13 +5,22 @@
package org.mozilla.fenix.settings.creditcards
import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.widget.ArrayAdapter
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import kotlinx.android.synthetic.main.fragment_credit_card_editor.view.*
import kotlinx.android.synthetic.main.fragment_credit_card_editor.*
import mozilla.components.concept.storage.UpdatableCreditCardFields
import mozilla.components.support.ktx.android.view.hideKeyboard
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.settings.creditcards.controller.CreditCardEditorController
import org.mozilla.fenix.settings.creditcards.controller.DefaultCreditCardEditorController
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
@ -21,23 +30,49 @@ import java.util.Locale
*/
class CreditCardEditorFragment : Fragment(R.layout.fragment_credit_card_editor) {
private lateinit var controller: CreditCardEditorController
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
showToolbar(getString(R.string.credit_cards_add_card))
setupButtonClickListeners(view)
setHasOptionsMenu(true)
setupButtonClickListeners()
setupExpiryMonthDropDown(view)
setupExpiryYearDropDown(view)
controller = DefaultCreditCardEditorController(
storage = requireContext().components.core.autofillStorage,
lifecycleScope = lifecycleScope,
navController = findNavController()
)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.credit_card_editor, menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
R.id.save_credit_card_button -> {
saveCreditCard()
true
}
else -> false
}
/**
* Setup the all button click listeners in the credit card editor.
*/
private fun setupButtonClickListeners(view: View) {
view.cancel_button.setOnClickListener {
private fun setupButtonClickListeners() {
cancel_button.setOnClickListener {
findNavController().popBackStack()
}
save_button.setOnClickListener {
saveCreditCard()
}
}
/**
@ -57,7 +92,7 @@ class CreditCardEditorFragment : Fragment(R.layout.fragment_credit_card_editor)
adapter.add(dateFormat.format(calendar.time))
}
view.expiry_month_drop_down.adapter = adapter
expiry_month_drop_down.adapter = adapter
}
/**
@ -74,7 +109,25 @@ class CreditCardEditorFragment : Fragment(R.layout.fragment_credit_card_editor)
adapter.add(year.toString())
}
view.expiry_year_drop_down.adapter = adapter
expiry_year_drop_down.adapter = adapter
}
/**
* Helper function called by the the "Save" button and menu item to save a new credit card
* from the entered credit card fields.
*/
private fun saveCreditCard() {
view?.hideKeyboard()
controller.handleSaveCreditCard(
UpdatableCreditCardFields(
billingName = name_on_card_input.text.toString(),
cardNumber = card_number_input.text.toString(),
expiryMonth = (expiry_month_drop_down.selectedItemPosition + 1).toLong(),
expiryYear = expiry_year_drop_down.selectedItem.toString().toLong(),
cardType = "amex"
)
)
}
companion object {

@ -0,0 +1,55 @@
/* 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.creditcards.controller
import androidx.navigation.NavController
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import mozilla.components.concept.storage.UpdatableCreditCardFields
import mozilla.components.service.sync.autofill.AutofillCreditCardsAddressesStorage
/**
* [CreditCardEditorFragment] controller. An interface that handles the view manipulation of the
* credit card editor.
*/
interface CreditCardEditorController {
/**
* Saves the provided credit card field into the credit card storage. Called when a user
* taps on the save menu item or "Save" button.
*
* @param creditCardFields A [UpdatableCreditCardFields] record to add.
*/
fun handleSaveCreditCard(creditCardFields: UpdatableCreditCardFields)
}
/**
* The default implementation of [CreditCardEditorController].
*
* @param storage An instance of the [AutofillCreditCardsAddressesStorage] for adding and retrieving
* credit cards.
* @param lifecycleScope [CoroutineScope] scope to launch coroutines.
* @param navController [NavController] used for navigation.
* @param ioDispatcher [CoroutineDispatcher] used for executing async tasks. Defaults to [Dispatchers.IO].
*/
class DefaultCreditCardEditorController(
private val storage: AutofillCreditCardsAddressesStorage,
private val lifecycleScope: CoroutineScope,
private val navController: NavController,
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) : CreditCardEditorController {
override fun handleSaveCreditCard(creditCardFields: UpdatableCreditCardFields) {
lifecycleScope.launch(ioDispatcher) {
storage.addCreditCard(creditCardFields)
lifecycleScope.launch(Dispatchers.Main) {
navController.popBackStack()
}
}
}
}

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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/. -->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/save_credit_card_button"
android:icon="@drawable/mozac_ic_check"
android:title="@string/save"
app:iconTint="?primaryText"
app:showAsAction="ifRoom" />
</menu>

@ -0,0 +1,73 @@
/* 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.creditcards
import androidx.navigation.NavController
import io.mockk.coVerify
import io.mockk.mockk
import io.mockk.spyk
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestCoroutineDispatcher
import kotlinx.coroutines.test.TestCoroutineScope
import kotlinx.coroutines.test.runBlockingTest
import mozilla.components.concept.storage.UpdatableCreditCardFields
import mozilla.components.service.sync.autofill.AutofillCreditCardsAddressesStorage
import mozilla.components.support.test.rule.MainCoroutineRule
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.settings.creditcards.controller.DefaultCreditCardEditorController
@ExperimentalCoroutinesApi
class DefaultCreditCardEditorControllerTest {
private val storage: AutofillCreditCardsAddressesStorage = mockk(relaxed = true)
private val navController: NavController = mockk(relaxed = true)
private val testCoroutineScope = TestCoroutineScope()
private val testDispatcher = TestCoroutineDispatcher()
private lateinit var controller: DefaultCreditCardEditorController
@get:Rule
val coroutinesTestRule = MainCoroutineRule(testDispatcher)
@Before
fun setup() {
controller = spyk(
DefaultCreditCardEditorController(
storage = storage,
lifecycleScope = testCoroutineScope,
navController = navController,
ioDispatcher = testDispatcher
)
)
}
@After
fun cleanUp() {
testCoroutineScope.cleanupTestCoroutines()
testDispatcher.cleanupTestCoroutines()
}
@Test
fun handleSaveCreditCard() = testCoroutineScope.runBlockingTest {
val creditCardFields = UpdatableCreditCardFields(
billingName = "Banana Apple",
cardNumber = "4111111111111112",
expiryMonth = 1,
expiryYear = 2030,
cardType = "discover"
)
controller.handleSaveCreditCard(creditCardFields)
coVerify {
storage.addCreditCard(creditCardFields)
navController.popBackStack()
}
}
}
Loading…
Cancel
Save