Skip to content

Commit

Permalink
fix: DPS-292 fixes externalPayerInfo on Paypal (#849)
Browse files Browse the repository at this point in the history
* Mirror externalPayerId to external_payer_id in PayPal instrument

* Also mirror firsName and lastName

* Add constructor for tests

* Added unit tests for mirrored encode/decode
  • Loading branch information
NQuinn27 authored May 4, 2024
1 parent 0fe95e1 commit 7bf0fac
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 1 deletion.
82 changes: 81 additions & 1 deletion Sources/PrimerSDK/Classes/Data Models/PayPal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,87 @@ extension Response.Body.Tokenization {

// swiftlint:disable:next nesting
public struct ExternalPayerInfo: Codable {
public var externalPayerId, email, firstName, lastName: String?
public var externalPayerId, externalPayerIdSnakeCase,
email,
firstName, firstNameSnakeCase,
lastName, lastNameSnakeCase: String?

public init(externalPayerId: String,
externalPayerIdSnakeCase: String? = nil,
email: String,
firstName: String?,
firstNameSnakeCase: String? = nil,
lastName: String,
lastNameSnakeCase: String? = nil) {
self.externalPayerId = externalPayerId
self.externalPayerIdSnakeCase = externalPayerIdSnakeCase ?? externalPayerId
self.email = email
self.firstName = firstName
self.firstNameSnakeCase = firstNameSnakeCase ?? firstName
self.lastName = lastName
self.lastNameSnakeCase = lastNameSnakeCase ?? lastName
}

public init(from decoder: Decoder) throws {
let container: KeyedDecodingContainer<Response.Body.Tokenization.PayPal.ExternalPayerInfo.CodingKeys> =
try decoder.container(keyedBy: Response.Body.Tokenization.PayPal.ExternalPayerInfo.CodingKeys.self)

self.externalPayerId = try container.decodeIfPresent(
String.self,
forKey: Response.Body.Tokenization.PayPal.ExternalPayerInfo.CodingKeys.externalPayerId)

self.externalPayerIdSnakeCase = try container.decodeIfPresent(
String.self,
forKey: Response.Body.Tokenization.PayPal.ExternalPayerInfo.CodingKeys.externalPayerIdSnakeCase)

self.email = try container.decodeIfPresent(
String.self,
forKey: Response.Body.Tokenization.PayPal.ExternalPayerInfo.CodingKeys.email)

self.firstName = try container.decodeIfPresent(
String.self,
forKey: Response.Body.Tokenization.PayPal.ExternalPayerInfo.CodingKeys.firstName)

self.firstNameSnakeCase = try container.decodeIfPresent(
String.self,
forKey: Response.Body.Tokenization.PayPal.ExternalPayerInfo.CodingKeys.firstNameSnakeCase)

self.lastName = try container.decodeIfPresent(
String.self,
forKey: Response.Body.Tokenization.PayPal.ExternalPayerInfo.CodingKeys.lastName)

self.lastNameSnakeCase = try container.decodeIfPresent(
String.self,
forKey: Response.Body.Tokenization.PayPal.ExternalPayerInfo.CodingKeys.lastNameSnakeCase)

// This logic ensures we mirror externalPayerId to external_payer_id and vice versa
if self.externalPayerId == nil && self.externalPayerIdSnakeCase != nil {
self.externalPayerId = self.externalPayerIdSnakeCase
} else if self.externalPayerIdSnakeCase == nil && self.externalPayerId != nil {
self.externalPayerIdSnakeCase = self.externalPayerId
}

if firstName == nil && firstNameSnakeCase != nil {
firstName = firstNameSnakeCase
} else if firstNameSnakeCase == nil && firstName != nil {
firstNameSnakeCase = firstName
}

if lastName == nil && lastNameSnakeCase != nil {
lastName = lastNameSnakeCase
} else if lastNameSnakeCase == nil && lastName != nil {
lastNameSnakeCase = lastName
}
}

// swiftlint:disable:next nesting
enum CodingKeys: String, CodingKey {
case externalPayerId
case externalPayerIdSnakeCase = "external_payer_id"
case firstNameSnakeCase = "first_name"
case lastNameSnakeCase = "last_name"
case email, firstName, lastName
}
}
}
}
106 changes: 106 additions & 0 deletions Tests/Unit Tests/Data Models/PayPalResposeTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//
// PayPalResposeTests.swift
// Debug App SPM
//
// Created by Niall Quinn on 04/05/24.
// Copyright © 2024 Primer API Ltd. All rights reserved.
//

import XCTest
@testable import PrimerSDK

final class PayPalResposeTests: XCTestCase {

private typealias PayPalResponse = Response.Body.Tokenization.PayPal

func test_externalPayerInfo_snakecase() async {
let JSON_snake_case = """
{
"external_payer_id": "external-id",
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]"
}
"""

guard let data = JSON_snake_case.data(using: .utf8) else {
XCTFail()
return
}
do {
let decoder = JSONDecoder()
let decoded: PayPalResponse.ExternalPayerInfo = try decoder.decode(PayPalResponse.ExternalPayerInfo.self, from: data)

XCTAssertEqual(decoded.externalPayerId, "external-id")
XCTAssertEqual(decoded.externalPayerId, decoded.externalPayerIdSnakeCase)

XCTAssertEqual(decoded.firstName, "John")
XCTAssertEqual(decoded.firstName, decoded.firstNameSnakeCase)

XCTAssertEqual(decoded.lastName, "Doe")
XCTAssertEqual(decoded.lastName, decoded.lastNameSnakeCase)
} catch {
XCTFail()
}
}

func test_externalPayerInfo_camelcase() async {
let JSON_camelCase = """
{
"externalPayerId": "external-id",
"firstName": "John",
"lastName": "Doe",
"email": "[email protected]"
}
"""

guard let data = JSON_camelCase.data(using: .utf8) else {
XCTFail()
return
}
do {
let decoder = JSONDecoder()
let decoded: PayPalResponse.ExternalPayerInfo = try decoder.decode(PayPalResponse.ExternalPayerInfo.self, from: data)

XCTAssertEqual(decoded.externalPayerId, "external-id")
XCTAssertEqual(decoded.externalPayerId, decoded.externalPayerIdSnakeCase)

XCTAssertEqual(decoded.firstName, "John")
XCTAssertEqual(decoded.firstName, decoded.firstNameSnakeCase)

XCTAssertEqual(decoded.lastName, "Doe")
XCTAssertEqual(decoded.lastName, decoded.lastNameSnakeCase)
} catch {
XCTFail()
}
}

func test_jsonEncoding() async {
let payerInfo = PayPalResponse.ExternalPayerInfo(externalPayerId: "external-id",
email: "[email protected]",
firstName: "John",
lastName: "Doe")

do {
let encoder = JSONEncoder()
let encoded = try encoder.encode(payerInfo)
guard let string = String(data: encoded, encoding: .utf8) else {
XCTFail()
return
}

XCTAssertTrue(string.contains("\"externalPayerId\":\"external-id\""))
XCTAssertTrue(string.contains("\"external_payer_id\":\"external-id\""))

XCTAssertTrue(string.contains("\"firstName\":\"John\""))
XCTAssertTrue(string.contains("\"first_name\":\"John\""))

XCTAssertTrue(string.contains("\"lastName\":\"Doe\""))
XCTAssertTrue(string.contains("\"last_name\":\"Doe\""))

XCTAssertTrue(string.contains("\"email\":\"[email protected]\""))
} catch {
XCTFail()
}
}
}

0 comments on commit 7bf0fac

Please sign in to comment.