This commit is contained in:
parent
1128f921ad
commit
6eb528f912
|
@ -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))
|
||||
}
|
||||
|
||||
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…
Reference in New Issue
Block a user