TM-SGNL-iOS/Signal/test/ViewControllers/DonationPaymentDetailsViewControllerTest.swift
TeleMessage developers dde0620daf initial commit
2025-05-03 12:28:28 -07:00

210 lines
6.1 KiB
Swift

//
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import XCTest
@testable import Signal
final class DonationPaymentDetailsViewControllerTest: XCTestCase {
// MARK: - Formatting tests
func testFormatCardNumber() {
// We test this by "round-tripping".
let testCases: [String] = [
"",
// American Express
"37",
"3782 ",
"3782 822463 ",
"3782 822463 10005",
"3782 822463 100051234",
// UnionPay
"6200 ",
"6200 0",
"6200 0000 00",
"6200 0000 0000 000",
"6200 0000 0000 0000",
"6200 0000 0000 0000000",
// Other types
"42",
"4242 4242 ",
"4242 4242 4242 4242",
"4242 4242 4242 4242424"
]
for testCase in testCases {
let reformatted = DonationPaymentDetailsViewController.formatCardNumber(
unformatted: testCase.asciiDigitsOnly
)
XCTAssertEqual(reformatted, testCase)
}
}
func testFormatExpirationDate() {
// We test this by "round-tripping".
let testCases: [String] = [
"",
"0",
"1",
"2/",
"9/",
"01/",
"02/",
"10/",
"11/",
"12/",
"1/3",
"1/9",
"2/3",
"2/00",
"2/34",
"01/00",
"01/23",
"02/00",
"02/34",
"10/98",
"12/34",
// These cases aren't that important because they're invalid.
// If these tests fail, that's probably fine.
// We mostly want to ensure they don't crash.
"1/345",
"0/0",
"0/000"
]
for testCase in testCases {
let reformatted = DonationPaymentDetailsViewController.formatExpirationDate(
unformatted: testCase.asciiDigitsOnly
)
XCTAssertEqual(reformatted, testCase)
}
}
// MARK: - Form state tests
// Field validity is largely tested elsewhere
// (for example, the specifics of CVV validation).
private static func nextYearTwoDigits() -> String {
let calendar = Calendar(identifier: .iso8601)
let currentYear = calendar.component(.year, from: Date())
let nextYear = currentYear + 1
return String(String(nextYear).suffix(2))
}
private static func validRawExpiration() -> String {
" 09 / \(nextYearTwoDigits()) "
}
private func assertFullyValid(
_ formState: DonationPaymentDetailsViewController.FormState,
_ message: String = "Form state not fully valid"
) {
switch formState {
case .fullyValid:
break
case .invalid, .potentiallyValid:
XCTFail(message)
}
}
private func fs(
cardNumber: String = "4242424242424242",
isCardNumberFieldFocused: Bool = false,
expirationDate: String = DonationPaymentDetailsViewControllerTest.validRawExpiration(),
cvv: String = "123"
) -> DonationPaymentDetailsViewController.FormState {
DonationPaymentDetailsViewController.formState(
cardNumber: cardNumber,
isCardNumberFieldFocused: isCardNumberFieldFocused,
expirationDate: expirationDate,
cvv: cvv
)
}
func testFormStateFullForm() {
XCTAssertEqual(fs(cardNumber: "x", cvv: "x"), .invalid(invalidFields: [.cardNumber, .cvv]))
XCTAssertEqual(fs(cvv: ""), .potentiallyValid)
XCTAssertEqual(fs(), .fullyValid(.card(.init(
cardNumber: "4242424242424242",
expirationMonth: 9,
expirationTwoDigitYear: UInt8(Self.nextYearTwoDigits())!,
cvv: "123"
))))
}
func testFormStateCardNumber() {
XCTAssertEqual(fs(cardNumber: "x"), .invalid(invalidFields: [.cardNumber]))
XCTAssertEqual(fs(cardNumber: ""), .potentiallyValid)
XCTAssertEqual(fs(cardNumber: "123"), .potentiallyValid)
assertFullyValid(fs(cardNumber: " 4111 1111 1111 1111 "))
}
func testFormStateExpirationDate() {
let year = Self.nextYearTwoDigits()
let invalids: [String] = [
"x",
"13\(year)",
"09\(year)0",
"009\(year)",
"13 / \(year)",
"09 / \(year)0",
"009 / \(year)",
"09 / \(year)x",
"09 / \(year) /",
"00 / \(year)"
]
for expirationDate in invalids {
XCTAssertEqual(
fs(expirationDate: expirationDate),
.invalid(invalidFields: [.expirationDate]),
expirationDate
)
}
let potentiallyValids: [String] = [
"",
"0",
"1",
"09",
"13",
"09 /",
"1 / 3",
"0 / \(year)"
]
for expirationDate in potentiallyValids {
XCTAssertEqual(
fs(expirationDate: expirationDate),
.potentiallyValid,
expirationDate
)
}
let fullyValids: [String] = [
"1\(year)",
"9\(year)",
"09\(year)",
" 12 \(year) ",
"1 / \(year)",
"9 / \(year)",
"09 / \(year)",
" 12 / \(year) "
]
for expirationDate in fullyValids {
assertFullyValid(fs(expirationDate: expirationDate), expirationDate)
}
}
func testFormStateCvv() {
XCTAssertEqual(fs(cvv: "x"), .invalid(invalidFields: [.cvv]))
XCTAssertEqual(fs(cvv: ""), .potentiallyValid)
XCTAssertEqual(fs(cvv: "12"), .potentiallyValid)
assertFullyValid(fs(cvv: " 123 "))
let amexCard = "378282246310005"
XCTAssertEqual(fs(cardNumber: amexCard, cvv: "123"), .potentiallyValid)
assertFullyValid(fs(cardNumber: amexCard, cvv: " 1234 "))
}
}