Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't enable the "save this card" checkbox by default #3076

Merged
merged 9 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## x.x.x xxxx-xx-xx
### PaymentSheet
* [Fixed] Fixed an issue where changing the country of a phone number would not update the UI when the phone number's validity changed.
* [Changed] The "save this card" checkbox is now unchecked by default. To change this behavior, set your PaymentSheet.Configuration.savePaymentMethodOptInBehavior to `.requiresOptOut`.

### Payments
* [Added] Updated support for MobilePay bindings.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,20 +210,10 @@ class PaymentSheetStandardUITests: PaymentSheetUITestCase {

// toggle save this card on and off
var saveThisCardToggle = app.switches["Save this card for future Example, Inc. payments"]
let expectDefaultSelectionOn = Locale.current.regionCode == "US"
if expectDefaultSelectionOn {
XCTAssertTrue(saveThisCardToggle.isSelected)
} else {
XCTAssertFalse(saveThisCardToggle.isSelected)
}
XCTAssertFalse(saveThisCardToggle.isSelected)
saveThisCardToggle.tap()
if expectDefaultSelectionOn {
XCTAssertFalse(saveThisCardToggle.isSelected)
} else {
XCTAssertTrue(saveThisCardToggle.isSelected)
saveThisCardToggle.tap() // toggle back off

}
XCTAssertTrue(saveThisCardToggle.isSelected)
saveThisCardToggle.tap() // toggle back off
XCTAssertFalse(saveThisCardToggle.isSelected)

// Complete payment
Expand Down Expand Up @@ -263,9 +253,7 @@ class PaymentSheetStandardUITests: PaymentSheetUITestCase {
try! fillCardData(app)
// toggle save this card on
saveThisCardToggle = app.switches["Save this card for future Example, Inc. payments"]
if !expectDefaultSelectionOn {
saveThisCardToggle.tap()
}
saveThisCardToggle.tap()
XCTAssertTrue(saveThisCardToggle.isSelected)

// Complete payment
Expand Down Expand Up @@ -796,18 +784,17 @@ class PaymentSheetStandardLPMUITests: PaymentSheetUITestCase {
let payButton = app.buttons["Pay $50.99"]
XCTAssertTrue(payButton.waitForExistence(timeout: 5))

let expectDefaultSelectionOn = Locale.current.regionCode == "US"
let selectedMandate =
"By saving your bank account for Example, Inc. you agree to authorize payments pursuant to these terms."
let unselectedMandate = "By continuing, you agree to authorize payments pursuant to these terms."
XCTAssertTrue(
app.textViews[expectDefaultSelectionOn ? selectedMandate : unselectedMandate].waitForExistence(timeout: 5)
app.textViews[unselectedMandate].waitForExistence(timeout: 5)
)

let saveThisAccountToggle = app.switches["Save this account for future Example, Inc. payments"]
saveThisAccountToggle.tap()
XCTAssertTrue(
app.textViews[expectDefaultSelectionOn ? unselectedMandate : selectedMandate].waitForExistence(timeout: 5)
app.textViews[selectedMandate].waitForExistence(timeout: 5)
)

// no pay button tap because linked account is stubbed/fake in UI test
Expand Down Expand Up @@ -1058,6 +1045,11 @@ class PaymentSheetStandardLPMUITests: PaymentSheetUITestCase {
// We should have selected cartes bancaires
XCTAssertTrue(app.textFields["Cartes Bancaires"].waitForExistence(timeout: 5))

// toggle save this card on
let saveThisCardToggle = app.switches["Save this card for future Example, Inc. payments"]
saveThisCardToggle.tap()
XCTAssertTrue(saveThisCardToggle.isSelected)

// Finish checkout
app.buttons["Pay €50.99"].tap()
let successText = app.staticTexts["Success!"]
Expand Down Expand Up @@ -2096,19 +2088,10 @@ class PaymentSheetDeferredServerSideUITests: PaymentSheetUITestCase {

// toggle save this card on and off
var saveThisCardToggle = app.switches["Save this card for future Example, Inc. payments"]
let expectDefaultSelectionOn = Locale.current.regionCode == "US"
if expectDefaultSelectionOn {
XCTAssertTrue(saveThisCardToggle.isSelected)
} else {
XCTAssertFalse(saveThisCardToggle.isSelected)
}
XCTAssertFalse(saveThisCardToggle.isSelected)
saveThisCardToggle.tap()
if expectDefaultSelectionOn {
XCTAssertFalse(saveThisCardToggle.isSelected)
} else {
XCTAssertTrue(saveThisCardToggle.isSelected)
saveThisCardToggle.tap() // toggle back off
}
XCTAssertTrue(saveThisCardToggle.isSelected)
saveThisCardToggle.tap() // toggle back off
XCTAssertFalse(saveThisCardToggle.isSelected)

// Complete payment
Expand All @@ -2125,9 +2108,7 @@ class PaymentSheetDeferredServerSideUITests: PaymentSheetUITestCase {

// toggle save this card on
saveThisCardToggle = app.switches["Save this card for future Example, Inc. payments"]
if !expectDefaultSelectionOn {
saveThisCardToggle.tap()
}
saveThisCardToggle.tap()
XCTAssertTrue(saveThisCardToggle.isSelected)

// Complete payment
Expand Down Expand Up @@ -2574,6 +2555,11 @@ class PaymentSheetDeferredServerSideUITests: PaymentSheetUITestCase {
app.buttons["+ Add"].waitForExistenceAndTap()
try fillCardData(app)

// toggle save this card on
let saveThisCardToggle = app.switches["Save this card for future Example, Inc. payments"]
saveThisCardToggle.tap()
XCTAssertTrue(saveThisCardToggle.isSelected)

app.buttons["Continue"].tap()
app.buttons["Confirm"].tap()
XCTAssertTrue(app.staticTexts["Success!"].waitForExistence(timeout: 5.0))
Expand Down Expand Up @@ -2609,6 +2595,11 @@ class PaymentSheetDeferredServerSideUITests: PaymentSheetUITestCase {

try! fillCardData(app)

// toggle save this card on
let saveThisCardToggle = app.switches["Save this card for future Example, Inc. payments"]
saveThisCardToggle.tap()
XCTAssertTrue(saveThisCardToggle.isSelected)

app.buttons["Continue"].tap()
app.buttons["Confirm"].tap()

Expand Down Expand Up @@ -2647,6 +2638,11 @@ class PaymentSheetDeferredServerSideUITests: PaymentSheetUITestCase {

try! fillCardData(app)

var saveThisCardToggle = app.switches["Save this card for future Example, Inc. payments"]
XCTAssertFalse(saveThisCardToggle.isSelected)
saveThisCardToggle.tap()
XCTAssertTrue(saveThisCardToggle.isSelected)

let payButton = app.buttons["Pay $50.99"]
XCTAssert(payButton.isEnabled)
payButton.tap()
Expand Down Expand Up @@ -2686,6 +2682,11 @@ class PaymentSheetDeferredServerSideUITests: PaymentSheetUITestCase {

try! fillCardData(app)

var saveThisCardToggle = app.switches["Save this card for future Example, Inc. payments"]
XCTAssertFalse(saveThisCardToggle.isSelected)
saveThisCardToggle.tap()
XCTAssertTrue(saveThisCardToggle.isSelected)

app.buttons["Continue"].tap()
app.buttons["Confirm"].tap()

Expand Down Expand Up @@ -2723,6 +2724,11 @@ class PaymentSheetDeferredServerSideUITests: PaymentSheetUITestCase {

try! fillCardData(app)

var saveThisCardToggle = app.switches["Save this card for future Example, Inc. payments"]
XCTAssertFalse(saveThisCardToggle.isSelected)
saveThisCardToggle.tap()
XCTAssertTrue(saveThisCardToggle.isSelected)

let payButton = app.buttons["Pay $50.99"]
XCTAssert(payButton.isEnabled)
payButton.tap()
Expand Down Expand Up @@ -2942,6 +2948,12 @@ class PaymentSheetLinkUITests: PaymentSheetUITestCase {

// Begin by saving a card for this new user who is not signed up for Link
try! fillCardData(app)

var saveThisCardToggle = app.switches["Save this card for future Example, Inc. payments"]
XCTAssertFalse(saveThisCardToggle.isSelected)
saveThisCardToggle.tap()
XCTAssertTrue(saveThisCardToggle.isSelected)

app.buttons["Pay $50.99"].tap()
XCTAssertTrue(app.staticTexts["Success!"].waitForExistence(timeout: 10.0))

Expand All @@ -2953,6 +2965,12 @@ class PaymentSheetLinkUITests: PaymentSheetUITestCase {
let addCardButton = app.buttons["+ Add"]
XCTAssertTrue(addCardButton.waitForExistence(timeout: 4.0))
addCardButton.tap()

saveThisCardToggle = app.switches["Save this card for future Example, Inc. payments"]
XCTAssertFalse(saveThisCardToggle.isSelected)
saveThisCardToggle.tap()
XCTAssertTrue(saveThisCardToggle.isSelected)

fillLinkAndPay(mode: .fieldConsent, cardNumber: "5555555555554444")

// reload w/ same customer
Expand All @@ -2976,6 +2994,12 @@ class PaymentSheetLinkUITests: PaymentSheetUITestCase {

// Setup a saved card to simulate having saved payment methods
try! fillCardData(app, postalEnabled: false) // postal pre-filled by default billing address

var saveThisCardToggle = app.switches["Save this card for future Example, Inc. payments"]
XCTAssertFalse(saveThisCardToggle.isSelected)
saveThisCardToggle.tap()
XCTAssertTrue(saveThisCardToggle.isSelected)

app.buttons["Pay $50.99"].tap()
XCTAssertTrue(app.staticTexts["Success!"].waitForExistence(timeout: 10.0))

Expand Down Expand Up @@ -3083,6 +3107,12 @@ class PaymentSheetLinkUITests: PaymentSheetUITestCase {
app.buttons["Payment method"].waitForExistenceAndTap()
// Begin by saving a card for this new user who is not signed up for Link
try! fillCardData(app)

var saveThisCardToggle = app.switches["Save this card for future Example, Inc. payments"]
XCTAssertFalse(saveThisCardToggle.isSelected)
saveThisCardToggle.tap()
XCTAssertTrue(saveThisCardToggle.isSelected)

app.buttons["Continue"].tap()
app.buttons["Confirm"].waitForExistenceAndTap()
XCTAssertTrue(app.staticTexts["Success!"].waitForExistence(timeout: 10.0))
Expand All @@ -3095,6 +3125,10 @@ class PaymentSheetLinkUITests: PaymentSheetUITestCase {
let addCardButton = app.buttons["+ Add"]
XCTAssertTrue(addCardButton.waitForExistence(timeout: 4.0))
addCardButton.tap()
saveThisCardToggle = app.switches["Save this card for future Example, Inc. payments"]
XCTAssertFalse(saveThisCardToggle.isSelected)
saveThisCardToggle.tap()
XCTAssertTrue(saveThisCardToggle.isSelected)
fillLinkAndPay(mode: .fieldConsent, uiStyle: .flowController, showLinkWalletButton: false)
}

Expand Down Expand Up @@ -3143,6 +3177,12 @@ class PaymentSheetLinkUITests: PaymentSheetUITestCase {

// Setup a saved card to simulate having saved payment methods
try! fillCardData(app, postalEnabled: false) // postal pre-filled by default billing address

// toggle save this card on
let saveThisCardToggle = app.switches["Save this card for future Example, Inc. payments"]
saveThisCardToggle.tap()
XCTAssertTrue(saveThisCardToggle.isSelected)

app.buttons["Continue"].tap()
app.buttons["Confirm"].waitForExistenceAndTap()
XCTAssertTrue(app.staticTexts["Success!"].waitForExistence(timeout: 10.0))
Expand Down Expand Up @@ -3348,8 +3388,15 @@ extension PaymentSheetUITestCase {
XCTAssertTrue(app.staticTexts["Success"].waitForExistence(timeout: 10))
app.buttons.matching(identifier: "Done").allElementsBoundByIndex.last?.tap()

if mode == .payment {
let saveThisAccountToggle = app.switches["Save this account for future Example, Inc. payments"]
XCTAssertFalse(saveThisAccountToggle.isSelected)
saveThisAccountToggle.tap()
}

// Confirm
let confirmButtonText = mode == .payment ? "Pay $50.99" : "Set up"

app.buttons[confirmButtonText].waitForExistenceAndTap()
let successText = app.staticTexts["Success!"]
XCTAssertTrue(successText.waitForExistence(timeout: 10.0))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ extension PaymentSheet {
public enum SavePaymentMethodOptInBehavior {

/// (Default) The SDK will apply opt-out behavior for supported countries.
/// Currently, this behavior is supported in the US.
/// Currently, we use requiresOptIn for all countries.
case automatic

/// The control will always default to unselected and users
Expand All @@ -61,8 +61,7 @@ extension PaymentSheet {
var isSelectedByDefault: Bool {
switch self {
case .automatic:
// only enable the save checkbox by default for US
return Locale.current.stp_regionCode == "US"
return false
Comment on lines 63 to +64
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably add this to our list of "things to break" in the next major version

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like having .automatic around just in case, maybe someday we can control it server-side

case .requiresOptIn:
return false
case .requiresOptOut:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1514,8 +1514,8 @@ class PaymentSheetFormFactoryTest: XCTestCase {
XCTAssertEqual(params.paymentMethodParams.card?.expMonth, cardValues.expMonth)
XCTAssertEqual(params.paymentMethodParams.card?.expYear, cardValues.expYear)
XCTAssertEqual(params.paymentMethodParams.card?.cvc, cardValues.cvc)
// ...and the checkbox state should be enabled (the default)
XCTAssertEqual(params.saveForFutureUseCheckboxState, .selected)
// ...and the checkbox state should be disabled (the default)
XCTAssertEqual(params.saveForFutureUseCheckboxState, .deselected)
}

func testAppliesPreviousCustomerInput_checkbox() {
Expand Down Expand Up @@ -1552,9 +1552,9 @@ class PaymentSheetFormFactoryTest: XCTestCase {

// Making another card form for payment using the previous card form's input...
let cardForm_payment = makeCardForm(isSettingUp: false, previousCustomerInput: cardForm_setup_params)
// ...should have the checkbox selected (the default)
// ...should have the checkbox deselected (the default)
let cardForm_payment_params = cardForm_payment.updateParams(params: .init(type: .stripe(.card)))
XCTAssertEqual(cardForm_payment_params?.saveForFutureUseCheckboxState, .selected)
XCTAssertEqual(cardForm_payment_params?.saveForFutureUseCheckboxState, .deselected)

// Deselecting the checkbox...
let saveCheckbox = cardForm_payment.getAllUnwrappedSubElements().compactMap({ $0 as? CheckboxElement }).first(where: { $0.label.hasPrefix("Save") })
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading