@@ -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,140 @@ 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_successPathIncorrectPayerIdFormat_isMalformedResultError( ) {
410
+ var received : Result < PayPalWebCheckoutResult , CoreSDKError > ?
411
+ payPalClient. appSwitchCompletion = { received = $0 }
412
+
413
+ // Should be PayerID
414
+ let url = URL ( string:
415
+ " https://appSwitchURL/success?token=ORDER123&PayerId=PAYER456&switch_initiated_time=1757431432185 "
416
+ ) !
417
+
418
+ payPalClient. handleReturnURL ( url)
419
+
420
+ if case . failure( let error) ? = received {
421
+ XCTAssertEqual ( error. code, PayPalError . malformedResultError. code)
422
+ XCTAssertEqual ( error. domain, PayPalError . domain)
423
+ } else {
424
+ XCTFail ( " Expected malformedResultError " )
425
+ }
426
+ XCTAssertNil ( payPalClient. appSwitchCompletion)
427
+ }
428
+
429
+ func testHandleReturnURL_successPathIncorrectPayeridFormat_isMalformedResultError( ) {
430
+ var received : Result < PayPalWebCheckoutResult , CoreSDKError > ?
431
+ payPalClient. appSwitchCompletion = { received = $0 }
432
+
433
+ // Should be PayerID
434
+ let url = URL ( string:
435
+ " https://appSwitchURL/success?token=ORDER123&Payer_id=PAYER456&switch_initiated_time=1757431432185 "
436
+ ) !
437
+
438
+ payPalClient. handleReturnURL ( url)
439
+
440
+ if case . failure( let error) ? = received {
441
+ XCTAssertEqual ( error. code, PayPalError . malformedResultError. code)
442
+ XCTAssertEqual ( error. domain, PayPalError . domain)
443
+ } else {
444
+ XCTFail ( " Expected malformedResultError " )
445
+ }
446
+ XCTAssertNil ( payPalClient. appSwitchCompletion)
447
+ }
448
+
449
+ func testHandleReturnURL__onlyCompletesOnce( ) {
450
+ var completionCount = 0
451
+ payPalClient. appSwitchCompletion = { _ in completionCount += 1 }
452
+
453
+ let url = URL ( string:
454
+ " https://appSwitchURL/success?token=ORDER123&PayerID=PAYER456&switch_initiated_time=1757431432185 "
455
+ ) !
456
+
457
+ payPalClient. handleReturnURL ( url)
458
+ // Second call should do nothing because appSwitchCompletion was cleared via defer
459
+ payPalClient. handleReturnURL ( url)
460
+
461
+ XCTAssertEqual ( completionCount, 1 , " Completion should be called exactly once " )
462
+ XCTAssertNil ( payPalClient. appSwitchCompletion)
463
+ }
329
464
}
330
465
// swiftlint:enable type_body_length
0 commit comments