diff --git a/Example/PaymentSheet Example/PaymentSheetUITest/PaymentSheetVerticalUITest.swift b/Example/PaymentSheet Example/PaymentSheetUITest/PaymentSheetVerticalUITest.swift index 79a97d45f29..cd4d4eb6577 100644 --- a/Example/PaymentSheet Example/PaymentSheetUITest/PaymentSheetVerticalUITest.swift +++ b/Example/PaymentSheet Example/PaymentSheetUITest/PaymentSheetVerticalUITest.swift @@ -123,10 +123,13 @@ class PaymentSheetVerticalUITests: PaymentSheetUITestCase { // Fail payment app.buttons["Pay $50.99"].tap() app.waitForButtonOrStaticText("FAIL TEST PAYMENT").tap() - XCTAssertTrue(app.staticTexts["We are unable to authenticate your payment method. Please choose a different payment method and try again."].waitForExistence(timeout: 10)) + let errorMessage = app.staticTexts["We are unable to authenticate your payment method. Please choose a different payment method and try again."] + XCTAssertTrue(errorMessage.waitForExistence(timeout: 10)) // Try Cash App Pay app.buttons["Cash App Pay"].waitForExistenceAndTap() + // Validate error disappears + XCTAssertFalse(errorMessage.waitForExistence(timeout: 0.1)) app.buttons["Pay $50.99"].tap() app.waitForButtonOrStaticText("AUTHORIZE TEST PAYMENT").tap() XCTAssertTrue(app.staticTexts["Success!"].waitForExistence(timeout: 10)) @@ -184,7 +187,7 @@ class PaymentSheetVerticalUITests: PaymentSheetUITestCase { XCTAssertTrue(app.staticTexts["Select card"].waitForExistence(timeout: 5.0)) XCTAssertTrue(app.buttons["Edit"].waitForExistenceAndTap()) - // Remove both the payment methods just added + // Remove one of the payment methods just added app.buttons["CircularButton.Remove"].firstMatch.waitForExistenceAndTap() XCTAssertTrue(app.alerts.buttons["Remove"].waitForExistenceAndTap()) @@ -225,6 +228,8 @@ class PaymentSheetVerticalUITests: PaymentSheetUITestCase { XCTAssertTrue(app.buttons["Card"].waitForExistence(timeout: 5.0)) // Verify there's no more Saved section XCTAssertFalse(app.staticTexts["Saved"].waitForExistence(timeout: 0.1)) + // Verify primary button isn't enabled b/c there is no selected PM + XCTAssertFalse(app.buttons["Set up"].isEnabled) } private func setupCards(cards: [String], settings: PaymentSheetTestPlaygroundSettings) { diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/ViewControllers/PaymentSheetVerticalViewController.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/ViewControllers/PaymentSheetVerticalViewController.swift index 323b8b5acf0..22079507684 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/ViewControllers/PaymentSheetVerticalViewController.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/ViewControllers/PaymentSheetVerticalViewController.swift @@ -145,12 +145,9 @@ class PaymentSheetVerticalViewController: UIViewController, FlowControllerViewCo regenerateUI() // Only use the previous customer input for the first form shown self.previousPaymentOption = nil - updatePrimaryButton() - updateMandate(animated: false) - updateError() } - /// Regenerates the main content - either the PM list or the PM form + /// Regenerates the main content - either the PM list or the PM form and updates all UI elements (pay button, error, mandate) func regenerateUI(updatedListSelection: VerticalPaymentMethodListSelection? = nil) { // Remove any content vcs; we'll rebuild and add them now if let paymentMethodListViewController { @@ -182,6 +179,14 @@ class PaymentSheetVerticalViewController: UIViewController, FlowControllerViewCo add(childViewController: paymentMethodListViewController, containerView: paymentContainerView) } } + updateUI() + } + + /// Updates all UI elements (pay button, error, mandate) + func updateUI() { + updatePrimaryButton() + updateMandate() + updateError() } func updatePrimaryButton() { @@ -236,7 +241,7 @@ class PaymentSheetVerticalViewController: UIViewController, FlowControllerViewCo func updateError() { errorLabel.text = error?.nonGenericDescription - UIView.animate(withDuration: PaymentSheetUI.defaultAnimationDuration) { + animateHeightChange { self.errorLabel.setHiddenIfNecessary(self.error == nil) } } @@ -480,6 +485,7 @@ class PaymentSheetVerticalViewController: UIViewController, FlowControllerViewCo } @objc func presentManageScreen() { + error = nil // Special case, only 1 card remaining but is co-branded, show update view controller if savedPaymentMethods.count == 1, let paymentMethod = savedPaymentMethods.first, @@ -569,6 +575,7 @@ extension PaymentSheetVerticalViewController: VerticalPaymentMethodListViewContr } func didTapPaymentMethod(_ selection: VerticalPaymentMethodListSelection) { + error = nil #if !canImport(CompositorServices) UISelectionFeedbackGenerator().selectionChanged() #endif @@ -584,8 +591,7 @@ extension PaymentSheetVerticalViewController: VerticalPaymentMethodListViewContr navigationBar.setStyle(.back(showAdditionalButton: false)) } } - updatePrimaryButton() - updateMandate() + updateUI() } func didTapSavedPaymentMethodAccessoryButton() { @@ -644,9 +650,7 @@ extension PaymentSheetVerticalViewController: SheetNavigationBarDelegate { paymentMethodFormViewController = nil switchContentIfNecessary(to: paymentMethodListViewController!, containerView: paymentContainerView) navigationBar.setStyle(.close(showAdditionalButton: false)) - updatePrimaryButton() - updateMandate() - updateError() + updateUI() } } diff --git a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetVerticalViewControllerSnapshotTest.swift b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetVerticalViewControllerSnapshotTest.swift index 1e866418604..2f26a32fb4a 100644 --- a/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetVerticalViewControllerSnapshotTest.swift +++ b/StripePaymentSheet/StripePaymentSheetTests/PaymentSheet/PaymentSheetVerticalViewControllerSnapshotTest.swift @@ -215,10 +215,12 @@ final class PaymentSheetVerticalViewControllerSnapshotTest: STPSnapshotTestCase // Take another snapshot displaying the mandate let listVC = sut.paymentMethodListViewController! listVC.didTap(rowButton: listVC.getRowButton(accessibilityIdentifier: "Cash App Pay"), selection: .new(paymentMethodType: .stripe(.cashApp))) + sut.updateErrorLabel(for: MockError()) verify(sut, identifier: "under_list_with_mandate") // Take another snapshot displaying the form sut.didTapPaymentMethod(.new(paymentMethodType: .stripe(.USBankAccount))) + sut.updateErrorLabel(for: MockError()) verify(sut, identifier: "under_form") }