From 2ddebb4e7ae32011ed59227b5427cda69cb43478 Mon Sep 17 00:00:00 2001 From: Michael Shafrir Date: Fri, 21 Feb 2020 10:35:56 -0500 Subject: [PATCH 1/3] Add support for Diners Club 16 Summary - Add `CardBrand.DinersClub16` to represent 16-digit Diners Club cards - Update Diners Club BIN range - Card numbers starting with `"30"`, `"38"`, or `"39"` represent 16-digit Diners Club cards - Card numbers starting with `"36"` represent 14-digit Diners Club cards - Update most tests to use `CardNumberFixtures` Testing Add unit tests --- .../com/stripe/android/model/CardBrand.kt | 15 +- .../stripe/android/view/CardInputWidget.kt | 4 +- .../com/stripe/android/CardNumberFixtures.kt | 34 +++- .../java/com/stripe/android/CardUtilsTest.kt | 35 ++-- .../java/com/stripe/android/StripeTest.java | 8 +- .../com/stripe/android/StripeTextUtilsTest.kt | 8 +- .../com/stripe/android/model/CardBrandTest.kt | 30 ++- .../stripe/android/model/CardParamsTest.kt | 4 +- .../java/com/stripe/android/model/CardTest.kt | 6 +- .../model/ConfirmPaymentIntentParamsTest.kt | 4 +- .../stripe/android/model/SourceParamsTest.kt | 8 +- .../android/view/CardInputWidgetTest.kt | 120 ++++++------ .../android/view/CardMultilineWidgetTest.kt | 90 ++++----- .../android/view/CardNumberEditTextTest.kt | 79 +++++--- .../com/stripe/android/view/ViewUtilsTest.kt | 182 +++++++++--------- 15 files changed, 350 insertions(+), 277 deletions(-) diff --git a/stripe/src/main/java/com/stripe/android/model/CardBrand.kt b/stripe/src/main/java/com/stripe/android/model/CardBrand.kt index 1db32a26b24..ff0c19db87d 100644 --- a/stripe/src/main/java/com/stripe/android/model/CardBrand.kt +++ b/stripe/src/main/java/com/stripe/android/model/CardBrand.kt @@ -65,6 +65,7 @@ enum class CardBrand( prefixes = listOf("35") ), + // 14-digit Diners Club DinersClub( "diners", "Diners Club", @@ -72,7 +73,19 @@ enum class CardBrand( maxLengthWithSpaces = 17, maxLengthWithoutSpaces = 14, prefixes = listOf( - "300", "301", "302", "303", "304", "305", "309", "36", "38", "39" + "36" + ) + ), + + // 16-digit Diners Club + DinersClub16( + "diners", + "Diners Club", + R.drawable.stripe_ic_diners, + maxLengthWithSpaces = 19, + maxLengthWithoutSpaces = 16, + prefixes = listOf( + "30", "38", "39" ) ), diff --git a/stripe/src/main/java/com/stripe/android/view/CardInputWidget.kt b/stripe/src/main/java/com/stripe/android/view/CardInputWidget.kt index a1f59fb1436..9aa2db28e02 100644 --- a/stripe/src/main/java/com/stripe/android/view/CardInputWidget.kt +++ b/stripe/src/main/java/com/stripe/android/view/CardInputWidget.kt @@ -942,7 +942,7 @@ class CardInputWidget @JvmOverloads constructor( get() { return when (brand) { CardBrand.AmericanExpress -> PEEK_TEXT_AMEX - CardBrand.DinersClub -> PEEK_TEXT_DINERS + CardBrand.DinersClub -> PEEK_TEXT_DINERS_14 else -> PEEK_TEXT_COMMON } } @@ -1290,7 +1290,7 @@ class CardInputWidget @JvmOverloads constructor( internal const val LOGGING_TOKEN = "CardInputView" private const val PEEK_TEXT_COMMON = "4242" - private const val PEEK_TEXT_DINERS = "88" + private const val PEEK_TEXT_DINERS_14 = "88" private const val PEEK_TEXT_AMEX = "34343" private const val CVC_PLACEHOLDER_COMMON = "CVC" diff --git a/stripe/src/test/java/com/stripe/android/CardNumberFixtures.kt b/stripe/src/test/java/com/stripe/android/CardNumberFixtures.kt index 151f74e89c6..570f10de71e 100644 --- a/stripe/src/test/java/com/stripe/android/CardNumberFixtures.kt +++ b/stripe/src/test/java/com/stripe/android/CardNumberFixtures.kt @@ -1,10 +1,32 @@ package com.stripe.android +/** + * See [Basic test card numbers](https://stripe.com/docs/testing#cards) + */ internal object CardNumberFixtures { - const val VALID_AMEX_NO_SPACES: String = "378282246310005" - const val VALID_AMEX_WITH_SPACES: String = "3782 822463 10005" - const val VALID_DINERS_CLUB_NO_SPACES: String = "30569309025904" - const val VALID_DINERS_CLUB_WITH_SPACES: String = "3056 9309 0259 04" - const val VALID_VISA_NO_SPACES: String = "4242424242424242" - const val VALID_VISA_WITH_SPACES: String = "4242 4242 4242 4242" + const val AMEX_NO_SPACES: String = "378282246310005" + const val AMEX_WITH_SPACES: String = "3782 822463 10005" + + const val VISA_NO_SPACES: String = "4242424242424242" + const val VISA_WITH_SPACES: String = "4242 4242 4242 4242" + + const val VISA_DEBIT_NO_SPACES: String = "4000056655665556" + + const val MASTERCARD_NO_SPACES = "5555555555554444" + const val MASTERCARD_WITH_SPACES = "5555 5555 5555 4444" + + const val DINERS_CLUB_14_NO_SPACES: String = "36227206271667" + const val DINERS_CLUB_14_WITH_SPACES: String = "3622 720627 1667" + + const val DINERS_CLUB_16_NO_SPACES = "3056930009020004" + const val DINERS_CLUB_16_WITH_SPACES = "3056 9300 0902 0004" + + const val DISCOVER_NO_SPACES = "6011000990139424" + const val DISCOVER_WITH_SPACES = "6011 0009 9013 9424" + + const val JCB_NO_SPACES = "3566002020360505" + const val JCB_WITH_SPACES = "3566 0020 2036 0505" + + const val UNIONPAY_NO_SPACES = "6200000000000005" + const val UNIONPAY_WITH_SPACES = "6200 0000 0000 0005" } diff --git a/stripe/src/test/java/com/stripe/android/CardUtilsTest.kt b/stripe/src/test/java/com/stripe/android/CardUtilsTest.kt index dcec8476748..29543fe9ad2 100644 --- a/stripe/src/test/java/com/stripe/android/CardUtilsTest.kt +++ b/stripe/src/test/java/com/stripe/android/CardUtilsTest.kt @@ -45,8 +45,12 @@ class CardUtilsTest { } @Test - fun getPossibleCardType_withDinersClubPrefix_returnsDinersClub() { - assertEquals(CardBrand.DinersClub, CardUtils.getPossibleCardType("303922 2234")) + fun getPossibleCardType_withDinersClub16Prefix_returnsDinersClub16() { + assertEquals(CardBrand.DinersClub16, CardUtils.getPossibleCardType("303922 2234")) + } + + @Test + fun getPossibleCardType_withDinersClub14Prefix_returnsDinersClub() { assertEquals(CardBrand.DinersClub, CardUtils.getPossibleCardType("36778 9098")) } @@ -73,7 +77,7 @@ class CardUtilsTest { @Test fun isValidCardLength_whenValidVisaNumber_returnsTrue() { - assertTrue(CardUtils.isValidCardLength("4242424242424242")) + assertTrue(CardUtils.isValidCardLength(CardNumberFixtures.VISA_NO_SPACES)) } @Test @@ -83,27 +87,27 @@ class CardUtilsTest { @Test fun isValidCardLength_whenValidDiscover_returnsTrue() { - assertTrue(CardUtils.isValidCardLength("6011000990139424")) + assertTrue(CardUtils.isValidCardLength(CardNumberFixtures.DISCOVER_NO_SPACES)) } @Test - fun isValidCardLength_whenValidDinersClub_returnsTrue() { - assertTrue(CardUtils.isValidCardLength("30569309025904")) + fun isValidCardLength_whenValidDinersClub16_returnsTrue() { + assertTrue(CardUtils.isValidCardLength(CardNumberFixtures.DINERS_CLUB_16_NO_SPACES)) } @Test fun isValidCardLength_whenValidMasterCard_returnsTrue() { - assertTrue(CardUtils.isValidCardLength("5555555555554444")) + assertTrue(CardUtils.isValidCardLength(CardNumberFixtures.MASTERCARD_NO_SPACES)) } @Test fun isValidCardLength_whenValidAmEx_returnsTrue() { - assertTrue(CardUtils.isValidCardLength("378282246310005")) + assertTrue(CardUtils.isValidCardLength(CardNumberFixtures.AMEX_NO_SPACES)) } @Test fun isValidCardLength_whenValidUnionPay_returnsTrue() { - assertTrue(CardUtils.isValidCardLength("6200000000000005")) + assertTrue(CardUtils.isValidCardLength(CardNumberFixtures.UNIONPAY_NO_SPACES)) } @Test @@ -131,11 +135,6 @@ class CardUtilsTest { assertFalse(CardUtils.isValidCardLength("37828224631000")) } - @Test - fun isValidCardLength_whenDinersClubStyleNumberButVisaLength_returnsFalse() { - assertFalse(CardUtils.isValidCardLength("3056930902590400")) - } - @Test fun isValidCardLength_whenDinersClubStyleNumberStyleNumberButAmexLength_returnsFalse() { assertFalse(CardUtils.isValidCardLength("305693090259040")) @@ -143,7 +142,7 @@ class CardUtilsTest { @Test fun isValidLuhnNumber_whenValidVisaNumber_returnsTrue() { - assertTrue(CardUtils.isValidLuhnNumber("4242424242424242")) + assertTrue(CardUtils.isValidLuhnNumber(CardNumberFixtures.VISA_NO_SPACES)) } @Test @@ -153,7 +152,7 @@ class CardUtilsTest { @Test fun isValidLuhnNumber_whenValidDiscover_returnsTrue() { - assertTrue(CardUtils.isValidLuhnNumber("6011000990139424")) + assertTrue(CardUtils.isValidLuhnNumber(CardNumberFixtures.DISCOVER_NO_SPACES)) } @Test @@ -163,12 +162,12 @@ class CardUtilsTest { @Test fun isValidLuhnNumber_whenValidMasterCard_returnsTrue() { - assertTrue(CardUtils.isValidLuhnNumber("5555555555554444")) + assertTrue(CardUtils.isValidLuhnNumber(CardNumberFixtures.MASTERCARD_NO_SPACES)) } @Test fun isValidLuhnNumber_whenValidAmEx_returnsTrue() { - assertTrue(CardUtils.isValidLuhnNumber("378282246310005")) + assertTrue(CardUtils.isValidLuhnNumber(CardNumberFixtures.AMEX_NO_SPACES)) } @Test diff --git a/stripe/src/test/java/com/stripe/android/StripeTest.java b/stripe/src/test/java/com/stripe/android/StripeTest.java index d97c9e5365d..e1a4a7281ae 100644 --- a/stripe/src/test/java/com/stripe/android/StripeTest.java +++ b/stripe/src/test/java/com/stripe/android/StripeTest.java @@ -52,7 +52,7 @@ import kotlinx.coroutines.CoroutineScope; -import static com.stripe.android.CardNumberFixtures.VALID_VISA_NO_SPACES; +import static com.stripe.android.CardNumberFixtures.VISA_NO_SPACES; import static kotlinx.coroutines.CoroutineScopeKt.MainScope; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -440,7 +440,7 @@ public void createSourceSynchronous_withBancontactParams_passesIntegrationTest() @Test public void createSourceSynchronous_withCardParams_passesIntegrationTest() throws StripeException { - final Card card = new Card.Builder(VALID_VISA_NO_SPACES, 12, 2050, "123") + final Card card = new Card.Builder(VISA_NO_SPACES, 12, 2050, "123") .addressCity("Sheboygan") .addressCountry("US") .addressLine1("123 Main St") @@ -480,7 +480,7 @@ public void createSourceSynchronous_withCardParams_passesIntegrationTest() public void createSourceSynchronous_with3DSParams_passesIntegrationTest() throws StripeException { final Stripe stripe = createStripe(); - final Card card = Card.create(VALID_VISA_NO_SPACES, 12, 2050, "123"); + final Card card = Card.create(VISA_NO_SPACES, 12, 2050, "123"); final SourceParams params = SourceParams.createCardParams(card); final Source cardSource = stripe.createSourceSynchronous(params); @@ -1352,7 +1352,7 @@ public void createFileSynchronous_shouldCreateFile() { private Source createSource() throws StripeException { final Stripe stripe = createStripe(); final SourceParams params = SourceParams.createCardParams( - Card.create(VALID_VISA_NO_SPACES, 12, 2050, "123") + Card.create(VISA_NO_SPACES, 12, 2050, "123") ); final Source cardSource = stripe.createSourceSynchronous(params); diff --git a/stripe/src/test/java/com/stripe/android/StripeTextUtilsTest.kt b/stripe/src/test/java/com/stripe/android/StripeTextUtilsTest.kt index ce17b0440a7..7237a286706 100644 --- a/stripe/src/test/java/com/stripe/android/StripeTextUtilsTest.kt +++ b/stripe/src/test/java/com/stripe/android/StripeTextUtilsTest.kt @@ -12,7 +12,7 @@ class StripeTextUtilsTest { fun removeSpacesAndHyphens_withSpacesInInterior_returnsSpacelessNumber() { val testCardNumber = "4242 4242 4242 4242" assertEquals( - CardNumberFixtures.VALID_VISA_NO_SPACES, + CardNumberFixtures.VISA_NO_SPACES, StripeTextUtils.removeSpacesAndHyphens(testCardNumber) ) } @@ -21,7 +21,7 @@ class StripeTextUtilsTest { fun removeSpacesAndHyphens_withExcessiveSpacesInInterior_returnsSpacelessNumber() { val testCardNumber = "4 242 4 242 4 242 42 4 2" assertEquals( - CardNumberFixtures.VALID_VISA_NO_SPACES, + CardNumberFixtures.VISA_NO_SPACES, StripeTextUtils.removeSpacesAndHyphens(testCardNumber) ) } @@ -30,7 +30,7 @@ class StripeTextUtilsTest { fun removeSpacesAndHyphens_withSpacesOnExterior_returnsSpacelessNumber() { val testCardNumber = " 42424242 4242 4242 " assertEquals( - CardNumberFixtures.VALID_VISA_NO_SPACES, + CardNumberFixtures.VISA_NO_SPACES, StripeTextUtils.removeSpacesAndHyphens(testCardNumber) ) } @@ -48,7 +48,7 @@ class StripeTextUtilsTest { @Test fun removeSpacesAndHyphens_withHyphenatedCardNumber_returnsCardNumber() { assertEquals( - CardNumberFixtures.VALID_VISA_NO_SPACES, + CardNumberFixtures.VISA_NO_SPACES, StripeTextUtils.removeSpacesAndHyphens("4242-4242-4242-4242") ) } diff --git a/stripe/src/test/java/com/stripe/android/model/CardBrandTest.kt b/stripe/src/test/java/com/stripe/android/model/CardBrandTest.kt index ef737acece7..808dfb7d6b0 100644 --- a/stripe/src/test/java/com/stripe/android/model/CardBrandTest.kt +++ b/stripe/src/test/java/com/stripe/android/model/CardBrandTest.kt @@ -28,15 +28,31 @@ class CardBrandTest { fun fromCardNumber_withAmericanExpress() { assertEquals( CardBrand.AmericanExpress, - CardBrand.fromCardNumber(CardNumberFixtures.VALID_AMEX_NO_SPACES) + CardBrand.fromCardNumber(CardNumberFixtures.AMEX_NO_SPACES) ) } @Test - fun fromCardNumber_withDinersClub() { + fun fromCardNumber_withDinersClub14() { assertEquals( CardBrand.DinersClub, - CardBrand.fromCardNumber(CardNumberFixtures.VALID_DINERS_CLUB_NO_SPACES) + CardBrand.fromCardNumber(CardNumberFixtures.DINERS_CLUB_14_NO_SPACES) + ) + } + + @Test + fun fromCardNumber_withDinersClub16() { + assertEquals( + CardBrand.DinersClub16, + CardBrand.fromCardNumber(CardNumberFixtures.DINERS_CLUB_16_NO_SPACES) + ) + } + + @Test + fun fromCardNumber_withJcb() { + assertEquals( + CardBrand.JCB, + CardBrand.fromCardNumber(CardNumberFixtures.JCB_NO_SPACES) ) } @@ -44,7 +60,7 @@ class CardBrandTest { fun fromCardNumber_withVisa() { assertEquals( CardBrand.Visa, - CardBrand.fromCardNumber(CardNumberFixtures.VALID_VISA_NO_SPACES) + CardBrand.fromCardNumber(CardNumberFixtures.VISA_NO_SPACES) ) } @@ -52,7 +68,7 @@ class CardBrandTest { fun fromCardNumber_withInvalidVisa() { assertEquals( CardBrand.Unknown, - CardBrand.fromCardNumber("1" + CardNumberFixtures.VALID_VISA_NO_SPACES) + CardBrand.fromCardNumber("1" + CardNumberFixtures.VISA_NO_SPACES) ) } @@ -60,10 +76,10 @@ class CardBrandTest { fun isValidCardLengthWithBrand_whenBrandUnknown_alwaysReturnsFalse() { // Adding this check to ensure the input number is correct assertTrue( - CardBrand.Visa.isValidCardNumberLength(CardNumberFixtures.VALID_VISA_NO_SPACES) + CardBrand.Visa.isValidCardNumberLength(CardNumberFixtures.VISA_NO_SPACES) ) assertFalse( - CardBrand.Unknown.isValidCardNumberLength(CardNumberFixtures.VALID_VISA_NO_SPACES) + CardBrand.Unknown.isValidCardNumberLength(CardNumberFixtures.VISA_NO_SPACES) ) } diff --git a/stripe/src/test/java/com/stripe/android/model/CardParamsTest.kt b/stripe/src/test/java/com/stripe/android/model/CardParamsTest.kt index 5bafc572c01..c3e6f2787f5 100644 --- a/stripe/src/test/java/com/stripe/android/model/CardParamsTest.kt +++ b/stripe/src/test/java/com/stripe/android/model/CardParamsTest.kt @@ -9,7 +9,7 @@ class CardParamsTest { @Test fun toParamMap_shouldCreateExpectedMap() { val actualParams = CardParams( - number = CardNumberFixtures.VALID_VISA_NO_SPACES, + number = CardNumberFixtures.VISA_NO_SPACES, expMonth = 12, expYear = 2025, cvc = "123", @@ -42,7 +42,7 @@ class CardParamsTest { @Test fun builder_createsExpectedObject() { val expected = CardParams( - number = CardNumberFixtures.VALID_VISA_NO_SPACES, + number = CardNumberFixtures.VISA_NO_SPACES, expMonth = 12, expYear = 2025, cvc = "123", diff --git a/stripe/src/test/java/com/stripe/android/model/CardTest.kt b/stripe/src/test/java/com/stripe/android/model/CardTest.kt index 55312e16ab9..a3c4e2f7e31 100644 --- a/stripe/src/test/java/com/stripe/android/model/CardTest.kt +++ b/stripe/src/test/java/com/stripe/android/model/CardTest.kt @@ -70,7 +70,7 @@ class CardTest { @Test fun testTypeReturnsCorrectlyForUnionPay() { - val card = Card.create(number = "6200000000000005") + val card = Card.create(number = CardNumberFixtures.UNIONPAY_NO_SPACES) assertEquals(CardBrand.UnionPay, card.brand) } @@ -132,13 +132,13 @@ class CardTest { @Test fun shouldPassValidateNumber() { - val card = Card.create(CardNumberFixtures.VALID_VISA_NO_SPACES) + val card = Card.create(CardNumberFixtures.VISA_NO_SPACES) assertTrue(card.validateNumber()) } @Test fun shouldPassValidateNumberSpaces() { - val card = Card.create(CardNumberFixtures.VALID_VISA_WITH_SPACES) + val card = Card.create(CardNumberFixtures.VISA_WITH_SPACES) assertTrue(card.validateNumber()) } diff --git a/stripe/src/test/java/com/stripe/android/model/ConfirmPaymentIntentParamsTest.kt b/stripe/src/test/java/com/stripe/android/model/ConfirmPaymentIntentParamsTest.kt index 430d58ec0ad..7681aaecda2 100644 --- a/stripe/src/test/java/com/stripe/android/model/ConfirmPaymentIntentParamsTest.kt +++ b/stripe/src/test/java/com/stripe/android/model/ConfirmPaymentIntentParamsTest.kt @@ -1,6 +1,6 @@ package com.stripe.android.model -import com.stripe.android.CardNumberFixtures.VALID_VISA_NO_SPACES +import com.stripe.android.CardNumberFixtures.VISA_NO_SPACES import com.stripe.android.model.ConfirmPaymentIntentParams.Companion.PARAM_PAYMENT_METHOD_OPTIONS import com.stripe.android.model.ConfirmPaymentIntentParams.Companion.PARAM_SAVE_PAYMENT_METHOD import com.stripe.android.model.ConfirmPaymentIntentParams.Companion.PARAM_SOURCE_ID @@ -312,7 +312,7 @@ class ConfirmPaymentIntentParamsTest { private companion object { private val FULL_FIELDS_VISA_CARD = - Card.Builder(VALID_VISA_NO_SPACES, 12, 2050, "123") + Card.Builder(VISA_NO_SPACES, 12, 2050, "123") .name("Captain Cardholder") .addressLine1("1 ABC Street") .addressLine2("Apt. 123") diff --git a/stripe/src/test/java/com/stripe/android/model/SourceParamsTest.kt b/stripe/src/test/java/com/stripe/android/model/SourceParamsTest.kt index d042b37f802..bab717bd88d 100644 --- a/stripe/src/test/java/com/stripe/android/model/SourceParamsTest.kt +++ b/stripe/src/test/java/com/stripe/android/model/SourceParamsTest.kt @@ -1,6 +1,6 @@ package com.stripe.android.model -import com.stripe.android.CardNumberFixtures.VALID_VISA_NO_SPACES +import com.stripe.android.CardNumberFixtures.VISA_NO_SPACES import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNull @@ -175,7 +175,7 @@ class SourceParamsTest { val apiMap = params.apiParameterMap requireNotNull(apiMap) - assertEquals(VALID_VISA_NO_SPACES, apiMap["number"]) + assertEquals(VISA_NO_SPACES, apiMap["number"]) assertEquals(12, apiMap["exp_month"]) assertEquals(2050, apiMap["exp_year"]) assertEquals("123", apiMap["cvc"]) @@ -203,7 +203,7 @@ class SourceParamsTest { val totalExpectedMap = mapOf( "type" to "card", "card" to mapOf( - "number" to VALID_VISA_NO_SPACES, + "number" to VISA_NO_SPACES, "exp_month" to 12, "exp_year" to 2050, "cvc" to "123" @@ -713,7 +713,7 @@ class SourceParamsTest { private const val RETURN_URL = "stripe://return" private val FULL_FIELDS_VISA_CARD = - Card.Builder(VALID_VISA_NO_SPACES, 12, 2050, "123") + Card.Builder(VISA_NO_SPACES, 12, 2050, "123") .name("Captain Cardholder") .addressLine1("1 ABC Street") .addressLine2("Apt. 123") diff --git a/stripe/src/test/java/com/stripe/android/view/CardInputWidgetTest.kt b/stripe/src/test/java/com/stripe/android/view/CardInputWidgetTest.kt index c385f599e8a..ca9a07bc562 100644 --- a/stripe/src/test/java/com/stripe/android/view/CardInputWidgetTest.kt +++ b/stripe/src/test/java/com/stripe/android/view/CardInputWidgetTest.kt @@ -7,12 +7,12 @@ import android.widget.ImageView import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.reset import com.nhaarman.mockitokotlin2.verify -import com.stripe.android.CardNumberFixtures.VALID_AMEX_NO_SPACES -import com.stripe.android.CardNumberFixtures.VALID_AMEX_WITH_SPACES -import com.stripe.android.CardNumberFixtures.VALID_DINERS_CLUB_NO_SPACES -import com.stripe.android.CardNumberFixtures.VALID_DINERS_CLUB_WITH_SPACES -import com.stripe.android.CardNumberFixtures.VALID_VISA_NO_SPACES -import com.stripe.android.CardNumberFixtures.VALID_VISA_WITH_SPACES +import com.stripe.android.CardNumberFixtures.AMEX_NO_SPACES +import com.stripe.android.CardNumberFixtures.AMEX_WITH_SPACES +import com.stripe.android.CardNumberFixtures.DINERS_CLUB_14_NO_SPACES +import com.stripe.android.CardNumberFixtures.DINERS_CLUB_14_WITH_SPACES +import com.stripe.android.CardNumberFixtures.VISA_NO_SPACES +import com.stripe.android.CardNumberFixtures.VISA_WITH_SPACES import com.stripe.android.R import com.stripe.android.model.Address import com.stripe.android.model.CardBrand @@ -110,14 +110,14 @@ internal class CardInputWidgetTest : BaseViewTest( fun getCard_whenInputIsValidVisa_withPostalCodeDisabled_returnsCardObjectWithLoggingToken() { cardInputWidget.postalCodeEnabled = false - cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + cardNumberEditText.setText(VISA_WITH_SPACES) expiryEditText.append("12") expiryEditText.append("50") cvcEditText.append(CVC_VALUE_COMMON) val card = cardInputWidget.card assertNotNull(card) - assertEquals(VALID_VISA_NO_SPACES, card.number) + assertEquals(VISA_NO_SPACES, card.number) assertNotNull(card.expMonth) assertNotNull(card.expYear) assertEquals(12, card.expMonth) @@ -131,7 +131,7 @@ internal class CardInputWidgetTest : BaseViewTest( val expectedPaymentMethodParams = PaymentMethodCreateParams.create( card = PaymentMethodCreateParams.Card( - number = VALID_VISA_NO_SPACES, + number = VISA_NO_SPACES, cvc = CVC_VALUE_COMMON, expiryMonth = 12, expiryYear = 2050, @@ -145,7 +145,7 @@ internal class CardInputWidgetTest : BaseViewTest( fun getCard_whenInputIsValidVisa_withPostalCodeEnabled_returnsCardObjectWithLoggingToken() { cardInputWidget.postalCodeEnabled = true - cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + cardNumberEditText.setText(VISA_WITH_SPACES) expiryEditText.append("12") expiryEditText.append("50") cvcEditText.append(CVC_VALUE_COMMON) @@ -153,7 +153,7 @@ internal class CardInputWidgetTest : BaseViewTest( val card = cardInputWidget.card assertNotNull(card) - assertEquals(VALID_VISA_NO_SPACES, card.number) + assertEquals(VISA_NO_SPACES, card.number) assertEquals(12, card.expMonth) assertEquals(2050, card.expYear) assertEquals(CVC_VALUE_COMMON, card.cvc) @@ -166,7 +166,7 @@ internal class CardInputWidgetTest : BaseViewTest( val expectedPaymentMethodParams = PaymentMethodCreateParams.create( card = PaymentMethodCreateParams.Card( - number = VALID_VISA_NO_SPACES, + number = VISA_NO_SPACES, cvc = CVC_VALUE_COMMON, expiryMonth = 12, expiryYear = 2050, @@ -185,13 +185,13 @@ internal class CardInputWidgetTest : BaseViewTest( fun getCard_whenInputIsValidAmEx_withPostalCodeDisabled_createsExpectedObjects() { cardInputWidget.postalCodeEnabled = false - cardNumberEditText.setText(VALID_AMEX_WITH_SPACES) + cardNumberEditText.setText(AMEX_WITH_SPACES) expiryEditText.append("12") expiryEditText.append("50") cvcEditText.append(CVC_VALUE_AMEX) val card = requireNotNull(cardInputWidget.card) - assertEquals(VALID_AMEX_NO_SPACES, card.number) + assertEquals(AMEX_NO_SPACES, card.number) assertNotNull(card.expMonth) assertNotNull(card.expYear) assertEquals(12, card.expMonth) @@ -204,7 +204,7 @@ internal class CardInputWidgetTest : BaseViewTest( requireNotNull(cardInputWidget.paymentMethodCreateParams) val expectedPaymentMethodParams = PaymentMethodCreateParams.create( PaymentMethodCreateParams.Card( - number = VALID_AMEX_NO_SPACES, + number = AMEX_NO_SPACES, cvc = CVC_VALUE_AMEX, expiryMonth = 12, expiryYear = 2050, @@ -218,14 +218,14 @@ internal class CardInputWidgetTest : BaseViewTest( fun getCard_whenInputIsValidAmEx_withPostalCodeEnabled_createsExpectedObjects() { cardInputWidget.postalCodeEnabled = true - cardNumberEditText.setText(VALID_AMEX_WITH_SPACES) + cardNumberEditText.setText(AMEX_WITH_SPACES) expiryEditText.append("12") expiryEditText.append("50") cvcEditText.append(CVC_VALUE_AMEX) postalCodeEditText.setText(POSTAL_CODE_VALUE) val card = requireNotNull(cardInputWidget.card) - assertEquals(VALID_AMEX_NO_SPACES, card.number) + assertEquals(AMEX_NO_SPACES, card.number) assertNotNull(card.expMonth) assertNotNull(card.expYear) assertEquals(12, card.expMonth) @@ -240,7 +240,7 @@ internal class CardInputWidgetTest : BaseViewTest( val expectedPaymentMethodParams = PaymentMethodCreateParams.create( card = PaymentMethodCreateParams.Card( - number = VALID_AMEX_NO_SPACES, + number = AMEX_NO_SPACES, cvc = CVC_VALUE_AMEX, expiryYear = 2050, expiryMonth = 12, @@ -259,13 +259,13 @@ internal class CardInputWidgetTest : BaseViewTest( fun getCard_whenInputIsValidDinersClub_withPostalCodeDisabled_returnsCardObjectWithLoggingToken() { cardInputWidget.postalCodeEnabled = false - cardNumberEditText.setText(VALID_DINERS_CLUB_WITH_SPACES) + cardNumberEditText.setText(DINERS_CLUB_14_WITH_SPACES) expiryEditText.append("12") expiryEditText.append("50") cvcEditText.append(CVC_VALUE_COMMON) val card = requireNotNull(cardInputWidget.card) - assertEquals(VALID_DINERS_CLUB_NO_SPACES, card.number) + assertEquals(DINERS_CLUB_14_NO_SPACES, card.number) assertNotNull(card.expMonth) assertNotNull(card.expYear) assertEquals(12, card.expMonth) @@ -278,7 +278,7 @@ internal class CardInputWidgetTest : BaseViewTest( assertNotNull(paymentMethodCard) val expectedPaymentMethodCard = PaymentMethodCreateParams.Card( - number = VALID_DINERS_CLUB_NO_SPACES, + number = DINERS_CLUB_14_NO_SPACES, cvc = CVC_VALUE_COMMON, expiryMonth = 12, expiryYear = 2050, @@ -291,14 +291,14 @@ internal class CardInputWidgetTest : BaseViewTest( fun getCard_whenInputIsValidDinersClub_withPostalCodeEnabled_returnsCardObjectWithLoggingToken() { cardInputWidget.postalCodeEnabled = true - cardNumberEditText.setText(VALID_DINERS_CLUB_WITH_SPACES) + cardNumberEditText.setText(DINERS_CLUB_14_WITH_SPACES) expiryEditText.append("12") expiryEditText.append("50") cvcEditText.append(CVC_VALUE_COMMON) postalCodeEditText.setText(POSTAL_CODE_VALUE) val card = requireNotNull(cardInputWidget.card) - assertEquals(VALID_DINERS_CLUB_NO_SPACES, card.number) + assertEquals(DINERS_CLUB_14_NO_SPACES, card.number) assertNotNull(card.expMonth) assertNotNull(card.expYear) assertEquals(12, card.expMonth) @@ -310,7 +310,7 @@ internal class CardInputWidgetTest : BaseViewTest( val paymentMethodCard = cardInputWidget.paymentMethodCard assertNotNull(paymentMethodCard) val expectedPaymentMethodCard = PaymentMethodCreateParams.Card( - number = VALID_DINERS_CLUB_NO_SPACES, + number = DINERS_CLUB_14_NO_SPACES, cvc = CVC_VALUE_COMMON, expiryYear = 2050, expiryMonth = 12, @@ -324,7 +324,7 @@ internal class CardInputWidgetTest : BaseViewTest( cardInputWidget.postalCodeEnabled = true cardInputWidget.postalCodeRequired = true - cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + cardNumberEditText.setText(VISA_WITH_SPACES) expiryEditText.append("12") expiryEditText.append("50") cvcEditText.append(CVC_VALUE_COMMON) @@ -340,7 +340,7 @@ internal class CardInputWidgetTest : BaseViewTest( @Test fun getCard_whenInputHasIncompleteCardNumber_returnsNull() { // This will be 242 4242 4242 4242 - cardNumberEditText.setText(VALID_VISA_WITH_SPACES.substring(1)) + cardNumberEditText.setText(VISA_WITH_SPACES.substring(1)) expiryEditText.append("12") expiryEditText.append("50") cvcEditText.append(CVC_VALUE_COMMON) @@ -357,7 +357,7 @@ internal class CardInputWidgetTest : BaseViewTest( // The test will be testing the wrong variable after 2080. Please update the test. assertTrue(Calendar.getInstance().get(Calendar.YEAR) < 2080) - cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + cardNumberEditText.setText(VISA_WITH_SPACES) // Date interpreted as 12/2012 until 2080, when it will be 12/2112 expiryEditText.append("12") expiryEditText.append("12") @@ -372,7 +372,7 @@ internal class CardInputWidgetTest : BaseViewTest( @Test fun getCard_whenIncompleteCvCForVisa_returnsNull() { - cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + cardNumberEditText.setText(VISA_WITH_SPACES) expiryEditText.append("12") expiryEditText.append("50") cvcEditText.append("12") @@ -388,7 +388,7 @@ internal class CardInputWidgetTest : BaseViewTest( fun getCard_doesNotValidatePostalCode() { cardInputWidget.postalCodeEnabled = true - cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + cardNumberEditText.setText(VISA_WITH_SPACES) expiryEditText.append("12") expiryEditText.append("50") cvcEditText.append(CVC_VALUE_COMMON) @@ -405,7 +405,7 @@ internal class CardInputWidgetTest : BaseViewTest( fun getCard_when3DigitCvCForAmEx_withPostalCodeDisabled_returnsCard() { cardInputWidget.postalCodeEnabled = false - cardNumberEditText.setText(VALID_AMEX_WITH_SPACES) + cardNumberEditText.setText(AMEX_WITH_SPACES) expiryEditText.append("12") expiryEditText.append("50") cvcEditText.append(CVC_VALUE_COMMON) @@ -421,7 +421,7 @@ internal class CardInputWidgetTest : BaseViewTest( fun getCard_when3DigitCvCForAmEx_withPostalCodeEnabled_returnsCard() { cardInputWidget.postalCodeEnabled = true - cardNumberEditText.setText(VALID_AMEX_WITH_SPACES) + cardNumberEditText.setText(AMEX_WITH_SPACES) expiryEditText.append("12") expiryEditText.append("50") cvcEditText.append(CVC_VALUE_COMMON) @@ -436,7 +436,7 @@ internal class CardInputWidgetTest : BaseViewTest( @Test fun getCard_whenIncompleteCvCForAmEx_returnsNull() { - cardNumberEditText.setText(VALID_AMEX_WITH_SPACES) + cardNumberEditText.setText(AMEX_WITH_SPACES) expiryEditText.append("12") expiryEditText.append("50") cvcEditText.append("12") @@ -452,7 +452,7 @@ internal class CardInputWidgetTest : BaseViewTest( fun getPaymentMethodCreateParams_shouldReturnExpectedObject() { cardInputWidget.postalCodeEnabled = true - cardInputWidget.setCardNumber(VALID_VISA_NO_SPACES) + cardInputWidget.setCardNumber(VISA_NO_SPACES) cardInputWidget.setExpiryDate(12, 2030) cardInputWidget.setCvcCode(CVC_VALUE_COMMON) cardInputWidget.setPostalCode(POSTAL_CODE_VALUE) @@ -462,7 +462,7 @@ internal class CardInputWidgetTest : BaseViewTest( val expectedParams = PaymentMethodCreateParams.create( card = PaymentMethodCreateParams.Card( - number = VALID_VISA_NO_SPACES, + number = VISA_NO_SPACES, cvc = CVC_VALUE_COMMON, expiryMonth = 12, expiryYear = 2030, @@ -479,7 +479,7 @@ internal class CardInputWidgetTest : BaseViewTest( @Test fun getCard_whenIncompleteCvCForDiners_returnsNull() { - cardNumberEditText.setText(VALID_DINERS_CLUB_WITH_SPACES) + cardNumberEditText.setText(DINERS_CLUB_14_WITH_SPACES) expiryEditText.append("12") expiryEditText.append("50") cvcEditText.append("12") @@ -495,7 +495,7 @@ internal class CardInputWidgetTest : BaseViewTest( fun onCompleteCardNumber_whenValid_shiftsFocusToExpiryDate() { cardInputWidget.setCardInputListener(cardInputListener) - cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + cardNumberEditText.setText(VISA_WITH_SPACES) verify(cardInputListener).onCardComplete() verify(cardInputListener).onFocusChange(FOCUS_EXPIRY) @@ -506,7 +506,7 @@ internal class CardInputWidgetTest : BaseViewTest( @Test fun onDeleteFromExpiryDate_whenEmpty_shiftsFocusToCardNumberAndDeletesDigit() { cardInputWidget.setCardInputListener(cardInputListener) - cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + cardNumberEditText.setText(VISA_WITH_SPACES) assertTrue(expiryEditText.hasFocus()) // The above functionality is tested elsewhere, so we reset this listener. @@ -517,21 +517,21 @@ internal class CardInputWidgetTest : BaseViewTest( assertEquals(R.id.et_expiry_date, onGlobalFocusChangeListener.oldFocusId) assertEquals(R.id.et_card_number, onGlobalFocusChangeListener.newFocusId) - val subString = VALID_VISA_WITH_SPACES.substring(0, VALID_VISA_WITH_SPACES.length - 1) + val subString = VISA_WITH_SPACES.substring(0, VISA_WITH_SPACES.length - 1) assertEquals(subString, cardNumberEditText.text.toString()) assertEquals(subString.length, cardNumberEditText.selectionStart) } @Test fun onDeleteFromExpiryDate_whenNotEmpty_doesNotShiftFocusOrDeleteDigit() { - cardNumberEditText.setText(VALID_AMEX_WITH_SPACES) + cardNumberEditText.setText(AMEX_WITH_SPACES) assertTrue(expiryEditText.hasFocus()) expiryEditText.append("1") ViewTestUtils.sendDeleteKeyEvent(expiryEditText) assertTrue(expiryEditText.hasFocus()) - assertEquals(VALID_AMEX_WITH_SPACES, cardNumberEditText.text.toString()) + assertEquals(AMEX_WITH_SPACES, cardNumberEditText.text.toString()) } @Test @@ -540,7 +540,7 @@ internal class CardInputWidgetTest : BaseViewTest( assertTrue(Calendar.getInstance().get(Calendar.YEAR) < 2080) cardInputWidget.setCardInputListener(cardInputListener) - cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + cardNumberEditText.setText(VISA_WITH_SPACES) verify(cardInputListener).onCardComplete() verify(cardInputListener).onFocusChange(FOCUS_EXPIRY) @@ -572,7 +572,7 @@ internal class CardInputWidgetTest : BaseViewTest( // This test will be invalid if run between 2080 and 2112. Please update the code. assertTrue(Calendar.getInstance().get(Calendar.YEAR) < 2080) - cardNumberEditText.setText(VALID_AMEX_WITH_SPACES) + cardNumberEditText.setText(AMEX_WITH_SPACES) expiryEditText.append("12") expiryEditText.append("79") @@ -592,7 +592,7 @@ internal class CardInputWidgetTest : BaseViewTest( // This test will be invalid if run between 2080 and 2112. Please update the code. assertTrue(Calendar.getInstance().get(Calendar.YEAR) < 2080) - cardNumberEditText.setText(VALID_AMEX_WITH_SPACES) + cardNumberEditText.setText(AMEX_WITH_SPACES) expiryEditText.append("12") expiryEditText.append("79") @@ -607,7 +607,7 @@ internal class CardInputWidgetTest : BaseViewTest( @Test fun onDeleteFromCvcDate_whenEmptyAndExpiryDateIsEmpty_shiftsFocusOnly() { - cardNumberEditText.setText(VALID_DINERS_CLUB_WITH_SPACES) + cardNumberEditText.setText(DINERS_CLUB_14_WITH_SPACES) // Simulates user tapping into this text field without filling out the date first. cvcEditText.requestFocus() @@ -894,7 +894,7 @@ internal class CardInputWidgetTest : BaseViewTest( // Moving left with an actual Visa number does the same as moving when empty. // |(peek==40)--(space==185)--(date==50)--(space==195)--(cvc==30)| - cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + cardNumberEditText.setText(VISA_WITH_SPACES) val shiftedParameters = cardInputWidget.placementParameters assertEquals(40, shiftedParameters.peekCardWidth) assertEquals(185, shiftedParameters.cardDateSeparation) @@ -911,7 +911,7 @@ internal class CardInputWidgetTest : BaseViewTest( // Moving left with an actual Visa number does the same as moving when empty. // |(peek==40)--(space==98)--(date==50)--(space==82)--(cvc==30)--(space==0)--(postal==100)| - cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + cardNumberEditText.setText(VISA_WITH_SPACES) val shiftedParameters = cardInputWidget.placementParameters assertEquals(40, shiftedParameters.peekCardWidth) assertEquals(98, shiftedParameters.cardDateSeparation) @@ -928,7 +928,7 @@ internal class CardInputWidgetTest : BaseViewTest( // Moving left with an AmEx number has a larger peek and cvc size. // |(peek==50)--(space==175)--(date==50)--(space==185)--(cvc==40)| - cardNumberEditText.setText(VALID_AMEX_WITH_SPACES) + cardNumberEditText.setText(AMEX_WITH_SPACES) val shiftedParameters = cardInputWidget.placementParameters assertEquals(50, shiftedParameters.peekCardWidth) assertEquals(175, shiftedParameters.cardDateSeparation) @@ -945,7 +945,7 @@ internal class CardInputWidgetTest : BaseViewTest( // Moving left with an AmEx number has a larger peek and cvc size. // |(peek==50)--(space==88)--(date==50)--(space==72)--(cvc==40)--(space==0)--(postal==100)| - cardNumberEditText.setText(VALID_AMEX_WITH_SPACES) + cardNumberEditText.setText(AMEX_WITH_SPACES) val shiftedParameters = cardInputWidget.placementParameters assertEquals(50, shiftedParameters.peekCardWidth) assertEquals(88, shiftedParameters.cardDateSeparation) @@ -962,7 +962,7 @@ internal class CardInputWidgetTest : BaseViewTest( // When we move for a Diner's club card, the peek text is shorter, so we expect: // |(peek==20)--(space==205)--(date==50)--(space==195)--(cvc==30)| - cardNumberEditText.setText(VALID_DINERS_CLUB_WITH_SPACES) + cardNumberEditText.setText(DINERS_CLUB_14_WITH_SPACES) val shiftedParameters = cardInputWidget.placementParameters assertEquals(20, shiftedParameters.peekCardWidth) assertEquals(205, shiftedParameters.cardDateSeparation) @@ -979,7 +979,7 @@ internal class CardInputWidgetTest : BaseViewTest( // When we move for a Diner's club card, the peek text is shorter, so we expect: // |(peek==20)--(space==205)--(date==50)--(space==195)--(cvc==30)--(space==0)--(postal==100)| - cardNumberEditText.setText(VALID_DINERS_CLUB_WITH_SPACES) + cardNumberEditText.setText(DINERS_CLUB_14_WITH_SPACES) val shiftedParameters = cardInputWidget.placementParameters assertEquals(20, shiftedParameters.peekCardWidth) assertEquals(118, shiftedParameters.cardDateSeparation) @@ -1018,7 +1018,7 @@ internal class CardInputWidgetTest : BaseViewTest( @Test fun setCvcCode_whenCardBrandIsAmericanExpress_allowsFourDigits() { - cardInputWidget.setCardNumber(VALID_AMEX_NO_SPACES) + cardInputWidget.setCardNumber(AMEX_NO_SPACES) cardInputWidget.setCvcCode(CVC_VALUE_AMEX) assertEquals("1234", cvcEditText.text.toString()) } @@ -1068,12 +1068,12 @@ internal class CardInputWidgetTest : BaseViewTest( cardInputWidget.postalCodeEnabled = false assertTrue(Calendar.getInstance().get(Calendar.YEAR) <= 2079) - cardInputWidget.setCardNumber(VALID_AMEX_WITH_SPACES) + cardInputWidget.setCardNumber(AMEX_WITH_SPACES) cardInputWidget.setExpiryDate(12, 2079) cardInputWidget.setCvcCode(CVC_VALUE_AMEX) val card = cardInputWidget.card assertNotNull(card) - assertEquals(VALID_AMEX_NO_SPACES, card.number) + assertEquals(AMEX_NO_SPACES, card.number) assertNotNull(card.expMonth) assertNotNull(card.expYear) assertEquals(12, card.expMonth) @@ -1084,7 +1084,7 @@ internal class CardInputWidgetTest : BaseViewTest( val paymentMethodCard = cardInputWidget.paymentMethodCard assertNotNull(paymentMethodCard) val expectedPaymentMethodCard = PaymentMethodCreateParams.Card( - number = VALID_AMEX_NO_SPACES, + number = AMEX_NO_SPACES, cvc = CVC_VALUE_AMEX, expiryMonth = 12, expiryYear = 2079, @@ -1098,13 +1098,13 @@ internal class CardInputWidgetTest : BaseViewTest( cardInputWidget.postalCodeEnabled = true assertTrue(Calendar.getInstance().get(Calendar.YEAR) <= 2079) - cardInputWidget.setCardNumber(VALID_AMEX_WITH_SPACES) + cardInputWidget.setCardNumber(AMEX_WITH_SPACES) cardInputWidget.setExpiryDate(12, 2079) cardInputWidget.setCvcCode(CVC_VALUE_AMEX) cardInputWidget.setPostalCode(POSTAL_CODE_VALUE) val card = cardInputWidget.card assertNotNull(card) - assertEquals(VALID_AMEX_NO_SPACES, card.number) + assertEquals(AMEX_NO_SPACES, card.number) assertNotNull(card.expMonth) assertNotNull(card.expYear) assertEquals(12, card.expMonth) @@ -1115,7 +1115,7 @@ internal class CardInputWidgetTest : BaseViewTest( val paymentMethodCard = cardInputWidget.paymentMethodCard assertNotNull(paymentMethodCard) val expectedPaymentMethodCard = PaymentMethodCreateParams.Card( - number = VALID_AMEX_NO_SPACES, + number = AMEX_NO_SPACES, cvc = CVC_VALUE_AMEX, expiryYear = 2079, expiryMonth = 12, @@ -1127,7 +1127,7 @@ internal class CardInputWidgetTest : BaseViewTest( @Test fun addValues_thenClear_withPostalCodeDisabled_leavesAllTextFieldsEmpty() { cardInputWidget.postalCodeEnabled = false - cardInputWidget.setCardNumber(VALID_VISA_NO_SPACES) + cardInputWidget.setCardNumber(VISA_NO_SPACES) cardInputWidget.setExpiryDate(12, 2079) cardInputWidget.setCvcCode(CVC_VALUE_AMEX) cardInputWidget.clear() @@ -1141,7 +1141,7 @@ internal class CardInputWidgetTest : BaseViewTest( @Test fun addValues_thenClear_withPostalCodeEnabled_leavesAllTextFieldsEmpty() { cardInputWidget.postalCodeEnabled = true - cardInputWidget.setCardNumber(VALID_VISA_NO_SPACES) + cardInputWidget.setCardNumber(VISA_NO_SPACES) cardInputWidget.setExpiryDate(12, 2079) cardInputWidget.setCvcCode(CVC_VALUE_AMEX) cardInputWidget.setPostalCode(POSTAL_CODE_VALUE) @@ -1237,7 +1237,7 @@ internal class CardInputWidgetTest : BaseViewTest( currentInvalidFields ) - cardInputWidget.setCardNumber(VALID_VISA_NO_SPACES) + cardInputWidget.setCardNumber(VISA_NO_SPACES) assertFalse(currentIsValid) assertEquals( setOf(CardValidCallback.Fields.Expiry, CardValidCallback.Fields.Cvc), diff --git a/stripe/src/test/java/com/stripe/android/view/CardMultilineWidgetTest.kt b/stripe/src/test/java/com/stripe/android/view/CardMultilineWidgetTest.kt index e4e3bb8444d..299c666c020 100644 --- a/stripe/src/test/java/com/stripe/android/view/CardMultilineWidgetTest.kt +++ b/stripe/src/test/java/com/stripe/android/view/CardMultilineWidgetTest.kt @@ -9,11 +9,11 @@ import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.never import com.nhaarman.mockitokotlin2.verify import com.stripe.android.ApiKeyFixtures -import com.stripe.android.CardNumberFixtures.VALID_AMEX_NO_SPACES -import com.stripe.android.CardNumberFixtures.VALID_AMEX_WITH_SPACES -import com.stripe.android.CardNumberFixtures.VALID_DINERS_CLUB_WITH_SPACES -import com.stripe.android.CardNumberFixtures.VALID_VISA_NO_SPACES -import com.stripe.android.CardNumberFixtures.VALID_VISA_WITH_SPACES +import com.stripe.android.CardNumberFixtures.AMEX_NO_SPACES +import com.stripe.android.CardNumberFixtures.AMEX_WITH_SPACES +import com.stripe.android.CardNumberFixtures.DINERS_CLUB_14_WITH_SPACES +import com.stripe.android.CardNumberFixtures.VISA_NO_SPACES +import com.stripe.android.CardNumberFixtures.VISA_WITH_SPACES import com.stripe.android.CustomerSession import com.stripe.android.PaymentConfiguration import com.stripe.android.R @@ -141,14 +141,14 @@ internal class CardMultilineWidgetTest { @Test fun getCard_whenInputIsValidVisaWithZip_returnsCardObjectWithLoggingToken() { - fullGroup.cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + fullGroup.cardNumberEditText.setText(VISA_WITH_SPACES) fullGroup.expiryDateEditText.append("12") fullGroup.expiryDateEditText.append("50") fullGroup.cvcEditText.append("123") fullGroup.postalCodeEditText.append("12345") val card = requireNotNull(cardMultilineWidget.card) - assertEquals(VALID_VISA_NO_SPACES, card.number) + assertEquals(VISA_NO_SPACES, card.number) assertNotNull(card.expMonth) assertNotNull(card.expYear) assertEquals(12, card.expMonth) @@ -161,7 +161,7 @@ internal class CardMultilineWidgetTest { @Test fun getCard_whenInputIsValidVisaButInputHasNoZip_returnsValidCard() { - fullGroup.cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + fullGroup.cardNumberEditText.setText(VISA_WITH_SPACES) fullGroup.expiryDateEditText.append("12") fullGroup.expiryDateEditText.append("50") fullGroup.cvcEditText.append("123") @@ -172,13 +172,13 @@ internal class CardMultilineWidgetTest { @Test fun getCard_whenInputIsValidVisaAndNoZipRequired_returnsFullCardAndExpectedLogging() { - noZipGroup.cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + noZipGroup.cardNumberEditText.setText(VISA_WITH_SPACES) noZipGroup.expiryDateEditText.append("12") noZipGroup.expiryDateEditText.append("50") noZipGroup.cvcEditText.append("123") val card = noZipCardMultilineWidget.card assertNotNull(card) - assertEquals(VALID_VISA_NO_SPACES, card.number) + assertEquals(VISA_NO_SPACES, card.number) assertNotNull(card.expMonth) assertNotNull(card.expYear) assertEquals(12, card.expMonth) @@ -191,13 +191,13 @@ internal class CardMultilineWidgetTest { @Test fun getCard_whenInputIsValidAmexAndNoZipRequiredAnd4DigitCvc_returnsFullCardAndExpectedLogging() { - noZipGroup.cardNumberEditText.setText(VALID_AMEX_WITH_SPACES) + noZipGroup.cardNumberEditText.setText(AMEX_WITH_SPACES) noZipGroup.expiryDateEditText.append("12") noZipGroup.expiryDateEditText.append("50") noZipGroup.cvcEditText.append("1234") val card = noZipCardMultilineWidget.card assertNotNull(card) - assertEquals(VALID_AMEX_NO_SPACES, card.number) + assertEquals(AMEX_NO_SPACES, card.number) assertNotNull(card.expMonth) assertNotNull(card.expYear) assertEquals(12, card.expMonth) @@ -210,13 +210,13 @@ internal class CardMultilineWidgetTest { @Test fun getCard_whenInputIsValidAmexAndNoZipRequiredAnd3DigitCvc_returnsFullCardAndExpectedLogging() { - noZipGroup.cardNumberEditText.setText(VALID_AMEX_WITH_SPACES) + noZipGroup.cardNumberEditText.setText(AMEX_WITH_SPACES) noZipGroup.expiryDateEditText.append("12") noZipGroup.expiryDateEditText.append("50") noZipGroup.cvcEditText.append("123") val card = noZipCardMultilineWidget.card assertNotNull(card) - assertEquals(VALID_AMEX_NO_SPACES, card.number) + assertEquals(AMEX_NO_SPACES, card.number) assertNotNull(card.expMonth) assertNotNull(card.expYear) assertEquals(12, card.expMonth) @@ -229,7 +229,7 @@ internal class CardMultilineWidgetTest { @Test fun getPaymentMethodCreateParams_shouldReturnExpectedObject() { - fullGroup.cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + fullGroup.cardNumberEditText.setText(VISA_WITH_SPACES) fullGroup.expiryDateEditText.append("12") fullGroup.expiryDateEditText.append("50") fullGroup.cvcEditText.append("123") @@ -240,7 +240,7 @@ internal class CardMultilineWidgetTest { val expectedParams = PaymentMethodCreateParams.create( PaymentMethodCreateParams.Card( - number = VALID_VISA_NO_SPACES, + number = VISA_NO_SPACES, cvc = "123", expiryMonth = 12, expiryYear = 2050, @@ -258,7 +258,7 @@ internal class CardMultilineWidgetTest { @Test fun paymentMethodCard_whenInputIsValidVisaWithZip_returnsCardAndBillingDetails() { - fullGroup.cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + fullGroup.cardNumberEditText.setText(VISA_WITH_SPACES) fullGroup.expiryDateEditText.append("12") fullGroup.expiryDateEditText.append("50") fullGroup.cvcEditText.append("123") @@ -268,7 +268,7 @@ internal class CardMultilineWidgetTest { assertNotNull(card) val inputCard = PaymentMethodCreateParams.Card( - number = VALID_VISA_NO_SPACES, + number = VISA_NO_SPACES, cvc = "123", expiryMonth = 12, expiryYear = 2050, @@ -287,7 +287,7 @@ internal class CardMultilineWidgetTest { cardMultilineWidget.setShouldShowPostalCode(true) cardMultilineWidget.postalCodeRequired = true - fullGroup.cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + fullGroup.cardNumberEditText.setText(VISA_WITH_SPACES) fullGroup.expiryDateEditText.append("12") fullGroup.expiryDateEditText.append("50") fullGroup.cvcEditText.append("123") @@ -300,7 +300,7 @@ internal class CardMultilineWidgetTest { cardMultilineWidget.setShouldShowPostalCode(true) cardMultilineWidget.postalCodeRequired = false - fullGroup.cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + fullGroup.cardNumberEditText.setText(VISA_WITH_SPACES) fullGroup.expiryDateEditText.append("12") fullGroup.expiryDateEditText.append("50") fullGroup.cvcEditText.append("123") @@ -313,7 +313,7 @@ internal class CardMultilineWidgetTest { cardMultilineWidget.setShouldShowPostalCode(true) cardMultilineWidget.postalCodeRequired = false - fullGroup.cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + fullGroup.cardNumberEditText.setText(VISA_WITH_SPACES) fullGroup.expiryDateEditText.append("12") fullGroup.expiryDateEditText.append("50") fullGroup.cvcEditText.append("123") @@ -323,7 +323,7 @@ internal class CardMultilineWidgetTest { @Test fun paymentMethodCard_whenInputIsValidVisaAndNoZipRequired_returnsFullCard() { - noZipGroup.cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + noZipGroup.cardNumberEditText.setText(VISA_WITH_SPACES) noZipGroup.expiryDateEditText.append("12") noZipGroup.expiryDateEditText.append("50") noZipGroup.cvcEditText.append("123") @@ -331,7 +331,7 @@ internal class CardMultilineWidgetTest { assertNotNull(card) val inputCard = PaymentMethodCreateParams.Card( - number = VALID_VISA_NO_SPACES, + number = VISA_NO_SPACES, cvc = "123", expiryMonth = 12, expiryYear = 2050, @@ -344,7 +344,7 @@ internal class CardMultilineWidgetTest { @Test fun paymentMethodCard_whenInputIsValidAmexAndNoZipRequiredAnd4DigitCvc_returnsFullCard() { - noZipGroup.cardNumberEditText.setText(VALID_AMEX_WITH_SPACES) + noZipGroup.cardNumberEditText.setText(AMEX_WITH_SPACES) noZipGroup.expiryDateEditText.append("12") noZipGroup.expiryDateEditText.append("50") noZipGroup.cvcEditText.append("1234") @@ -354,7 +354,7 @@ internal class CardMultilineWidgetTest { assertNotNull(card) val inputCard = PaymentMethodCreateParams.Card( - number = VALID_AMEX_NO_SPACES, + number = AMEX_NO_SPACES, cvc = "1234", expiryMonth = 12, expiryYear = 2050, @@ -367,7 +367,7 @@ internal class CardMultilineWidgetTest { @Test fun paymentMethodCard_whenInputIsValidAmexAndNoZipRequiredAnd3DigitCvc_returnsFullCard() { - noZipGroup.cardNumberEditText.setText(VALID_AMEX_WITH_SPACES) + noZipGroup.cardNumberEditText.setText(AMEX_WITH_SPACES) noZipGroup.expiryDateEditText.append("12") noZipGroup.expiryDateEditText.append("50") noZipGroup.cvcEditText.append("123") @@ -375,7 +375,7 @@ internal class CardMultilineWidgetTest { assertNotNull(card) val inputCard = PaymentMethodCreateParams.Card( - number = VALID_AMEX_NO_SPACES, + number = AMEX_NO_SPACES, cvc = "123", expiryMonth = 12, expiryYear = 2050, @@ -396,7 +396,7 @@ internal class CardMultilineWidgetTest { @Test fun clear_whenZipRequiredAndAllFieldsEntered_clearsAllfields() { - fullGroup.cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + fullGroup.cardNumberEditText.setText(VISA_WITH_SPACES) fullGroup.expiryDateEditText.append("12") fullGroup.expiryDateEditText.append("50") fullGroup.cvcEditText.append("123") @@ -413,8 +413,8 @@ internal class CardMultilineWidgetTest { @Test fun clear_whenFieldsInErrorState_clearsFieldsAndHidesErrors() { // Makes this 4242 4242 4242 4243 - val badVisa = VALID_VISA_WITH_SPACES - .substring(VALID_VISA_WITH_SPACES.length - 1) + "3" + val badVisa = VISA_WITH_SPACES + .substring(VISA_WITH_SPACES.length - 1) + "3" fullGroup.cardNumberEditText.setText(badVisa) fullGroup.expiryDateEditText.append("01") @@ -482,12 +482,12 @@ internal class CardMultilineWidgetTest { cardMultilineWidget.setCardInputListener(fullCardListener) noZipCardMultilineWidget.setCardInputListener(noZipCardListener) - fullGroup.cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + fullGroup.cardNumberEditText.setText(VISA_WITH_SPACES) verify(fullCardListener).onCardComplete() verify(fullCardListener).onFocusChange(FOCUS_EXPIRY) assertTrue(fullGroup.expiryDateEditText.hasFocus()) - noZipGroup.cardNumberEditText.setText(VALID_AMEX_WITH_SPACES) + noZipGroup.cardNumberEditText.setText(AMEX_WITH_SPACES) verify(noZipCardListener).onCardComplete() verify(noZipCardListener).onFocusChange(FOCUS_EXPIRY) assertTrue(noZipGroup.expiryDateEditText.hasFocus()) @@ -516,7 +516,7 @@ internal class CardMultilineWidgetTest { cardMultilineWidget.setCardInputListener(fullCardListener) noZipCardMultilineWidget.setCardInputListener(noZipCardListener) - fullGroup.cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + fullGroup.cardNumberEditText.setText(VISA_WITH_SPACES) fullGroup.expiryDateEditText.append("12") fullGroup.expiryDateEditText.append("50") fullGroup.cvcEditText.append("123") @@ -524,7 +524,7 @@ internal class CardMultilineWidgetTest { verify(fullCardListener).onFocusChange(FOCUS_POSTAL) assertTrue(fullGroup.postalCodeEditText.hasFocus()) - noZipGroup.cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + noZipGroup.cardNumberEditText.setText(VISA_WITH_SPACES) noZipGroup.expiryDateEditText.append("12") noZipGroup.expiryDateEditText.append("50") noZipGroup.cvcEditText.append("123") @@ -538,9 +538,9 @@ internal class CardMultilineWidgetTest { cardMultilineWidget.setCardInputListener(fullCardListener) noZipCardMultilineWidget.setCardInputListener(noZipCardListener) - val deleteOneCharacterString = VALID_VISA_WITH_SPACES - .substring(0, VALID_VISA_WITH_SPACES.length - 1) - fullGroup.cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + val deleteOneCharacterString = VISA_WITH_SPACES + .substring(0, VISA_WITH_SPACES.length - 1) + fullGroup.cardNumberEditText.setText(VISA_WITH_SPACES) reset(fullCardListener) assertTrue(fullGroup.expiryDateEditText.hasFocus()) @@ -550,7 +550,7 @@ internal class CardMultilineWidgetTest { assertTrue(fullGroup.cardNumberEditText.hasFocus()) assertEquals(deleteOneCharacterString, fullGroup.cardNumberEditText.text?.toString()) - noZipGroup.cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + noZipGroup.cardNumberEditText.setText(VISA_WITH_SPACES) reset(noZipCardListener) assertTrue(noZipGroup.expiryDateEditText.hasFocus()) @@ -593,7 +593,7 @@ internal class CardMultilineWidgetTest { fun deleteWhenEmpty_fromPostalCode_shiftsToCvc() { cardMultilineWidget.setCardInputListener(fullCardListener) - fullGroup.cardNumberEditText.setText(VALID_DINERS_CLUB_WITH_SPACES) + fullGroup.cardNumberEditText.setText(DINERS_CLUB_14_WITH_SPACES) fullGroup.expiryDateEditText.append("12") fullGroup.expiryDateEditText.append("50") fullGroup.cvcEditText.append("123") @@ -607,31 +607,31 @@ internal class CardMultilineWidgetTest { @Test fun setCardNumber_whenHasSpaces_canCreateValidCard() { - cardMultilineWidget.setCardNumber(VALID_VISA_NO_SPACES) + cardMultilineWidget.setCardNumber(VISA_NO_SPACES) fullGroup.expiryDateEditText.append("12") fullGroup.expiryDateEditText.append("50") fullGroup.cvcEditText.append("123") fullGroup.postalCodeEditText.append("12345") val card = cardMultilineWidget.card - assertEquals(VALID_VISA_NO_SPACES, card?.number) + assertEquals(VISA_NO_SPACES, card?.number) } @Test fun setCardNumber_whenHasNoSpaces_canCreateValidCard() { - cardMultilineWidget.setCardNumber(VALID_VISA_WITH_SPACES) + cardMultilineWidget.setCardNumber(VISA_WITH_SPACES) fullGroup.expiryDateEditText.append("12") fullGroup.expiryDateEditText.append("50") fullGroup.cvcEditText.append("123") fullGroup.postalCodeEditText.append("12345") val card = cardMultilineWidget.card - assertEquals(VALID_VISA_NO_SPACES, card?.number) + assertEquals(VISA_NO_SPACES, card?.number) } @Test fun validateCardNumber_whenValid_doesNotShowError() { - cardMultilineWidget.setCardNumber(VALID_VISA_WITH_SPACES) + cardMultilineWidget.setCardNumber(VISA_WITH_SPACES) val isValid = cardMultilineWidget.validateCardNumber() val shouldShowError = fullGroup.cardNumberEditText.shouldShowError @@ -713,7 +713,7 @@ internal class CardMultilineWidgetTest { currentInvalidFields ) - cardMultilineWidget.setCardNumber(VALID_VISA_NO_SPACES) + cardMultilineWidget.setCardNumber(VISA_NO_SPACES) assertFalse(currentIsValid) assertEquals( setOf(CardValidCallback.Fields.Expiry, CardValidCallback.Fields.Cvc), diff --git a/stripe/src/test/java/com/stripe/android/view/CardNumberEditTextTest.kt b/stripe/src/test/java/com/stripe/android/view/CardNumberEditTextTest.kt index c1d7058fbe2..4d60366a83b 100644 --- a/stripe/src/test/java/com/stripe/android/view/CardNumberEditTextTest.kt +++ b/stripe/src/test/java/com/stripe/android/view/CardNumberEditTextTest.kt @@ -2,12 +2,13 @@ package com.stripe.android.view import android.content.Context import androidx.test.core.app.ApplicationProvider -import com.stripe.android.CardNumberFixtures.VALID_AMEX_NO_SPACES -import com.stripe.android.CardNumberFixtures.VALID_AMEX_WITH_SPACES -import com.stripe.android.CardNumberFixtures.VALID_DINERS_CLUB_NO_SPACES -import com.stripe.android.CardNumberFixtures.VALID_DINERS_CLUB_WITH_SPACES -import com.stripe.android.CardNumberFixtures.VALID_VISA_NO_SPACES -import com.stripe.android.CardNumberFixtures.VALID_VISA_WITH_SPACES +import com.stripe.android.CardNumberFixtures.AMEX_NO_SPACES +import com.stripe.android.CardNumberFixtures.AMEX_WITH_SPACES +import com.stripe.android.CardNumberFixtures.DINERS_CLUB_14_NO_SPACES +import com.stripe.android.CardNumberFixtures.DINERS_CLUB_14_WITH_SPACES +import com.stripe.android.CardNumberFixtures.DINERS_CLUB_16_WITH_SPACES +import com.stripe.android.CardNumberFixtures.VISA_NO_SPACES +import com.stripe.android.CardNumberFixtures.VISA_WITH_SPACES import com.stripe.android.model.CardBrand import com.stripe.android.testharness.ViewTestUtils import kotlin.test.BeforeTest @@ -111,7 +112,7 @@ class CardNumberEditTextTest { @Test fun setText_whenTextIsValidCommonLengthNumber_changesCardValidState() { - cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + cardNumberEditText.setText(VISA_WITH_SPACES) assertTrue(cardNumberEditText.isCardNumberValid) assertEquals(1, completionCallbackInvocations) @@ -119,7 +120,7 @@ class CardNumberEditTextTest { @Test fun setText_whenTextIsSpacelessValidNumber_changesToSpaceNumberAndValidates() { - cardNumberEditText.setText(VALID_VISA_NO_SPACES) + cardNumberEditText.setText(VISA_NO_SPACES) assertTrue(cardNumberEditText.isCardNumberValid) assertEquals(1, completionCallbackInvocations) @@ -127,7 +128,7 @@ class CardNumberEditTextTest { @Test fun setText_whenTextIsValidAmExDinersClubLengthNumber_changesCardValidState() { - cardNumberEditText.setText(VALID_AMEX_WITH_SPACES) + cardNumberEditText.setText(AMEX_WITH_SPACES) assertTrue(cardNumberEditText.isCardNumberValid) assertEquals(1, completionCallbackInvocations) @@ -135,7 +136,7 @@ class CardNumberEditTextTest { @Test fun setText_whenTextChangesFromValidToInvalid_changesCardValidState() { - cardNumberEditText.setText(VALID_VISA_WITH_SPACES) + cardNumberEditText.setText(VISA_WITH_SPACES) // Simply setting the value interacts with this mock once -- that is tested elsewhere completionCallbackInvocations = 0 @@ -150,7 +151,7 @@ class CardNumberEditTextTest { @Test fun setText_whenTextIsInvalidCommonLengthNumber_doesNotNotifyListener() { // This creates a full-length but not valid number: 4242 4242 4242 4243 - val almostValid = VALID_VISA_WITH_SPACES.substring(0, 18) + "3" + val almostValid = VISA_WITH_SPACES.substring(0, 18) + "3" cardNumberEditText.setText(almostValid) assertFalse(cardNumberEditText.isCardNumberValid) assertEquals(0, completionCallbackInvocations) @@ -167,7 +168,7 @@ class CardNumberEditTextTest { @Test fun finishTypingCommonLengthCardNumber_whenValidCard_doesNotSetErrorValue() { - val almostThere = VALID_VISA_WITH_SPACES.substring(0, 18) + val almostThere = VISA_WITH_SPACES.substring(0, 18) cardNumberEditText.setText(almostThere) assertFalse(cardNumberEditText.shouldShowError) // We now have the valid 4242 Visa @@ -177,7 +178,7 @@ class CardNumberEditTextTest { @Test fun finishTypingCommonLengthCardNumber_whenInvalidCard_setsErrorValue() { - val almostThere = VALID_VISA_WITH_SPACES.substring(0, 18) + val almostThere = VISA_WITH_SPACES.substring(0, 18) cardNumberEditText.setText(almostThere) // This makes the number officially invalid cardNumberEditText.setText(cardNumberEditText.text?.toString() + "3") @@ -186,7 +187,7 @@ class CardNumberEditTextTest { @Test fun finishTypingInvalidCardNumber_whenFollowedByDelete_setsErrorBackToFalse() { - val notQuiteValid = VALID_VISA_WITH_SPACES.substring(0, 18) + "3" + val notQuiteValid = VISA_WITH_SPACES.substring(0, 18) + "3" cardNumberEditText.setText(notQuiteValid) assertTrue(cardNumberEditText.shouldShowError) @@ -196,8 +197,8 @@ class CardNumberEditTextTest { } @Test - fun finishTypingDinersClub_whenInvalid_setsErrorValueAndRemovesItAppropriately() { - val notQuiteValid = VALID_DINERS_CLUB_WITH_SPACES.substring(0, 16) + "3" + fun finishTypingDinersClub14_whenInvalid_setsErrorValueAndRemovesItAppropriately() { + val notQuiteValid = DINERS_CLUB_14_WITH_SPACES.take(DINERS_CLUB_14_WITH_SPACES.length - 1) + "3" cardNumberEditText.setText(notQuiteValid) assertTrue(cardNumberEditText.shouldShowError) @@ -205,13 +206,27 @@ class CardNumberEditTextTest { ViewTestUtils.sendDeleteKeyEvent(cardNumberEditText) assertFalse(cardNumberEditText.shouldShowError) - cardNumberEditText.setText(cardNumberEditText.text?.toString() + "4") + cardNumberEditText.setText(cardNumberEditText.text?.toString() + DINERS_CLUB_14_WITH_SPACES.last()) + assertFalse(cardNumberEditText.shouldShowError) + } + + @Test + fun finishTypingDinersClub16_whenInvalid_setsErrorValueAndRemovesItAppropriately() { + val notQuiteValid = DINERS_CLUB_16_WITH_SPACES.take(DINERS_CLUB_16_WITH_SPACES.length - 1) + "3" + cardNumberEditText.setText(notQuiteValid) + assertTrue(cardNumberEditText.shouldShowError) + + // Now that we're in an error state, back up by one + ViewTestUtils.sendDeleteKeyEvent(cardNumberEditText) + assertFalse(cardNumberEditText.shouldShowError) + + cardNumberEditText.setText(cardNumberEditText.text?.toString() + DINERS_CLUB_16_WITH_SPACES.last()) assertFalse(cardNumberEditText.shouldShowError) } @Test fun finishTypingAmEx_whenInvalid_setsErrorValueAndRemovesItAppropriately() { - val notQuiteValid = VALID_AMEX_WITH_SPACES.substring(0, 16) + "3" + val notQuiteValid = AMEX_WITH_SPACES.substring(0, 16) + "3" cardNumberEditText.setText(notQuiteValid) assertTrue(cardNumberEditText.shouldShowError) @@ -267,8 +282,8 @@ class CardNumberEditTextTest { @Test fun enterCompleteNumberInParts_onlyCallsBrandListenerOnce() { lastBrandChangeCallbackInvocation = null - val prefix = VALID_AMEX_WITH_SPACES.substring(0, 2) - val suffix = VALID_AMEX_WITH_SPACES.substring(2) + val prefix = AMEX_WITH_SPACES.substring(0, 2) + val suffix = AMEX_WITH_SPACES.substring(2) cardNumberEditText.setText(cardNumberEditText.text?.toString() + prefix) cardNumberEditText.setText(cardNumberEditText.text?.toString() + suffix) assertEquals(CardBrand.AmericanExpress, lastBrandChangeCallbackInvocation) @@ -310,27 +325,27 @@ class CardNumberEditTextTest { @Test fun getCardNumber_whenValidCard_returnsCardNumberWithoutSpaces() { - cardNumberEditText.setText(VALID_VISA_WITH_SPACES) - assertEquals(VALID_VISA_NO_SPACES, cardNumberEditText.cardNumber) + cardNumberEditText.setText(VISA_WITH_SPACES) + assertEquals(VISA_NO_SPACES, cardNumberEditText.cardNumber) - cardNumberEditText.setText(VALID_AMEX_WITH_SPACES) - assertEquals(VALID_AMEX_NO_SPACES, cardNumberEditText.cardNumber) + cardNumberEditText.setText(AMEX_WITH_SPACES) + assertEquals(AMEX_NO_SPACES, cardNumberEditText.cardNumber) - cardNumberEditText.setText(VALID_DINERS_CLUB_WITH_SPACES) - assertEquals(VALID_DINERS_CLUB_NO_SPACES, cardNumberEditText.cardNumber) + cardNumberEditText.setText(DINERS_CLUB_14_WITH_SPACES) + assertEquals(DINERS_CLUB_14_NO_SPACES, cardNumberEditText.cardNumber) } @Test fun getCardNumber_whenIncompleteCard_returnsNull() { cardNumberEditText.setText( - VALID_DINERS_CLUB_WITH_SPACES - .substring(0, VALID_DINERS_CLUB_WITH_SPACES.length - 2)) + DINERS_CLUB_14_WITH_SPACES + .substring(0, DINERS_CLUB_14_WITH_SPACES.length - 2)) assertNull(cardNumberEditText.cardNumber) } @Test fun getCardNumber_whenInvalidCardNumber_returnsNull() { - var almostVisa = VALID_VISA_WITH_SPACES.substring(0, VALID_VISA_WITH_SPACES.length - 1) + var almostVisa = VISA_WITH_SPACES.substring(0, VISA_WITH_SPACES.length - 1) almostVisa += "3" // creates the 4242 4242 4242 4243 bad number cardNumberEditText.setText(almostVisa) assertNull(cardNumberEditText.cardNumber) @@ -338,7 +353,7 @@ class CardNumberEditTextTest { @Test fun getCardNumber_whenValidNumberIsChangedToInvalid_returnsNull() { - cardNumberEditText.setText(VALID_AMEX_WITH_SPACES) + cardNumberEditText.setText(AMEX_WITH_SPACES) ViewTestUtils.sendDeleteKeyEvent(cardNumberEditText) assertNull(cardNumberEditText.cardNumber) @@ -354,9 +369,9 @@ class CardNumberEditTextTest { @Test fun testUpdateCardBrandFromNumber() { - cardNumberEditText.updateCardBrandFromNumber(VALID_DINERS_CLUB_NO_SPACES) + cardNumberEditText.updateCardBrandFromNumber(DINERS_CLUB_14_NO_SPACES) assertEquals(CardBrand.DinersClub, lastBrandChangeCallbackInvocation) - cardNumberEditText.updateCardBrandFromNumber(VALID_AMEX_NO_SPACES) + cardNumberEditText.updateCardBrandFromNumber(AMEX_NO_SPACES) assertEquals(CardBrand.AmericanExpress, lastBrandChangeCallbackInvocation) } diff --git a/stripe/src/test/java/com/stripe/android/view/ViewUtilsTest.kt b/stripe/src/test/java/com/stripe/android/view/ViewUtilsTest.kt index 29d08b294ab..a99a4d9fce2 100644 --- a/stripe/src/test/java/com/stripe/android/view/ViewUtilsTest.kt +++ b/stripe/src/test/java/com/stripe/android/view/ViewUtilsTest.kt @@ -1,9 +1,9 @@ package com.stripe.android.view +import com.google.common.truth.Truth.assertThat +import com.stripe.android.CardNumberFixtures import com.stripe.android.model.CardBrand import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNull import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner @@ -14,118 +14,126 @@ import org.robolectric.RobolectricTestRunner internal class ViewUtilsTest { @Test - fun separateCardNumberGroups_withVisa_returnsCorrectCardGroups() { - val testCardNumber = "4000056655665556" - val groups = - ViewUtils.separateCardNumberGroups(testCardNumber, CardBrand.Visa) - assertEquals(4, groups.size) - assertEquals("4000", groups[0]) - assertEquals("0566", groups[1]) - assertEquals("5566", groups[2]) - assertEquals("5556", groups[3]) + fun separateCardNumberGroups_withVisaDebit_returnsCorrectCardGroups() { + assertThat( + ViewUtils.separateCardNumberGroups( + CardNumberFixtures.VISA_DEBIT_NO_SPACES, + CardBrand.Visa + ) + ).isEqualTo( + arrayOf("4000", "0566", "5566", "5556") + ) } @Test fun separateCardNumberGroups_withAmex_returnsCorrectCardGroups() { - val testCardNumber = "378282246310005" - val groups = - ViewUtils.separateCardNumberGroups(testCardNumber, CardBrand.AmericanExpress) - assertEquals(3, groups.size) - assertEquals("3782", groups[0]) - assertEquals("822463", groups[1]) - assertEquals("10005", groups[2]) + assertThat( + ViewUtils.separateCardNumberGroups( + CardNumberFixtures.AMEX_NO_SPACES, + CardBrand.AmericanExpress + ) + ).isEqualTo( + arrayOf("3782", "822463", "10005") + ) } @Test - fun separateCardNumberGroups_withDinersClub_returnsCorrectCardGroups() { - val testCardNumber = "38520000023237" - val groups = - ViewUtils.separateCardNumberGroups(testCardNumber, CardBrand.DinersClub) - assertEquals(4, groups.size) - assertEquals("3852", groups[0]) - assertEquals("0000", groups[1]) - assertEquals("0232", groups[2]) - assertEquals("37", groups[3]) + fun separateCardNumberGroups_withDinersClub14_returnsCorrectCardGroups() { + assertThat( + ViewUtils.separateCardNumberGroups( + CardNumberFixtures.DINERS_CLUB_14_NO_SPACES, + CardBrand.DinersClub + ) + ).isEqualTo( + arrayOf("3622", "7206", "2716", "67") + ) } @Test fun separateCardNumberGroups_withInvalid_returnsCorrectCardGroups() { - val testCardNumber = "1234056655665556" - val groups = - ViewUtils.separateCardNumberGroups(testCardNumber, CardBrand.Unknown) - assertEquals(4, groups.size) - assertEquals("1234", groups[0]) - assertEquals("0566", groups[1]) - assertEquals("5566", groups[2]) - assertEquals("5556", groups[3]) + assertThat( + ViewUtils.separateCardNumberGroups( + "1234056655665556", + CardBrand.Unknown + ) + ).isEqualTo( + arrayOf("1234", "0566", "5566", "5556") + ) } @Test fun separateCardNumberGroups_withAmexPrefix_returnsPrefixGroups() { - val testCardNumber = "378282246310005" - var groups = ViewUtils.separateCardNumberGroups( - testCardNumber.substring(0, 2), CardBrand.AmericanExpress) - assertEquals(3, groups.size) - assertEquals("37", groups[0]) - assertNull(groups[1]) - assertNull(groups[2]) + assertThat( + ViewUtils.separateCardNumberGroups( + CardNumberFixtures.AMEX_NO_SPACES.take(2), + CardBrand.AmericanExpress + ) + ).isEqualTo( + arrayOf("37", null, null) + ) - groups = ViewUtils.separateCardNumberGroups( - testCardNumber.substring(0, 5), CardBrand.AmericanExpress) - assertEquals(3, groups.size) - assertEquals("3782", groups[0]) - assertEquals("8", groups[1]) - assertNull(groups[2]) + assertThat( + ViewUtils.separateCardNumberGroups( + CardNumberFixtures.AMEX_NO_SPACES.take(5), + CardBrand.AmericanExpress + ) + ).isEqualTo( + arrayOf("3782", "8", null) + ) - groups = ViewUtils.separateCardNumberGroups( - testCardNumber.substring(0, 11), CardBrand.AmericanExpress) - assertEquals(3, groups.size) - assertEquals("3782", groups[0]) - assertEquals("822463", groups[1]) - assertEquals("1", groups[2]) + assertThat( + ViewUtils.separateCardNumberGroups( + CardNumberFixtures.AMEX_NO_SPACES.take(11), + CardBrand.AmericanExpress + ) + ).isEqualTo( + arrayOf("3782", "822463", "1") + ) } @Test fun separateCardNumberGroups_withVisaPrefix_returnsCorrectGroups() { - val testCardNumber = "4000056655665556" - var groups = ViewUtils.separateCardNumberGroups( - testCardNumber.substring(0, 2), CardBrand.Visa) - assertEquals(4, groups.size) - assertEquals("40", groups[0]) - assertNull(groups[1]) - assertNull(groups[2]) - assertNull(groups[3]) + assertThat( + ViewUtils.separateCardNumberGroups( + CardNumberFixtures.VISA_DEBIT_NO_SPACES.take(2), + CardBrand.Visa + ) + ).isEqualTo( + arrayOf("40", null, null, null) + ) - groups = ViewUtils.separateCardNumberGroups( - testCardNumber.substring(0, 5), CardBrand.Visa) - assertEquals(4, groups.size) - assertEquals("4000", groups[0]) - assertEquals("0", groups[1]) - assertNull(groups[2]) - assertNull(groups[3]) + assertThat( + ViewUtils.separateCardNumberGroups( + CardNumberFixtures.VISA_DEBIT_NO_SPACES.take(5), + CardBrand.Visa + ) + ).isEqualTo( + arrayOf("4000", "0", null, null) + ) - groups = ViewUtils.separateCardNumberGroups( - testCardNumber.substring(0, 9), CardBrand.Visa) - assertEquals(4, groups.size) - assertEquals("4000", groups[0]) - assertEquals("0566", groups[1]) - assertEquals("5", groups[2]) - assertNull(groups[3]) + assertThat( + ViewUtils.separateCardNumberGroups( + CardNumberFixtures.VISA_DEBIT_NO_SPACES.take(9), + CardBrand.Visa + ) + ).isEqualTo( + arrayOf("4000", "0566", "5", null) + ) - groups = ViewUtils.separateCardNumberGroups( - testCardNumber.substring(0, 15), CardBrand.Visa) - assertEquals(4, groups.size) - assertEquals("4000", groups[0]) - assertEquals("0566", groups[1]) - assertEquals("5566", groups[2]) - assertEquals("555", groups[3]) + assertThat( + ViewUtils.separateCardNumberGroups( + CardNumberFixtures.VISA_DEBIT_NO_SPACES.take(15), + CardBrand.Visa + ) + ).isEqualTo( + arrayOf("4000", "0566", "5566", "555") + ) } @Test fun separateCardNumberGroups_forLongInputs_doesNotCrash() { - val testCardNumber = "1234567890123456789" - val groups = ViewUtils.separateCardNumberGroups( - testCardNumber, CardBrand.Visa) - assertEquals(4, groups.size) + assertThat( + ViewUtils.separateCardNumberGroups("1234567890123456789", CardBrand.Visa) + ).hasLength(4) } } From 72e6bf7ec7b503c66150bb6fa4c65ce48967ad77 Mon Sep 17 00:00:00 2001 From: Michael Shafrir Date: Fri, 21 Feb 2020 14:06:00 -0500 Subject: [PATCH 2/3] Use a single enum value for all Diners Club - Rename `maxLengthWithoutSpaces` to `defaultMaxLength` - Rename `maxLengthWithSpaces` to `defaultMaxLengthWithSpaces` - Create `getMaxLengthForCardNumber()` and `getMaxLengthWithSpacesForCardNumber()` to determine the max length based on the card number's prefix --- .../main/java/com/stripe/android/CardUtils.kt | 8 +-- .../java/com/stripe/android/model/Card.kt | 2 +- .../com/stripe/android/model/CardBrand.kt | 62 ++++++++++++------- .../stripe/android/view/CardNumberEditText.kt | 4 +- .../com/stripe/android/CardNumberFixtures.kt | 2 +- .../java/com/stripe/android/CardUtilsTest.kt | 58 ++++++++--------- .../com/stripe/android/model/CardBrandTest.kt | 12 +++- .../android/view/CardNumberEditTextTest.kt | 15 ++++- 8 files changed, 100 insertions(+), 63 deletions(-) diff --git a/stripe/src/main/java/com/stripe/android/CardUtils.kt b/stripe/src/main/java/com/stripe/android/CardUtils.kt index aa68b4779a2..a3f7727bcc2 100644 --- a/stripe/src/main/java/com/stripe/android/CardUtils.kt +++ b/stripe/src/main/java/com/stripe/android/CardUtils.kt @@ -13,8 +13,8 @@ object CardUtils { * or [CardBrand.Unknown] if it can't be determined */ @JvmStatic - fun getPossibleCardType(cardNumber: String?): CardBrand { - return getPossibleCardType(cardNumber, true) + fun getPossibleCardBrand(cardNumber: String?): CardBrand { + return getPossibleCardBrand(cardNumber, true) } /** @@ -76,10 +76,10 @@ object CardUtils { */ internal fun isValidCardLength(cardNumber: String?): Boolean { return cardNumber != null && - getPossibleCardType(cardNumber, false).isValidCardNumberLength(cardNumber) + getPossibleCardBrand(cardNumber, false).isValidCardNumberLength(cardNumber) } - private fun getPossibleCardType(cardNumber: String?, shouldNormalize: Boolean): CardBrand { + private fun getPossibleCardBrand(cardNumber: String?, shouldNormalize: Boolean): CardBrand { if (cardNumber.isNullOrBlank()) { return CardBrand.Unknown } diff --git a/stripe/src/main/java/com/stripe/android/model/Card.kt b/stripe/src/main/java/com/stripe/android/model/Card.kt index 05d696d5790..b0ec2ad6165 100644 --- a/stripe/src/main/java/com/stripe/android/model/Card.kt +++ b/stripe/src/main/java/com/stripe/android/model/Card.kt @@ -501,7 +501,7 @@ data class Card internal constructor( addressZipCheck = addressZipCheck.takeUnless { it.isNullOrBlank() }, addressCountry = addressCountry.takeUnless { it.isNullOrBlank() }, last4 = last4, - brand = brand ?: CardUtils.getPossibleCardType(number), + brand = brand ?: CardUtils.getPossibleCardBrand(number), fingerprint = fingerprint.takeUnless { it.isNullOrBlank() }, funding = funding, country = country.takeUnless { it.isNullOrBlank() }, diff --git a/stripe/src/main/java/com/stripe/android/model/CardBrand.kt b/stripe/src/main/java/com/stripe/android/model/CardBrand.kt index ff0c19db87d..5f97dc7e312 100644 --- a/stripe/src/main/java/com/stripe/android/model/CardBrand.kt +++ b/stripe/src/main/java/com/stripe/android/model/CardBrand.kt @@ -18,14 +18,12 @@ enum class CardBrand( val cvcLength: Set = setOf(3), /** - * The max length when the card number is formatted with spaces (e.g. "4242 4242 4242 4242") - */ - val maxLengthWithSpaces: Int = 19, - - /** - * The max length when the card number is formatted without spaces (e.g. "4242424242424242") + * The default max length when the card number is formatted without spaces (e.g. "4242424242424242") + * + * Note that [CardBrand.DinersClub]'s max length depends on the BIN (e.g. card number prefix). + * In the case of a [CardBrand.DinersClub] card, use [getMaxLengthForCardNumber]. */ - val maxLengthWithoutSpaces: Int = 16, + val defaultMaxLength: Int = 16, /** * Based on [Issuer identification number table](http://en.wikipedia.org/wiki/Bank_card_number#Issuer_identification_number_.28IIN.29) @@ -37,7 +35,12 @@ enum class CardBrand( * formatted to "4242 4242 4242 4242". The spaces in that number are at the positions * specified by [spacePositions]. */ - val spacePositions: Set = setOf(4, 9, 14) + val spacePositions: Set = setOf(4, 9, 14), + + /** + * By default, a [CardBrand] does not have variants. + */ + private val variantMaxLength: Map = emptyMap() ) { AmericanExpress( "amex", @@ -45,8 +48,7 @@ enum class CardBrand( R.drawable.stripe_ic_amex, cvcIcon = R.drawable.stripe_ic_cvc_amex, cvcLength = setOf(3, 4), - maxLengthWithSpaces = 17, - maxLengthWithoutSpaces = 15, + defaultMaxLength = 15, prefixes = listOf("34", "37"), spacePositions = setOf(4, 11) ), @@ -70,22 +72,16 @@ enum class CardBrand( "diners", "Diners Club", R.drawable.stripe_ic_diners, - maxLengthWithSpaces = 17, - maxLengthWithoutSpaces = 14, + defaultMaxLength = 16, prefixes = listOf( - "36" - ) - ), + // 14-digits + "36", - // 16-digit Diners Club - DinersClub16( - "diners", - "Diners Club", - R.drawable.stripe_ic_diners, - maxLengthWithSpaces = 19, - maxLengthWithoutSpaces = 16, - prefixes = listOf( + // 16-digits "30", "38", "39" + ), + variantMaxLength = mapOf( + "36" to 14 ) ), @@ -121,6 +117,8 @@ enum class CardBrand( cvcLength = setOf(3, 4) ); + val defaultMaxLengthWithSpaces: Int = defaultMaxLength + spacePositions.size + val maxCvcLength: Int get() { return cvcLength.max() ?: CVC_COMMON_LENGTH @@ -135,7 +133,7 @@ enum class CardBrand( */ fun isValidCardNumberLength(cardNumber: String?): Boolean { return cardNumber != null && Unknown != this && - cardNumber.length == maxLengthWithoutSpaces + cardNumber.length == getMaxLengthForCardNumber(cardNumber) } fun isValidCvc(cvc: String): Boolean { @@ -147,6 +145,22 @@ enum class CardBrand( return maxCvcLength == cvcLength } + /** + * If the [CardBrand] has variants, and the [cardNumber] starts with one of the variant + * prefixes, return the length for that variant. Otherwise, return [defaultMaxLength]. + * + * Note: currently only [CardBrand.DinersClub] has variants + */ + fun getMaxLengthForCardNumber(cardNumber: String): Int { + return variantMaxLength.entries.firstOrNull { (key, _) -> + cardNumber.startsWith(key) + }?.value ?: defaultMaxLength + } + + fun getMaxLengthWithSpacesForCardNumber(cardNumber: String): Int { + return getMaxLengthForCardNumber(cardNumber) + spacePositions.size + } + companion object { /** * @param cardNumber a card number diff --git a/stripe/src/main/java/com/stripe/android/view/CardNumberEditText.kt b/stripe/src/main/java/com/stripe/android/view/CardNumberEditText.kt index c4acb0bb9a8..b0464199813 100644 --- a/stripe/src/main/java/com/stripe/android/view/CardNumberEditText.kt +++ b/stripe/src/main/java/com/stripe/android/view/CardNumberEditText.kt @@ -39,7 +39,7 @@ class CardNumberEditText @JvmOverloads constructor( val lengthMax: Int get() { - return cardBrand.maxLengthWithSpaces + return cardBrand.getMaxLengthWithSpacesForCardNumber(fieldText) } private var ignoreChanges = false @@ -214,7 +214,7 @@ class CardNumberEditText @JvmOverloads constructor( @JvmSynthetic internal fun updateCardBrandFromNumber(partialNumber: String) { - updateCardBrand(CardUtils.getPossibleCardType(partialNumber)) + updateCardBrand(CardUtils.getPossibleCardBrand(partialNumber)) } internal companion object { diff --git a/stripe/src/test/java/com/stripe/android/CardNumberFixtures.kt b/stripe/src/test/java/com/stripe/android/CardNumberFixtures.kt index 570f10de71e..f3ffa97694c 100644 --- a/stripe/src/test/java/com/stripe/android/CardNumberFixtures.kt +++ b/stripe/src/test/java/com/stripe/android/CardNumberFixtures.kt @@ -16,7 +16,7 @@ internal object CardNumberFixtures { const val MASTERCARD_WITH_SPACES = "5555 5555 5555 4444" const val DINERS_CLUB_14_NO_SPACES: String = "36227206271667" - const val DINERS_CLUB_14_WITH_SPACES: String = "3622 720627 1667" + const val DINERS_CLUB_14_WITH_SPACES: String = "3622 7206 2716 67" const val DINERS_CLUB_16_NO_SPACES = "3056930009020004" const val DINERS_CLUB_16_WITH_SPACES = "3056 9300 0902 0004" diff --git a/stripe/src/test/java/com/stripe/android/CardUtilsTest.kt b/stripe/src/test/java/com/stripe/android/CardUtilsTest.kt index 29543fe9ad2..4dec07a7b26 100644 --- a/stripe/src/test/java/com/stripe/android/CardUtilsTest.kt +++ b/stripe/src/test/java/com/stripe/android/CardUtilsTest.kt @@ -12,67 +12,67 @@ import kotlin.test.assertTrue class CardUtilsTest { @Test - fun getPossibleCardType_withEmptyCard_returnsUnknown() { - assertEquals(CardBrand.Unknown, CardUtils.getPossibleCardType(" ")) + fun getPossibleCardBrand_withEmptyCard_returnsUnknown() { + assertEquals(CardBrand.Unknown, CardUtils.getPossibleCardBrand(" ")) } @Test - fun getPossibleCardType_withNullCardNumber_returnsUnknown() { - assertEquals(CardBrand.Unknown, CardUtils.getPossibleCardType(null)) + fun getPossibleCardBrand_withNullCardNumber_returnsUnknown() { + assertEquals(CardBrand.Unknown, CardUtils.getPossibleCardBrand(null)) } @Test - fun getPossibleCardType_withVisaPrefix_returnsVisa() { - assertEquals(CardBrand.Visa, CardUtils.getPossibleCardType("4899 99")) - assertEquals(CardBrand.Visa, CardUtils.getPossibleCardType("4")) + fun getPossibleCardBrand_withVisaPrefix_returnsVisa() { + assertEquals(CardBrand.Visa, CardUtils.getPossibleCardBrand("4899 99")) + assertEquals(CardBrand.Visa, CardUtils.getPossibleCardBrand("4")) } @Test - fun getPossibleCardType_withAmexPrefix_returnsAmex() { - assertEquals(CardBrand.AmericanExpress, CardUtils.getPossibleCardType("345")) - assertEquals(CardBrand.AmericanExpress, CardUtils.getPossibleCardType("37999999999")) + fun getPossibleCardBrand_withAmexPrefix_returnsAmex() { + assertEquals(CardBrand.AmericanExpress, CardUtils.getPossibleCardBrand("345")) + assertEquals(CardBrand.AmericanExpress, CardUtils.getPossibleCardBrand("37999999999")) } @Test - fun getPossibleCardType_withJCBPrefix_returnsJCB() { - assertEquals(CardBrand.JCB, CardUtils.getPossibleCardType("3535 3535")) + fun getPossibleCardBrand_withJCBPrefix_returnsJCB() { + assertEquals(CardBrand.JCB, CardUtils.getPossibleCardBrand("3535 3535")) } @Test - fun getPossibleCardType_withMasterCardPrefix_returnsMasterCard() { - assertEquals(CardBrand.MasterCard, CardUtils.getPossibleCardType("2222 452")) - assertEquals(CardBrand.MasterCard, CardUtils.getPossibleCardType("5050")) + fun getPossibleCardBrand_withMasterCardPrefix_returnsMasterCard() { + assertEquals(CardBrand.MasterCard, CardUtils.getPossibleCardBrand("2222 452")) + assertEquals(CardBrand.MasterCard, CardUtils.getPossibleCardBrand("5050")) } @Test - fun getPossibleCardType_withDinersClub16Prefix_returnsDinersClub16() { - assertEquals(CardBrand.DinersClub16, CardUtils.getPossibleCardType("303922 2234")) + fun getPossibleCardBrand_withDinersClub16Prefix_returnsDinersClub() { + assertEquals(CardBrand.DinersClub, CardUtils.getPossibleCardBrand("303922 2234")) } @Test - fun getPossibleCardType_withDinersClub14Prefix_returnsDinersClub() { - assertEquals(CardBrand.DinersClub, CardUtils.getPossibleCardType("36778 9098")) + fun getPossibleCardBrand_withDinersClub14Prefix_returnsDinersClub() { + assertEquals(CardBrand.DinersClub, CardUtils.getPossibleCardBrand("36778 9098")) } @Test - fun getPossibleCardType_withDiscoverPrefix_returnsDiscover() { - assertEquals(CardBrand.Discover, CardUtils.getPossibleCardType("60355")) - assertEquals(CardBrand.Discover, CardUtils.getPossibleCardType("6433 8 90923")) + fun getPossibleCardBrand_withDiscoverPrefix_returnsDiscover() { + assertEquals(CardBrand.Discover, CardUtils.getPossibleCardBrand("60355")) + assertEquals(CardBrand.Discover, CardUtils.getPossibleCardBrand("6433 8 90923")) // This one has too many numbers on purpose. Checking for length is not part of the // function under test. - assertEquals(CardBrand.Discover, CardUtils.getPossibleCardType("6523452309209340293423")) + assertEquals(CardBrand.Discover, CardUtils.getPossibleCardBrand("6523452309209340293423")) } @Test - fun getPossibleCardType_withUnionPayPrefix_returnsUnionPay() { - assertEquals(CardBrand.UnionPay, CardUtils.getPossibleCardType("62")) + fun getPossibleCardBrand_withUnionPayPrefix_returnsUnionPay() { + assertEquals(CardBrand.UnionPay, CardUtils.getPossibleCardBrand("62")) } @Test - fun getPossibleCardType_withNonsenseNumber_returnsUnknown() { - assertEquals(CardBrand.Unknown, CardUtils.getPossibleCardType("1234567890123456")) - assertEquals(CardBrand.Unknown, CardUtils.getPossibleCardType("9999 9999 9999 9999")) - assertEquals(CardBrand.Unknown, CardUtils.getPossibleCardType("3")) + fun getPossibleCardBrand_withNonsenseNumber_returnsUnknown() { + assertEquals(CardBrand.Unknown, CardUtils.getPossibleCardBrand("1234567890123456")) + assertEquals(CardBrand.Unknown, CardUtils.getPossibleCardBrand("9999 9999 9999 9999")) + assertEquals(CardBrand.Unknown, CardUtils.getPossibleCardBrand("3")) } @Test diff --git a/stripe/src/test/java/com/stripe/android/model/CardBrandTest.kt b/stripe/src/test/java/com/stripe/android/model/CardBrandTest.kt index 808dfb7d6b0..ede4d9d93e9 100644 --- a/stripe/src/test/java/com/stripe/android/model/CardBrandTest.kt +++ b/stripe/src/test/java/com/stripe/android/model/CardBrandTest.kt @@ -43,7 +43,7 @@ class CardBrandTest { @Test fun fromCardNumber_withDinersClub16() { assertEquals( - CardBrand.DinersClub16, + CardBrand.DinersClub, CardBrand.fromCardNumber(CardNumberFixtures.DINERS_CLUB_16_NO_SPACES) ) } @@ -78,6 +78,16 @@ class CardBrandTest { assertTrue( CardBrand.Visa.isValidCardNumberLength(CardNumberFixtures.VISA_NO_SPACES) ) + assertTrue( + CardBrand.DinersClub.isValidCardNumberLength( + CardNumberFixtures.DINERS_CLUB_16_NO_SPACES + ) + ) + assertTrue( + CardBrand.DinersClub.isValidCardNumberLength( + CardNumberFixtures.DINERS_CLUB_14_NO_SPACES + ) + ) assertFalse( CardBrand.Unknown.isValidCardNumberLength(CardNumberFixtures.VISA_NO_SPACES) ) diff --git a/stripe/src/test/java/com/stripe/android/view/CardNumberEditTextTest.kt b/stripe/src/test/java/com/stripe/android/view/CardNumberEditTextTest.kt index 4d60366a83b..d7553102c31 100644 --- a/stripe/src/test/java/com/stripe/android/view/CardNumberEditTextTest.kt +++ b/stripe/src/test/java/com/stripe/android/view/CardNumberEditTextTest.kt @@ -6,6 +6,7 @@ import com.stripe.android.CardNumberFixtures.AMEX_NO_SPACES import com.stripe.android.CardNumberFixtures.AMEX_WITH_SPACES import com.stripe.android.CardNumberFixtures.DINERS_CLUB_14_NO_SPACES import com.stripe.android.CardNumberFixtures.DINERS_CLUB_14_WITH_SPACES +import com.stripe.android.CardNumberFixtures.DINERS_CLUB_16_NO_SPACES import com.stripe.android.CardNumberFixtures.DINERS_CLUB_16_WITH_SPACES import com.stripe.android.CardNumberFixtures.VISA_NO_SPACES import com.stripe.android.CardNumberFixtures.VISA_WITH_SPACES @@ -324,17 +325,29 @@ class CardNumberEditTextTest { } @Test - fun getCardNumber_whenValidCard_returnsCardNumberWithoutSpaces() { + fun getCardNumber_whenVisaWithSpaces_returnsCardNumberWithoutSpaces() { cardNumberEditText.setText(VISA_WITH_SPACES) assertEquals(VISA_NO_SPACES, cardNumberEditText.cardNumber) + } + @Test + fun getCardNumber_whenAmexWithSpaces_returnsCardNumberWithoutSpaces() { cardNumberEditText.setText(AMEX_WITH_SPACES) assertEquals(AMEX_NO_SPACES, cardNumberEditText.cardNumber) + } + @Test + fun getCardNumber_withDinersClub14WithSpaces_returnsCardNumberWithoutSpaces() { cardNumberEditText.setText(DINERS_CLUB_14_WITH_SPACES) assertEquals(DINERS_CLUB_14_NO_SPACES, cardNumberEditText.cardNumber) } + @Test + fun getCardNumber_withDinersClub16WithSpaces_returnsCardNumberWithoutSpaces() { + cardNumberEditText.setText(DINERS_CLUB_16_WITH_SPACES) + assertEquals(DINERS_CLUB_16_NO_SPACES, cardNumberEditText.cardNumber) + } + @Test fun getCardNumber_whenIncompleteCard_returnsNull() { cardNumberEditText.setText( From 3967cdb163da3f1aae42c28690272a300f938d2b Mon Sep 17 00:00:00 2001 From: Michael Shafrir Date: Fri, 21 Feb 2020 15:44:18 -0500 Subject: [PATCH 3/3] Fix max length not updating Update max length whenever brand changes --- .../stripe/android/view/CardNumberEditText.kt | 25 +++++++------------ .../android/view/CardNumberEditTextTest.kt | 14 +++-------- 2 files changed, 13 insertions(+), 26 deletions(-) diff --git a/stripe/src/main/java/com/stripe/android/view/CardNumberEditText.kt b/stripe/src/main/java/com/stripe/android/view/CardNumberEditText.kt index b0464199813..f0357d87e0e 100644 --- a/stripe/src/main/java/com/stripe/android/view/CardNumberEditText.kt +++ b/stripe/src/main/java/com/stripe/android/view/CardNumberEditText.kt @@ -21,7 +21,14 @@ class CardNumberEditText @JvmOverloads constructor( @VisibleForTesting var cardBrand: CardBrand = CardBrand.Unknown - internal set + internal set(value) { + val prevBrand = field + field = value + if (value != prevBrand) { + brandChangeCallback(cardBrand) + updateLengthFilter() + } + } @JvmSynthetic internal var brandChangeCallback: (CardBrand) -> Unit = {} @@ -198,23 +205,9 @@ class CardNumberEditText @JvmOverloads constructor( }) } - private fun updateCardBrand(brand: CardBrand) { - if (cardBrand == brand) { - return - } - - val oldLength = lengthMax - - cardBrand = brand - brandChangeCallback(cardBrand) - if (oldLength != lengthMax) { - updateLengthFilter() - } - } - @JvmSynthetic internal fun updateCardBrandFromNumber(partialNumber: String) { - updateCardBrand(CardUtils.getPossibleCardBrand(partialNumber)) + cardBrand = CardUtils.getPossibleCardBrand(partialNumber) } internal companion object { diff --git a/stripe/src/test/java/com/stripe/android/view/CardNumberEditTextTest.kt b/stripe/src/test/java/com/stripe/android/view/CardNumberEditTextTest.kt index d7553102c31..01941545219 100644 --- a/stripe/src/test/java/com/stripe/android/view/CardNumberEditTextTest.kt +++ b/stripe/src/test/java/com/stripe/android/view/CardNumberEditTextTest.kt @@ -325,25 +325,19 @@ class CardNumberEditTextTest { } @Test - fun getCardNumber_whenVisaWithSpaces_returnsCardNumberWithoutSpaces() { + fun cardNumber_withSpaces_returnsCardNumberWithoutSpaces() { cardNumberEditText.setText(VISA_WITH_SPACES) assertEquals(VISA_NO_SPACES, cardNumberEditText.cardNumber) - } - @Test - fun getCardNumber_whenAmexWithSpaces_returnsCardNumberWithoutSpaces() { + cardNumberEditText.setText("") cardNumberEditText.setText(AMEX_WITH_SPACES) assertEquals(AMEX_NO_SPACES, cardNumberEditText.cardNumber) - } - @Test - fun getCardNumber_withDinersClub14WithSpaces_returnsCardNumberWithoutSpaces() { + cardNumberEditText.setText("") cardNumberEditText.setText(DINERS_CLUB_14_WITH_SPACES) assertEquals(DINERS_CLUB_14_NO_SPACES, cardNumberEditText.cardNumber) - } - @Test - fun getCardNumber_withDinersClub16WithSpaces_returnsCardNumberWithoutSpaces() { + cardNumberEditText.setText("") cardNumberEditText.setText(DINERS_CLUB_16_WITH_SPACES) assertEquals(DINERS_CLUB_16_NO_SPACES, cardNumberEditText.cardNumber) }