From 6968d07dab61169c0a38d07676368757de0e6d95 Mon Sep 17 00:00:00 2001 From: Mark Mroz Date: Wed, 4 Dec 2024 13:40:48 -0500 Subject: [PATCH] Add the zeroPaddedExpiryMonth to Card for V3 Checkout --- Afterpay.xcodeproj/project.pbxproj | 4 +++ AfterpayTests/CheckoutV3CardTests.swift | 33 +++++++++++++++++++++ Sources/Afterpay/Model/CheckoutV3Card.swift | 17 ++++++++++- 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 AfterpayTests/CheckoutV3CardTests.swift diff --git a/Afterpay.xcodeproj/project.pbxproj b/Afterpay.xcodeproj/project.pbxproj index b72dcf3f..5e14d3de 100644 --- a/Afterpay.xcodeproj/project.pbxproj +++ b/Afterpay.xcodeproj/project.pbxproj @@ -56,6 +56,7 @@ 5FB958DE2C0E00DC00137468 /* AfterpayV3Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FB958DD2C0E00DC00137468 /* AfterpayV3Tests.swift */; }; 5FB958E32C0E126200137468 /* URLSessionMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FB958E22C0E126200137468 /* URLSessionMock.swift */; }; 5FBAABA02C1B3109003558AF /* CashAppPayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FBAAB9F2C1B3109003558AF /* CashAppPayTests.swift */; }; + 5FEF44A22D00D64600174588 /* CheckoutV3CardTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FEF44A12D00D64100174588 /* CheckoutV3CardTests.swift */; }; 6602EF0F25358A8000A0468C /* ColorScheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6602EF0E25358A8000A0468C /* ColorScheme.swift */; }; 6605666324E5199500DA588E /* Locales.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6605666224E5199500DA588E /* Locales.swift */; }; 66169312257A06B200DF6CF4 /* CheckoutV2Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66169311257A06B200DF6CF4 /* CheckoutV2Message.swift */; }; @@ -156,6 +157,7 @@ 5FB958DD2C0E00DC00137468 /* AfterpayV3Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AfterpayV3Tests.swift; sourceTree = ""; }; 5FB958E22C0E126200137468 /* URLSessionMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSessionMock.swift; sourceTree = ""; }; 5FBAAB9F2C1B3109003558AF /* CashAppPayTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CashAppPayTests.swift; sourceTree = ""; }; + 5FEF44A12D00D64100174588 /* CheckoutV3CardTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckoutV3CardTests.swift; sourceTree = ""; }; 6602EF0E25358A8000A0468C /* ColorScheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorScheme.swift; sourceTree = ""; }; 6605666224E5199500DA588E /* Locales.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Locales.swift; sourceTree = ""; }; 66169311257A06B200DF6CF4 /* CheckoutV2Message.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckoutV2Message.swift; sourceTree = ""; }; @@ -323,6 +325,7 @@ 5FB958E12C0E124E00137468 /* Mocks */, 556DEBF92653531000BFC277 /* mock-widget-bootstrap.js */, 6635B95E24CAA9F000EBB3A6 /* ConfigurationTests.swift */, + 5FEF44A12D00D64100174588 /* CheckoutV3CardTests.swift */, 66C3F7FA25397A810086DD0A /* CurrencyFormatterTests.swift */, 551BEDF025F98FA800FDF9EE /* FeaturesTests.swift */, 665FC57B2488766C00A5A93E /* Info.plist */, @@ -646,6 +649,7 @@ 551BEDF125F98FA800FDF9EE /* FeaturesTests.swift in Sources */, 6635B95F24CAA9F000EBB3A6 /* ConfigurationTests.swift in Sources */, 5FB958DE2C0E00DC00137468 /* AfterpayV3Tests.swift in Sources */, + 5FEF44A22D00D64600174588 /* CheckoutV3CardTests.swift in Sources */, 66DAAC8D24E109D200127460 /* PriceBreakdownTests.swift in Sources */, 550D481B26255D8600C0B0C6 /* WidgetEventTests.swift in Sources */, 550D48152625539900C0B0C6 /* WidgetStatusTests.swift in Sources */, diff --git a/AfterpayTests/CheckoutV3CardTests.swift b/AfterpayTests/CheckoutV3CardTests.swift new file mode 100644 index 00000000..d2e47d34 --- /dev/null +++ b/AfterpayTests/CheckoutV3CardTests.swift @@ -0,0 +1,33 @@ +// +// CheckoutV3CardTests.swift +// Afterpay +// +// Created by Mark Mroz on 2024-12-04. +// Copyright © 2024 Afterpay. All rights reserved. +// + +import XCTest +@testable import Afterpay + +final class CheckoutV3CardTests: XCTestCase { + func testCardZeroPaddedExpiryMonth() { + XCTAssertEqual(makeCard(expiryMonth: 1).zeroPaddedExpiryMonth, "01") + XCTAssertEqual(makeCard(expiryMonth: 2).zeroPaddedExpiryMonth, "02") + XCTAssertEqual(makeCard(expiryMonth: 3).zeroPaddedExpiryMonth, "03") + XCTAssertEqual(makeCard(expiryMonth: 4).zeroPaddedExpiryMonth, "04") + XCTAssertEqual(makeCard(expiryMonth: 5).zeroPaddedExpiryMonth, "05") + XCTAssertEqual(makeCard(expiryMonth: 6).zeroPaddedExpiryMonth, "06") + XCTAssertEqual(makeCard(expiryMonth: 7).zeroPaddedExpiryMonth, "07") + XCTAssertEqual(makeCard(expiryMonth: 8).zeroPaddedExpiryMonth, "08") + XCTAssertEqual(makeCard(expiryMonth: 9).zeroPaddedExpiryMonth, "09") + XCTAssertEqual(makeCard(expiryMonth: 10).zeroPaddedExpiryMonth, "10") + XCTAssertEqual(makeCard(expiryMonth: 11).zeroPaddedExpiryMonth, "11") + XCTAssertEqual(makeCard(expiryMonth: 12).zeroPaddedExpiryMonth, "12") + } + + // MARK: - Private + + private func makeCard(expiryMonth: Int) -> Card { + Card(cardType: "Visa", cardNumber: "4242 4242 4242 4242", cvc: "222", expiryMonth: expiryMonth, expiryYear: 2024) + } +} diff --git a/Sources/Afterpay/Model/CheckoutV3Card.swift b/Sources/Afterpay/Model/CheckoutV3Card.swift index cf681e15..e7eb7b55 100644 --- a/Sources/Afterpay/Model/CheckoutV3Card.swift +++ b/Sources/Afterpay/Model/CheckoutV3Card.swift @@ -8,6 +8,8 @@ import Foundation +// MARK: - Virtual Card + public enum VirtualCard { case card(Card) case tokenized(TokenizedCard) @@ -24,13 +26,24 @@ public enum VirtualCard { } } -public struct Card: Decodable { +// MARK: - Card + +public struct Card { public let cardType: String public let cardNumber: String public let cvc: String public let expiryMonth: Int public let expiryYear: Int + /// A convenience method that returns the `expiryMonth` in zero padded format. + /// + /// - Returns: Returns the expiry month in zero padded format. + public var zeroPaddedExpiryMonth: String { + String(format: "%02d", expiryMonth) + } +} + +extension Card: Decodable { private enum CodingKeys: String, CodingKey { case cardNumber, cvc, expiry, cardType } @@ -68,6 +81,8 @@ public struct Card: Decodable { } } +// MARK: - TokenizedCard + public struct TokenizedCard: Decodable { public let paymentGateway: String public let cardToken: String