Skip to content

Commit

Permalink
Add BTVenmoError.canceled case (#1087)
Browse files Browse the repository at this point in the history
---------

Signed-off-by: Jax DesMarais-Leder <[email protected]>
  • Loading branch information
scannillo authored Aug 10, 2023
1 parent 3ace157 commit 5d442a6
Show file tree
Hide file tree
Showing 8 changed files with 35 additions and 16 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
## unreleased
* BraintreeVenmo
* Add additional error parsing for Venmo errors
* Throw cancelation specific error for `BTVenmoClient.tokenize()` (fixes #1085)
* _The callback style version of this function previously returned `(nil, nil)` for the cancel scenario, but will now return `(nil, error)` instead._
* BraintreeCore
* Send `live` instead of `production` for the `merchant_sdk_env` tag to PayPal's analytics service (FPTI)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,11 @@ class BraintreeDemoVenmoViewController: BraintreeDemoPaymentButtonBaseViewContro
progressBlock("Got a nonce 💎!")
completionBlock(venmoAccount)
} catch {
progressBlock(error.localizedDescription)
if (error as NSError).code == 10 {
progressBlock("Canceled 🔰")
} else {
progressBlock(error.localizedDescription)
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Demo/Demo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 52;
objectVersion = 54;
objects = {

/* Begin PBXBuildFile section */
Expand Down
17 changes: 8 additions & 9 deletions Demo/UI Tests/Venmo UI Tests/Venmo_UITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,12 @@ class Venmo_UITests: XCTestCase {
XCTAssertTrue(demoApp.buttons["An error occurred during the Venmo flow"].waitForExistence(timeout: 15))
}

// TODO: - Uncomment test once cancel case is handled as an error
// func testTokenizeVenmo_whenUserCancels_returnsCancel() {
// demoApp.buttons["Venmo"].tap()
//
// waitForElementToBeHittable(mockVenmo.buttons["Cancel"])
// mockVenmo.buttons["Cancel"].tap()
//
// XCTAssertTrue(demoApp.buttons["Canceled 🔰"].waitForExistence(timeout: 15))
// }
func testTokenizeVenmo_whenUserCancels_returnsCancel() {
demoApp.buttons["Venmo"].tap()

waitForElementToBeHittable(mockVenmo.buttons["Cancel"])
mockVenmo.buttons["Cancel"].tap()

XCTAssertTrue(demoApp.buttons["Canceled 🔰"].waitForExistence(timeout: 15))
}
}
1 change: 1 addition & 0 deletions SDK_ERROR_CODES.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,4 @@ See below for a comprehensive list of error types and codes thrown by each featu
| BTVenmoError.invalidRedirectURL | 7 |
| BTVenmoError.fetchConfigurationFailed | 8 |
| BTVenmoError.enrichedCustomerDataDisabled | 9 |
| BTVenmoError.canceled | 10 |
7 changes: 4 additions & 3 deletions Sources/BraintreeVenmo/BTVenmoClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ import BraintreeCore
/// - Parameters:
/// - request: A Venmo request.
/// - completion: This completion will be invoked when app switch is complete or an error occurs. On success, you will receive
/// an instance of `BTVenmoAccountNonce`; on failure, an error; on user cancellation, you will receive `nil` for both parameters.
/// an instance of `BTVenmoAccountNonce`; on failure or user cancelation you will receive an error.
/// If the user cancels out of the flow, the error code will be `.canceled`.
@objc(tokenizeWithVenmoRequest:completion:)
public func tokenize(_ request: BTVenmoRequest, completion: @escaping (BTVenmoAccountNonce?, Error?) -> Void) {
apiClient.sendAnalyticsEvent(BTVenmoAnalytics.tokenizeStarted)
Expand Down Expand Up @@ -205,7 +206,7 @@ import BraintreeCore
/// Initiates Venmo login via app switch, which returns a BTVenmoAccountNonce when successful.
/// - Parameter request: A `BTVenmoRequest`
/// - Returns: On success, you will receive an instance of `BTVenmoAccountNonce`
/// - Throws: An `Error` describing the failure
/// - Throws: An `Error` describing the failure. If the user cancels out of the flow, the error code will be `.canceled`.
public func tokenize(_ request: BTVenmoRequest) async throws -> BTVenmoAccountNonce {
try await withCheckedThrowingContinuation { continuation in
tokenize(request) { nonce, error in
Expand Down Expand Up @@ -415,7 +416,7 @@ import BraintreeCore

private func notifyCancel(completion: @escaping (BTVenmoAccountNonce?, Error?) -> Void) {
apiClient.sendAnalyticsEvent(BTVenmoAnalytics.appSwitchCanceled)
completion(nil, nil)
completion(nil, BTVenmoError.canceled)
}
}

Expand Down
7 changes: 7 additions & 0 deletions Sources/BraintreeVenmo/BTVenmoError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ enum BTVenmoError: Error, CustomNSError, LocalizedError {

/// 9. Enriched Customer Data is disabled
case enrichedCustomerDataDisabled

/// 10. The Venmo flow was canceled by the user
case canceled

static var errorDomain: String {
"com.braintreepayments.BTVenmoErrorDomain"
Expand Down Expand Up @@ -84,6 +87,8 @@ enum BTVenmoError: Error, CustomNSError, LocalizedError {
return 8
case .enrichedCustomerDataDisabled:
return 9
case .canceled:
return 10
}
}

Expand All @@ -109,6 +114,8 @@ enum BTVenmoError: Error, CustomNSError, LocalizedError {
return "Failed to fetch Braintree configuration."
case .enrichedCustomerDataDisabled:
return "Cannot collect customer data when ECD is disabled. Enable this feature in the Control Panel to collect this data."
case .canceled:
return "Venmo flow was canceled by the user."
}
}
}
9 changes: 7 additions & 2 deletions UnitTests/BraintreeVenmoTests/BTVenmoClient_Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ class BTVenmoClient_Tests: XCTestCase {
XCTAssertEqual(mockAPIClient.postedAnalyticsEvents.last!, BTVenmoAnalytics.tokenizeFailed)
}

func testTokenizeVenmoAccount_whenAppSwitchCanceled_callsBackWithNoError() {
func testTokenizeVenmoAccount_whenAppSwitchCanceled_callsBackWithCancelError() {
let venmoClient = BTVenmoClient(apiClient: mockAPIClient)
venmoClient.application = FakeApplication()
venmoClient.bundle = FakeBundle()
Expand All @@ -622,7 +622,12 @@ class BTVenmoClient_Tests: XCTestCase {
let expectation = expectation(description: "Callback invoked")
venmoClient.tokenize(venmoRequest) { venmoAccount, error in
XCTAssertNil(venmoAccount)
XCTAssertNil(error)
XCTAssertNotNil(error)

let error = error! as NSError
XCTAssertEqual(error.localizedDescription, BTVenmoError.canceled.localizedDescription)
XCTAssertEqual(error.code, 10)

expectation.fulfill()
}
BTVenmoClient.handleReturnURL(URL(string: "scheme://x-callback-url/vzero/auth/venmo/cancel")!)
Expand Down

0 comments on commit 5d442a6

Please sign in to comment.