@@ -4,7 +4,7 @@ import AuthenticationServices
4
4
@testable import PayPalWebPayments
5
5
@testable import TestShared
6
6
7
- // swiftlint: disable type_body_length
7
+ // swiftlint: disable type_body_length file_length
8
8
class PayPalClient_Tests : XCTestCase {
9
9
10
10
var config : CoreConfig !
@@ -42,7 +42,7 @@ class PayPalClient_Tests: XCTestCase {
42
42
43
43
XCTAssertEqual ( mockWebAuthenticationSession. lastLaunchedURL? . absoluteString, " https://sandbox.paypal.com/agreements/approve?approval_session_id=fake-token " )
44
44
}
45
-
45
+
46
46
func testVault_whenLive_launchesCorrectURLInWebSession( ) {
47
47
config = CoreConfig ( clientID: " testClientID " , environment: . live)
48
48
mockClientConfigAPI. stubUpdateClientConfigResponse = ClientConfigResponse ( updateClientConfig: true )
@@ -56,14 +56,14 @@ class PayPalClient_Tests: XCTestCase {
56
56
clientConfigAPI: mockClientConfigAPI,
57
57
webAuthenticationSession: mockWebAuthenticationSession
58
58
)
59
-
59
+
60
60
let vaultRequest = PayPalVaultRequest ( setupTokenID: " fake-token " )
61
61
payPalClient. vault ( vaultRequest) { _ in }
62
62
wait ( for: [ started] , timeout: 1.0 )
63
63
64
64
XCTAssertEqual ( mockWebAuthenticationSession. lastLaunchedURL? . absoluteString, " https://paypal.com/agreements/approve?approval_session_id=fake-token " )
65
65
}
66
-
66
+
67
67
func testVault_whenSuccessUrl_ReturnsVaultToken( ) {
68
68
69
69
mockWebAuthenticationSession. cannedResponseURL = URL ( string: " sdk.ios.paypal://vault/success?approval_token_id=fakeTokenID&approval_session_id=fakeSessionID " )
@@ -173,7 +173,7 @@ class PayPalClient_Tests: XCTestCase {
173
173
domain: PayPalError . domain,
174
174
errorDescription: PayPalError . payPalVaultResponseError. errorDescription
175
175
)
176
-
176
+
177
177
let vaultRequest = PayPalVaultRequest ( setupTokenID: " fakeTokenID " )
178
178
payPalClient. vault ( vaultRequest) { result in
179
179
switch result {
@@ -185,7 +185,7 @@ class PayPalClient_Tests: XCTestCase {
185
185
}
186
186
expectation. fulfill ( )
187
187
}
188
-
188
+
189
189
waitForExpectations ( timeout: 10 )
190
190
}
191
191
@@ -326,5 +326,100 @@ class PayPalClient_Tests: XCTestCase {
326
326
URL ( string: " https://sandbox.paypal.com/checkoutnow?token=1234&redirect_uri=sdk.ios.paypal://x-callback-url/paypal-sdk/paypal-checkout&native_xo=1 " )
327
327
)
328
328
}
329
+
330
+ // MARK: - handleReturnURL tests
331
+
332
+ func testHandleReturnURL_success_callsAppSwitchCompletionWithResult( ) {
333
+ var received : Result < PayPalWebCheckoutResult , CoreSDKError > ?
334
+ payPalClient. appSwitchCompletion = { received = $0 }
335
+
336
+ let url = URL ( string:
337
+ " https://appSwitchURL/success?token=ORDER123&PayerID=PAYER456&switch_initiated_time=1757431432185 " ) !
338
+
339
+ payPalClient. handleReturnURL ( url)
340
+
341
+ switch received {
342
+ case . success( let result) ? :
343
+ XCTAssertEqual ( result. orderID, " ORDER123 " )
344
+ XCTAssertEqual ( result. payerID, " PAYER456 " )
345
+ default :
346
+ XCTFail ( " Expected success with PayPalWebCheckoutResult " )
347
+ }
348
+
349
+ XCTAssertNil ( payPalClient. appSwitchCompletion)
350
+ }
351
+
352
+ func testHandleReturnURL_cancel_mapsToCheckoutCanceledError( ) {
353
+ var received : Result < PayPalWebCheckoutResult , CoreSDKError > ?
354
+ payPalClient. appSwitchCompletion = { received = $0 }
355
+
356
+ let url = URL ( string:
357
+ " https://appSwitchURL/cancel?token=ORDER123&PayerID=PAYER456&switch_initiated_time=1757431432185 "
358
+ ) !
359
+
360
+ payPalClient. handleReturnURL ( url)
361
+
362
+ if case . failure( let error) ? = received {
363
+ XCTAssertTrue ( PayPalError . isCheckoutCanceled ( error) )
364
+ } else {
365
+ XCTFail ( " Expected cancellation error " )
366
+ }
367
+ XCTAssertNil ( payPalClient. appSwitchCompletion)
368
+ }
369
+
370
+ func testHandleReturnURL_failPath_mapsToUnknownError( ) {
371
+ var received : Result < PayPalWebCheckoutResult , CoreSDKError > ?
372
+ payPalClient. appSwitchCompletion = { received = $0 }
373
+
374
+ let url = URL ( string:
375
+ " https://appSwitchURL/fail?token=ORDER123&PayerID=PAYER456&switch_initiated_time=1757431432185 "
376
+ ) !
377
+
378
+ payPalClient. handleReturnURL ( url)
379
+
380
+ if case . failure( let error) ? = received {
381
+ XCTAssertEqual ( error. code, PayPalError . malformedResultError. code)
382
+ XCTAssertEqual ( error. domain, PayPalError . domain)
383
+ } else {
384
+ XCTFail ( " Expected unknown error " )
385
+ }
386
+ XCTAssertNil ( payPalClient. appSwitchCompletion)
387
+ }
388
+
389
+ func testHandleReturnURL_successPathMissingPayerID_isMalformedResultError( ) {
390
+ var received : Result < PayPalWebCheckoutResult , CoreSDKError > ?
391
+ payPalClient. appSwitchCompletion = { received = $0 }
392
+
393
+ // Missing PayerID
394
+ let url = URL ( string:
395
+ " https://appSwitchURL/success?token=ORDER123&switch_initiated_time=1757431432185 "
396
+ ) !
397
+
398
+ payPalClient. handleReturnURL ( url)
399
+
400
+ if case . failure( let error) ? = received {
401
+ XCTAssertEqual ( error. code, PayPalError . malformedResultError. code)
402
+ XCTAssertEqual ( error. domain, PayPalError . domain)
403
+ } else {
404
+ XCTFail ( " Expected malformedResultError " )
405
+ }
406
+ XCTAssertNil ( payPalClient. appSwitchCompletion)
407
+ }
408
+
409
+ func testHandleReturnURL__onlyCompletesOnce( ) {
410
+ var completionCount = 0
411
+ payPalClient. appSwitchCompletion = { _ in completionCount += 1 }
412
+
413
+ let url = URL ( string:
414
+ " https://appSwitchURL/success?token=ORDER123&PayerID=PAYER456&switch_initiated_time=1757431432185 "
415
+ ) !
416
+
417
+ payPalClient. handleReturnURL ( url)
418
+ // Second call should do nothing because appSwitchCompletion was cleared via defer
419
+ payPalClient. handleReturnURL ( url)
420
+
421
+ XCTAssertEqual ( completionCount, 1 , " Completion should be called exactly once " )
422
+ XCTAssertNil ( payPalClient. appSwitchCompletion)
423
+ }
329
424
}
330
425
// swiftlint:enable type_body_length
0 commit comments