For #18272 - [Edit card] Display a saved card information in the Edit card screen (#18884)

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

@ -7,6 +7,7 @@ package org.mozilla.fenix.ext
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.text.Editable
import android.util.Patterns
import android.webkit.URLUtil
import androidx.core.net.toUri
@ -114,6 +115,11 @@ fun String.simplifiedUrl(): String {
return afterScheme
}
/**
* Returns an [Editable] for the provided string.
*/
fun String.toEditable(): Editable = Editable.Factory.getInstance().newEditable(this)
suspend fun bitmapForUrl(url: String, client: Client): Bitmap? = withContext(Dispatchers.IO) {
// Code below will cache it in Gecko's cache, which ensures that as long as we've fetched it once,
// we will be able to display this avatar as long as the cache isn't purged (e.g. via 'clear user data').

@ -9,45 +9,58 @@ 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 androidx.navigation.fragment.navArgs
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
import org.mozilla.fenix.settings.creditcards.interactor.CreditCardEditorInteractor
import org.mozilla.fenix.settings.creditcards.interactor.DefaultCreditCardEditorInteractor
import org.mozilla.fenix.settings.creditcards.view.CreditCardEditorView
/**
* Display a credit card editor for adding and editing a credit card.
*/
class CreditCardEditorFragment : Fragment(R.layout.fragment_credit_card_editor) {
private lateinit var controller: CreditCardEditorController
private val args by navArgs<CreditCardEditorFragmentArgs>()
/**
* Returns true if a credit card is being edited, and false otherwise.
*/
private val isEditing: Boolean
get() = args.creditCard != null
private lateinit var interactor: CreditCardEditorInteractor
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
showToolbar(getString(R.string.credit_cards_add_card))
setHasOptionsMenu(true)
setupButtonClickListeners()
setupExpiryMonthDropDown(view)
setupExpiryYearDropDown(view)
if (!isEditing) {
showToolbar(getString(R.string.credit_cards_add_card))
} else {
showToolbar(getString(R.string.credit_cards_edit_card))
}
controller = DefaultCreditCardEditorController(
storage = requireContext().components.core.autofillStorage,
lifecycleScope = lifecycleScope,
navController = findNavController()
interactor = DefaultCreditCardEditorInteractor(
controller = DefaultCreditCardEditorController(
storage = requireContext().components.core.autofillStorage,
lifecycleScope = lifecycleScope,
navController = findNavController()
)
)
val creditCardEditorState =
args.creditCard?.toCreditCardEditorState() ?: getInitialCreditCardEditorState()
CreditCardEditorView(view, interactor).bind(creditCardEditorState)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
@ -62,56 +75,6 @@ class CreditCardEditorFragment : Fragment(R.layout.fragment_credit_card_editor)
else -> false
}
/**
* Setup the all button click listeners in the credit card editor.
*/
private fun setupButtonClickListeners() {
cancel_button.setOnClickListener {
findNavController().popBackStack()
}
save_button.setOnClickListener {
saveCreditCard()
}
}
/**
* Setup the expiry month dropdown by formatting and populating it with the months in a calendar
* year.
*/
private fun setupExpiryMonthDropDown(view: View) {
val adapter =
ArrayAdapter<String>(view.context, android.R.layout.simple_spinner_dropdown_item)
val dateFormat = SimpleDateFormat("MMMM (MM)", Locale.getDefault())
val calendar = Calendar.getInstance()
calendar.set(Calendar.DAY_OF_MONTH, 1)
for (month in 0..NUMBER_OF_MONTHS) {
calendar.set(Calendar.MONTH, month)
adapter.add(dateFormat.format(calendar.time))
}
expiry_month_drop_down.adapter = adapter
}
/**
* Setup the expiry year dropdown with the latest 10 years.
*/
private fun setupExpiryYearDropDown(view: View) {
val adapter =
ArrayAdapter<String>(view.context, android.R.layout.simple_spinner_dropdown_item)
val calendar = Calendar.getInstance()
val currentYear = calendar.get(Calendar.YEAR)
for (year in currentYear until currentYear + NUMBER_OF_YEARS_TO_SHOW) {
adapter.add(year.toString())
}
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.
@ -119,7 +82,7 @@ class CreditCardEditorFragment : Fragment(R.layout.fragment_credit_card_editor)
private fun saveCreditCard() {
view?.hideKeyboard()
controller.handleSaveCreditCard(
interactor.onSaveButtonClicked(
UpdatableCreditCardFields(
billingName = name_on_card_input.text.toString(),
cardNumber = card_number_input.text.toString(),
@ -131,10 +94,7 @@ class CreditCardEditorFragment : Fragment(R.layout.fragment_credit_card_editor)
}
companion object {
// Number of months in a year (0-indexed).
private const val NUMBER_OF_MONTHS = 11
// Number of years to show in the expiry year dropdown.
private const val NUMBER_OF_YEARS_TO_SHOW = 10
const val NUMBER_OF_YEARS_TO_SHOW = 10
}
}

@ -0,0 +1,58 @@
/* 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 mozilla.components.concept.storage.CreditCard
import org.mozilla.fenix.settings.creditcards.CreditCardEditorFragment.Companion.NUMBER_OF_YEARS_TO_SHOW
import java.util.Calendar
/**
* The state for the [CreditCardEditorFragment].
*
* @property billingName The credit card billing name to display.
* @property cardNumber The credit card number to display.
* @property expiryMonth The selected credit card expiry month.
* @property expiryYears The range of expiry years to display.
* @property isEditing Whether or not the credit is being edited.
*/
data class CreditCardEditorState(
val billingName: String = "",
val cardNumber: String = "",
val expiryMonth: Int = 1,
val expiryYears: Pair<Int, Int>,
val isEditing: Boolean = false
)
/**
* Returns a [CreditCardEditorState] from the given [CreditCard].
*/
fun CreditCard.toCreditCardEditorState(): CreditCardEditorState {
val startYear = expiryYear.toInt()
val endYear = startYear + NUMBER_OF_YEARS_TO_SHOW
return CreditCardEditorState(
billingName = billingName,
cardNumber = cardNumber,
expiryMonth = expiryMonth.toInt(),
expiryYears = Pair(startYear, endYear),
isEditing = true
)
}
/**
* Returns the initial credit editor state if no credit card is provided.
*
* @return an empty [CreditCardEditorState] with a range of expiry years based on the latest
* 10 years.
*/
fun getInitialCreditCardEditorState(): CreditCardEditorState {
val calendar = Calendar.getInstance()
val startYear = calendar.get(Calendar.YEAR)
val endYear = startYear + NUMBER_OF_YEARS_TO_SHOW
return CreditCardEditorState(
expiryYears = Pair(startYear, endYear)
)
}

@ -19,10 +19,12 @@ import mozilla.components.service.sync.autofill.AutofillCreditCardsAddressesStor
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.
* @see [CreditCardEditorInteractor.onCancelButtonClicked]
*/
fun handleCancelButtonClicked()
/**
* @see [CreditCardEditorInteractor.onSaveButtonClicked]
*/
fun handleSaveCreditCard(creditCardFields: UpdatableCreditCardFields)
}
@ -43,6 +45,10 @@ class DefaultCreditCardEditorController(
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) : CreditCardEditorController {
override fun handleCancelButtonClicked() {
navController.popBackStack()
}
override fun handleSaveCreditCard(creditCardFields: UpdatableCreditCardFields) {
lifecycleScope.launch(ioDispatcher) {
storage.addCreditCard(creditCardFields)

@ -5,6 +5,7 @@
package org.mozilla.fenix.settings.creditcards.controller
import androidx.navigation.NavController
import mozilla.components.concept.storage.CreditCard
import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
import org.mozilla.fenix.settings.creditcards.CreditCardsManagementFragmentDirections
@ -17,7 +18,7 @@ interface CreditCardsManagementController {
/**
* @see [CreditCardsManagementInteractor.onSelectCreditCard]
*/
fun handleCreditCardClicked()
fun handleCreditCardClicked(creditCard: CreditCard)
}
/**
@ -27,10 +28,12 @@ class DefaultCreditCardsManagementController(
private val navController: NavController
) : CreditCardsManagementController {
override fun handleCreditCardClicked() {
override fun handleCreditCardClicked(creditCard: CreditCard) {
navController.navigateBlockingForAsyncNavGraph(
CreditCardsManagementFragmentDirections
.actionCreditCardsManagementFragmentToCreditCardEditorFragment()
.actionCreditCardsManagementFragmentToCreditCardEditorFragment(
creditCard = creditCard
)
)
}
}

@ -0,0 +1,47 @@
/* 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.interactor
import mozilla.components.concept.storage.UpdatableCreditCardFields
import org.mozilla.fenix.settings.creditcards.controller.CreditCardEditorController
/**
* Interface for the credit card editor Interactor.
*/
interface CreditCardEditorInteractor {
/**
* Navigates back to the credit card preference settings. Called when a user taps on the
* "Cancel" button.
*/
fun onCancelButtonClicked()
/**
* 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 onSaveButtonClicked(creditCardFields: UpdatableCreditCardFields)
}
/**
* The default implementation of [CreditCardEditorInteractor].
*
* @param controller An instance of [CreditCardEditorController] which will be delegated for all
* user interactions.
*/
class DefaultCreditCardEditorInteractor(
private val controller: CreditCardEditorController
) : CreditCardEditorInteractor {
override fun onCancelButtonClicked() {
controller.handleCancelButtonClicked()
}
override fun onSaveButtonClicked(creditCardFields: UpdatableCreditCardFields) {
controller.handleSaveCreditCard(creditCardFields)
}
}

@ -4,6 +4,7 @@
package org.mozilla.fenix.settings.creditcards.interactor
import mozilla.components.concept.storage.CreditCard
import org.mozilla.fenix.settings.creditcards.controller.CreditCardsManagementController
/**
@ -14,18 +15,23 @@ interface CreditCardsManagementInteractor {
/**
* Navigates to the credit card editor to edit the selected credit card. Called when a user
* taps on a credit card item.
*
* @param creditCard The selected [CreditCard] to edit.
*/
fun onSelectCreditCard()
fun onSelectCreditCard(creditCard: CreditCard)
}
/**
* The default implementation of [CreditCardEditorInteractor]
* The default implementation of [CreditCardsManagementInteractor].
*
* @param controller An instance of [CreditCardsManagementController] which will be delegated for
* all user interactions.
*/
class DefaultCreditCardsManagementInteractor(
private val controller: CreditCardsManagementController
) : CreditCardsManagementInteractor {
override fun onSelectCreditCard() {
controller.handleCreditCardClicked()
override fun onSelectCreditCard(creditCard: CreditCard) {
controller.handleCreditCardClicked(creditCard)
}
}

@ -0,0 +1,111 @@
/* 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.view
import android.R
import android.view.View
import android.widget.ArrayAdapter
import kotlinx.android.extensions.LayoutContainer
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.ext.toEditable
import org.mozilla.fenix.settings.creditcards.CreditCardEditorState
import org.mozilla.fenix.settings.creditcards.interactor.CreditCardEditorInteractor
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
/**
* Shows a credit card editor for adding or updating a credit card.
*/
class CreditCardEditorView(
override val containerView: View,
private val interactor: CreditCardEditorInteractor
) : LayoutContainer {
/**
* Binds the given [CreditCardEditorState] in the [CreditCardEditorFragment].
*/
fun bind(state: CreditCardEditorState) {
cancel_button.setOnClickListener {
interactor.onCancelButtonClicked()
}
save_button.setOnClickListener {
saveCreditCard()
}
card_number_input.text = state.cardNumber.toEditable()
name_on_card_input.text = state.billingName.toEditable()
bindExpiryMonthDropDown(state.expiryMonth)
bindExpiryYearDropDown(state.expiryYears)
}
/**
* Setup the expiry month dropdown by formatting and populating it with the months in a calendar
* year, and set the selection to the provided expiry month.
*
* @param expiryMonth The selected credit card expiry month to display.
*/
private fun bindExpiryMonthDropDown(expiryMonth: Int) {
val adapter =
ArrayAdapter<String>(containerView.context, R.layout.simple_spinner_dropdown_item)
val dateFormat = SimpleDateFormat("MMMM (MM)", Locale.getDefault())
val calendar = Calendar.getInstance()
calendar.set(Calendar.DAY_OF_MONTH, 1)
for (month in 0..NUMBER_OF_MONTHS) {
calendar.set(Calendar.MONTH, month)
adapter.add(dateFormat.format(calendar.time))
}
expiry_month_drop_down.adapter = adapter
expiry_month_drop_down.setSelection(expiryMonth - 1)
}
/**
* Setup the expiry year dropdown with the range specified by the provided expiryYears
*
* @param expiryYears A range specifying the start and end year to display in the expiry year
* dropdown.
*/
private fun bindExpiryYearDropDown(expiryYears: Pair<Int, Int>) {
val adapter =
ArrayAdapter<String>(containerView.context, R.layout.simple_spinner_dropdown_item)
val (startYear, endYear) = expiryYears
for (year in startYear until endYear) {
adapter.add(year.toString())
}
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() {
containerView.hideKeyboard()
interactor.onSaveButtonClicked(
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 {
// Number of months in a year (0-indexed).
const val NUMBER_OF_MONTHS = 11
}
}

@ -28,7 +28,7 @@ class CreditCardItemViewHolder(
bindCreditCardExpiryDate(creditCard)
itemView.setOnClickListener {
interactor.onSelectCreditCard()
interactor.onSelectCreditCard(creditCard)
}
}

@ -30,6 +30,7 @@ import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.redirectToReAuth
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.ext.toEditable
import org.mozilla.fenix.settings.logins.LoginsAction
import org.mozilla.fenix.settings.logins.LoginsFragmentStore
import org.mozilla.fenix.settings.logins.SavedLogin
@ -45,8 +46,6 @@ import org.mozilla.fenix.settings.logins.togglePasswordReveal
@Suppress("TooManyFunctions", "NestedBlockDepth", "ForbiddenComment")
class EditLoginFragment : Fragment(R.layout.fragment_edit_login) {
private fun String.toEditable(): Editable = Editable.Factory.getInstance().newEditable(this)
private val args by navArgs<EditLoginFragmentArgs>()
private lateinit var loginsFragmentStore: LoginsFragmentStore
private lateinit var interactor: EditLoginInteractor

@ -1065,7 +1065,13 @@
<fragment
android:id="@+id/creditCardEditorFragment"
android:name="org.mozilla.fenix.settings.creditcards.CreditCardEditorFragment"
android:label="@string/credit_cards_add_card" />
android:label="@string/credit_cards_add_card">
<argument
android:name="creditCard"
android:defaultValue="@null"
app:argType="mozilla.components.concept.storage.CreditCard"
app:nullable="true" />
</fragment>
<fragment
android:id="@+id/creditCardsManagementFragment"
android:name="org.mozilla.fenix.settings.creditcards.CreditCardsManagementFragment"

@ -1530,6 +1530,8 @@
<string name="preferences_credit_cards_manage_saved_cards">Manage saved cards</string>
<!-- Title of the "Add card" screen -->
<string name="credit_cards_add_card">Add card</string>
<!-- Title of the "Edit card" screen -->
<string name="credit_cards_edit_card">Edit card</string>
<!-- The header for the card number of a credit card -->
<string name="credit_cards_card_number">Card Number</string>
<!-- The header for the expiration date of a credit card -->

@ -0,0 +1,60 @@
/* 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 mozilla.components.concept.storage.CreditCard
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import org.mozilla.fenix.settings.creditcards.CreditCardEditorFragment.Companion.NUMBER_OF_YEARS_TO_SHOW
import java.util.Calendar
class CreditCardEditorStateTest {
private val creditCard = CreditCard(
guid = "id",
billingName = "Banana Apple",
cardNumber = "4111111111111110",
expiryMonth = 5,
expiryYear = 2030,
cardType = "amex",
timeCreated = 1L,
timeLastUsed = 1L,
timeLastModified = 1L,
timesUsed = 1L
)
@Test
fun testToCreditCardEditorState() {
val state = creditCard.toCreditCardEditorState()
val startYear = creditCard.expiryYear.toInt()
val endYear = startYear + NUMBER_OF_YEARS_TO_SHOW
with(state) {
assertEquals(creditCard.billingName, billingName)
assertEquals(creditCard.cardNumber, cardNumber)
assertEquals(creditCard.expiryMonth.toInt(), expiryMonth)
assertEquals(Pair(startYear, endYear), expiryYears)
assertTrue(isEditing)
}
}
@Test
fun testGetInitialCreditCardEditorState() {
val state = getInitialCreditCardEditorState()
val calendar = Calendar.getInstance()
val startYear = calendar.get(Calendar.YEAR)
val endYear = startYear + NUMBER_OF_YEARS_TO_SHOW
with(state) {
assertEquals("", billingName)
assertEquals("", cardNumber)
assertEquals(1, expiryMonth)
assertEquals(Pair(startYear, endYear), expiryYears)
assertFalse(isEditing)
}
}
}

@ -0,0 +1,126 @@
/* 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 android.view.LayoutInflater
import android.view.View
import io.mockk.mockk
import io.mockk.verify
import kotlinx.android.synthetic.main.fragment_credit_card_editor.view.*
import mozilla.components.concept.storage.CreditCard
import mozilla.components.concept.storage.UpdatableCreditCardFields
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
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.mozilla.fenix.settings.creditcards.CreditCardEditorFragment.Companion.NUMBER_OF_YEARS_TO_SHOW
import org.mozilla.fenix.settings.creditcards.interactor.CreditCardEditorInteractor
import org.mozilla.fenix.settings.creditcards.view.CreditCardEditorView
import java.util.Calendar
@RunWith(FenixRobolectricTestRunner::class)
class CreditCardEditorViewTest {
private lateinit var view: View
private lateinit var interactor: CreditCardEditorInteractor
private lateinit var creditCardEditorView: CreditCardEditorView
private val creditCard = CreditCard(
guid = "id",
billingName = "Banana Apple",
cardNumber = "4111111111111110",
expiryMonth = 5,
expiryYear = 2030,
cardType = "amex",
timeCreated = 1L,
timeLastUsed = 1L,
timeLastModified = 1L,
timesUsed = 1L
)
@Before
fun setup() {
view = LayoutInflater.from(testContext).inflate(R.layout.fragment_credit_card_editor, null)
interactor = mockk(relaxed = true)
creditCardEditorView = CreditCardEditorView(view, interactor)
}
@Test
fun `GIVEN the initial credit card editor state THEN credit card form inputs are in initial state`() {
creditCardEditorView.bind(getInitialCreditCardEditorState())
val calendar = Calendar.getInstance()
val startYear = calendar.get(Calendar.YEAR)
val endYear = startYear + NUMBER_OF_YEARS_TO_SHOW - 1
assertEquals("", view.card_number_input.text.toString())
assertEquals("", view.name_on_card_input.text.toString())
with(view.expiry_month_drop_down) {
assertEquals(12, count)
assertEquals("January (01)", selectedItem.toString())
assertEquals("December (12)", getItemAtPosition(count - 1).toString())
}
with(view.expiry_year_drop_down) {
assertEquals(10, count)
assertEquals(startYear.toString(), selectedItem.toString())
assertEquals(endYear.toString(), getItemAtPosition(count - 1).toString())
}
}
@Test
fun `GIVEN a credit card THEN credit card form inputs are displaying the provided credit card information`() {
creditCardEditorView.bind(creditCard.toCreditCardEditorState())
assertEquals(creditCard.cardNumber, view.card_number_input.text.toString())
assertEquals(creditCard.billingName, view.name_on_card_input.text.toString())
with(view.expiry_month_drop_down) {
assertEquals(12, count)
assertEquals("May (05)", selectedItem.toString())
}
with(view.expiry_year_drop_down) {
val endYear = creditCard.expiryYear + NUMBER_OF_YEARS_TO_SHOW - 1
assertEquals(10, count)
assertEquals(creditCard.expiryYear.toString(), selectedItem.toString())
assertEquals(endYear.toString(), getItemAtPosition(count - 1).toString())
}
}
@Test
fun `WHEN the cancel button is clicked THEN interactor is called`() {
creditCardEditorView.bind(getInitialCreditCardEditorState())
view.cancel_button.performClick()
verify { interactor.onCancelButtonClicked() }
}
@Test
fun `GIVEN a credit card WHEN the save button is clicked THEN interactor is called`() {
creditCardEditorView.bind(creditCard.toCreditCardEditorState())
view.save_button.performClick()
verify {
interactor.onSaveButtonClicked(
UpdatableCreditCardFields(
billingName = creditCard.billingName,
cardNumber = creditCard.cardNumber,
expiryMonth = creditCard.expiryMonth,
expiryYear = creditCard.expiryYear,
cardType = "amex"
)
)
}
}
}

@ -57,6 +57,6 @@ class CreditCardItemViewHolderTest {
CreditCardItemViewHolder(view, interactor).bind(creditCard)
view.performClick()
verify { interactor.onSelectCreditCard() }
verify { interactor.onSelectCreditCard(creditCard) }
}
}

@ -8,6 +8,7 @@ import androidx.navigation.NavController
import io.mockk.coVerify
import io.mockk.mockk
import io.mockk.spyk
import io.mockk.verify
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestCoroutineDispatcher
import kotlinx.coroutines.test.TestCoroutineScope
@ -53,6 +54,15 @@ class DefaultCreditCardEditorControllerTest {
testDispatcher.cleanupTestCoroutines()
}
@Test
fun handleCancelButtonClicked() {
controller.handleCancelButtonClicked()
verify {
navController.popBackStack()
}
}
@Test
fun handleSaveCreditCard() = testCoroutineScope.runBlockingTest {
val creditCardFields = UpdatableCreditCardFields(

@ -0,0 +1,44 @@
/* 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 io.mockk.mockk
import io.mockk.verify
import mozilla.components.concept.storage.UpdatableCreditCardFields
import org.junit.Before
import org.junit.Test
import org.mozilla.fenix.settings.creditcards.controller.CreditCardEditorController
import org.mozilla.fenix.settings.creditcards.interactor.DefaultCreditCardEditorInteractor
class DefaultCreditCardEditorInteractorTest {
private val controller: CreditCardEditorController = mockk(relaxed = true)
private lateinit var interactor: DefaultCreditCardEditorInteractor
@Before
fun setup() {
interactor = DefaultCreditCardEditorInteractor(controller)
}
@Test
fun onCancelButtonClicked() {
interactor.onCancelButtonClicked()
verify { controller.handleCancelButtonClicked() }
}
@Test
fun onSaveButtonClicked() {
val creditCardFields = UpdatableCreditCardFields(
billingName = "Banana Apple",
cardNumber = "4111111111111112",
expiryMonth = 1,
expiryYear = 2030,
cardType = "discover"
)
interactor.onSaveButtonClicked(creditCardFields)
verify { controller.handleSaveCreditCard(creditCardFields) }
}
}

@ -8,6 +8,7 @@ import androidx.navigation.NavController
import io.mockk.mockk
import io.mockk.spyk
import io.mockk.verify
import mozilla.components.concept.storage.CreditCard
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ -34,12 +35,27 @@ class DefaultCreditCardsManagementControllerTest {
@Test
fun handleCreditCardClicked() {
controller.handleCreditCardClicked()
val creditCard = CreditCard(
guid = "id",
billingName = "Banana Apple",
cardNumber = "4111111111111110",
expiryMonth = 1,
expiryYear = 2030,
cardType = "amex",
timeCreated = 1L,
timeLastUsed = 1L,
timeLastModified = 1L,
timesUsed = 1L
)
controller.handleCreditCardClicked(creditCard)
verify {
navController.navigate(
CreditCardsManagementFragmentDirections
.actionCreditCardsManagementFragmentToCreditCardEditorFragment()
.actionCreditCardsManagementFragmentToCreditCardEditorFragment(
creditCard = creditCard
)
)
}
}

@ -6,6 +6,7 @@ package org.mozilla.fenix.settings.creditcards
import io.mockk.mockk
import io.mockk.verify
import mozilla.components.concept.storage.CreditCard
import org.junit.Before
import org.junit.Test
import org.mozilla.fenix.settings.creditcards.controller.CreditCardsManagementController
@ -24,7 +25,8 @@ class DefaultCreditCardsManagementInteractorTest {
@Test
fun onSelectCreditCard() {
interactor.onSelectCreditCard()
verify { controller.handleCreditCardClicked() }
val creditCard: CreditCard = mockk(relaxed = true)
interactor.onSelectCreditCard(creditCard)
verify { controller.handleCreditCardClicked(creditCard) }
}
}

Loading…
Cancel
Save