From 344ee5e1c228046539b502f81786d004da6c5eb2 Mon Sep 17 00:00:00 2001 From: Donald Rodriguez Gutierrez <129230521+DonaldRG@users.noreply.github.com> Date: Mon, 19 Jun 2023 10:22:00 -0600 Subject: [PATCH 1/4] Public release 1.14.0 (#349) * Revert "Add VGSDateTextField." This reverts commit 92c1e5099afd272725b02d3af48fa845dc2433fa. * Bump SDK version --- .circleci/config.yml | 2 +- .../Core/Collector/VGSCollect.swift | 6 +- Sources/VGSCollectSDK/Core/Enums.swift | 16 +- .../VGSDateTokenizationConfiguration.swift | 108 +++++ .../VGSExpDateTokenizationConfiguration.swift | 28 +- Sources/VGSCollectSDK/Core/VGSDate.swift | 84 ++++ .../Core/VGSDateConfiguration.swift | 132 ++++++ .../Core/VGSExpDateConfiguration.swift | 33 +- .../Core/VGSCustomPaymentCardModel.swift | 2 +- .../Text Field/VGSDateTextField.swift | 361 ++++++++++++++++ .../Text Field/VGSExpDateTextField.swift | 3 +- .../UIElements/Text Field/VGSTextField.swift | 18 +- .../AnyType/VGSValidationRuleLength.swift | 2 +- .../VGSValidationRuleLengthMatch.swift | 2 +- .../AnyType/VGSValidationRulePattern.swift | 2 +- .../Card/VGSValidationRuleLuhnCheck.swift | 2 +- .../Card/VGSValidationRulePaymentCard.swift | 4 +- .../Validation/Date/VGSDateFormat.swift | 181 ++++++++ .../Date/VGSValidationRuleDateRange.swift | 76 ++++ .../VGSValidationRuleExpirationDate.swift | 4 +- .../Validation/VGSValidationError.swift | 3 + .../Validation/VGSValidationRule.swift | 4 +- .../Convertors/DateFormatConvertor.swift | 75 ++++ .../Convertors/ExpDateFormatConvertor.swift | 152 ++++--- .../Convertors/VGSTextFormatConvertable.swift | 31 ++ .../Utils/Extensions/Utils.swift | 2 +- .../VGSDateSeparateSerializer.swift | 32 ++ .../ConvertorsTests/DateConvertorTests.swift | 309 ++++++++++++++ Tests/FrameworkTests/Core/DateTests.swift | 53 +++ .../VGSDateSerialization_CustomConfig.json | 44 ++ ...rialization_CustomExpDateOutputConfig.json | 44 ++ .../VGSDateSerialization_DefaultConfig.json | 44 ++ ...GSDateSerialization_MapWithArrayMerge.json | 72 ++++ ...teSerialization_MapWithArrayOverwrite.json | 53 +++ ...kenizationSerialization_DefaultConfig.json | 85 ++++ .../Text Fields Tests/DateTextFieldTest.swift | 225 ++++++++++ .../VGSDateFormatTests.swift | 178 ++++++++ .../ValidationRuleDateTests.swift | 204 +++++++++ .../SerializersDataProvider.swift | 47 +++ .../VGSDateSeparateSerializerTests.swift | 256 ++++++++++++ .../VGSDateTokenizationSerializerTests.swift | 135 ++++++ .../VGSExpDateSeparateSerializerTests.swift | 387 ++++++++++-------- .../VGSExpDateSerializersDataProvider.swift | 59 --- ...GSExpDateTokenizationSerializerTests.swift | 192 ++++----- VGSCollectSDK.podspec | 2 +- VGSCollectSDK.xcodeproj/project.pbxproj | 144 ++++++- demoapp/demoapp.xcodeproj/project.pbxproj | 8 +- demoapp/demoapp/Main.storyboard | 282 +++++++++---- .../DateValidationViewController.swift | 186 +++++++++ 49 files changed, 3842 insertions(+), 532 deletions(-) create mode 100644 Sources/VGSCollectSDK/Core/TokenizationConfiguration/VGSDateTokenizationConfiguration.swift create mode 100644 Sources/VGSCollectSDK/Core/VGSDate.swift create mode 100644 Sources/VGSCollectSDK/Core/VGSDateConfiguration.swift create mode 100644 Sources/VGSCollectSDK/UIElements/Text Field/VGSDateTextField.swift create mode 100644 Sources/VGSCollectSDK/UIElements/Text Field/Validation/Date/VGSDateFormat.swift create mode 100644 Sources/VGSCollectSDK/UIElements/Text Field/Validation/Date/VGSValidationRuleDateRange.swift create mode 100644 Sources/VGSCollectSDK/Utils/Convertors/DateFormatConvertor.swift create mode 100644 Sources/VGSCollectSDK/Utils/Convertors/VGSTextFormatConvertable.swift create mode 100644 Sources/VGSCollectSDK/Utils/Helpers/Serializers/VGSDateSeparateSerializer.swift create mode 100644 Tests/FrameworkTests/ConvertorsTests/DateConvertorTests.swift create mode 100644 Tests/FrameworkTests/Core/DateTests.swift create mode 100644 Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_CustomConfig.json create mode 100644 Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_CustomExpDateOutputConfig.json create mode 100644 Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_DefaultConfig.json create mode 100644 Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_MapWithArrayMerge.json create mode 100644 Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_MapWithArrayOverwrite.json create mode 100644 Tests/FrameworkTests/Resources/DateTokenizationJSON/VGSDateTokenizationSerialization_DefaultConfig.json create mode 100644 Tests/FrameworkTests/Satellite Tests/Text Fields Tests/DateTextFieldTest.swift create mode 100644 Tests/FrameworkTests/Satellite Tests/Text Fields Tests/VGSDateFormatTests.swift create mode 100644 Tests/FrameworkTests/Satellite Tests/Text Fields Tests/ValidationRuleDateTests.swift create mode 100644 Tests/FrameworkTests/SerializersTest/SerializersDataProvider.swift create mode 100644 Tests/FrameworkTests/SerializersTest/VGSDateSeparateSerializerTests.swift create mode 100644 Tests/FrameworkTests/SerializersTest/VGSDateTokenizationSerializerTests.swift delete mode 100644 Tests/FrameworkTests/SerializersTest/VGSExpDateSerializersDataProvider.swift create mode 100644 demoapp/demoapp/UseCases/DateValidationViewController.swift diff --git a/.circleci/config.yml b/.circleci/config.yml index 83d37963..7c89195e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,4 +34,4 @@ workflows: build-and-test: jobs: - build-and-test-sdk - - build-and-ui-test-demo-app-ios-16-iphone14 + - build-and-ui-test-demo-app-ios-16-iphone14 \ No newline at end of file diff --git a/Sources/VGSCollectSDK/Core/Collector/VGSCollect.swift b/Sources/VGSCollectSDK/Core/Collector/VGSCollect.swift index b2bbddfc..bbeea0bf 100644 --- a/Sources/VGSCollectSDK/Core/Collector/VGSCollect.swift +++ b/Sources/VGSCollectSDK/Core/Collector/VGSCollect.swift @@ -52,9 +52,9 @@ public class VGSCollect { return storage.textFields } - // MARK: - Initialzation + // MARK: - Initialization - /// Initialzation. + /// Initialization. /// /// - Parameters: /// - id: `String` object, your organization vault id. @@ -72,7 +72,7 @@ public class VGSCollect { } } - /// Initialzation. + /// Initialization. /// /// - Parameters: /// - id: `String` object, your organization vault id. diff --git a/Sources/VGSCollectSDK/Core/Enums.swift b/Sources/VGSCollectSDK/Core/Enums.swift index 4f4aa6a3..e4e92a1c 100644 --- a/Sources/VGSCollectSDK/Core/Enums.swift +++ b/Sources/VGSCollectSDK/Core/Enums.swift @@ -32,6 +32,9 @@ public enum FieldType: Int, CaseIterable { /// Field type that requires Expiration Date input formatting and validation. case expDate + /// Field type that requires Date input formatting and validation. + case date + /// Field type that requires Credit Card CVC input formatting and validation. case cvc @@ -64,6 +67,8 @@ internal extension FieldType { return DateFormatPattern.shortYear.rawValue case .ssn: return "###-##-####" + case .date: + return VGSDateFormat.default.formatPattern default: return "" } @@ -71,7 +76,7 @@ internal extension FieldType { var defaultDivider: String { switch self { - case .expDate: + case .expDate, .date: return "/" case .ssn: return "-" @@ -86,6 +91,8 @@ internal extension FieldType { return "^(?:4[0-9]{12}(?:[0-9]{3})?|[25][1-7][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11})$" case .expDate: return "^(0[1-9]|1[0-2])\\/?([0-9]{4}|[0-9]{2})$" + case .date: + return "^([0-9]{4}|[0-9]{2})\\/?([0-9]{2})\\/?([0-9]{4}|[0-9]{2})$" case .cardHolderName: return "^([a-zA-Z0-9\\ \\,\\.\\-\\']{2,})$" case .ssn: @@ -100,7 +107,7 @@ internal extension FieldType { var keyboardType: UIKeyboardType { switch self { - case .cardNumber, .cvc, .expDate, .ssn: + case .cardNumber, .cvc, .expDate, .date, .ssn: return .asciiCapableNumberPad default: return .alphabet @@ -115,6 +122,9 @@ internal extension FieldType { case .expDate: rules.add(rule: VGSValidationRulePattern(pattern: self.defaultRegex, error: VGSValidationErrorType.pattern.rawValue)) rules.add(rule: VGSValidationRuleCardExpirationDate(error: VGSValidationErrorType.expDate.rawValue)) + case .date: + rules.add(rule: VGSValidationRulePattern(pattern: self.defaultRegex, error: VGSValidationErrorType.pattern.rawValue)) + rules.add(rule: VGSValidationRuleDateRange(error: VGSValidationErrorType.date.rawValue)) case .cardNumber: rules.add(rule: VGSValidationRulePaymentCard(error: VGSValidationErrorType.cardNumber.rawValue)) case .cvc: @@ -137,6 +147,8 @@ internal extension FieldType { return "card-security-code" case .expDate: return "card-expiration-date" + case .date: + return "date" case .ssn: return "ssn" case .none: diff --git a/Sources/VGSCollectSDK/Core/TokenizationConfiguration/VGSDateTokenizationConfiguration.swift b/Sources/VGSCollectSDK/Core/TokenizationConfiguration/VGSDateTokenizationConfiguration.swift new file mode 100644 index 00000000..c9878863 --- /dev/null +++ b/Sources/VGSCollectSDK/Core/TokenizationConfiguration/VGSDateTokenizationConfiguration.swift @@ -0,0 +1,108 @@ +// +// VGSDateTokenizationConfiguration.swift +// VGSCollectSDK +// + +import Foundation + +/// `VGSDateTokenizationParameters` - parameters required for tokenization API +public struct VGSDateTokenizationParameters: VGSTokenizationParametersProtocol { + + /// Vault storage type. + public var storage: String = VGSVaultStorageType.PERSISTENT.rawValue + + /// Data alies format. + public var format: String = VGSVaultAliasFormat.UUID.rawValue +} + +/// Class responsible for configuration `VGSDateTextField` or `VGSTextField` with `fieldType = .date`. +/// Extends `VGSConfiguration`. Required to work with tokenization API. +public final class VGSDateTokenizationConfiguration: VGSConfiguration, VGSDateConfigurationProtocol, VGSTextFieldTokenizationConfigurationProtocol, VGSFormatSerializableProtocol { + + // MARK: - Properties + /// Start date used to fill out the date picker + private var datePickerStartDate: VGSDate = VGSDateConfiguration.minValidPickerStartDate + + /// End date used to fill out the date picker + private var datePickerEndDate: VGSDate = VGSDateConfiguration.maxValidPickerEndDate + + /// Get the list of years from `datePickerStartDate` to `datePickerEndDate`. + /// In case any of the dates are not set, it will use the default + /// values `minValidStartDate` and `maxValidEndDate` respectively + internal var years: [Int] { + Array(datePickerStartDate.year...datePickerEndDate.year) + } + + // MARK: - Constructor + /// Initialization + /// Date configuration initializer, if no `datePickerStartDate` is provided, + /// a default date will be used adding 100 years to the current date. + /// Similar approach will be used if `datePickerEndDate` is not provided, + /// it will be calculated removing 100 years from current date. + /// + /// - Parameters: + /// - vgs: `VGSCollect` instance. + /// - fieldName: associated `fieldName`. + /// - datePickerStartDate: optional `VGSDate` instance. + /// - datePickerEndDate: optional `VGSDate` instance. + public init(collector vgs: VGSCollect, + fieldName: String, + datePickerStartDate: VGSDate? = nil, + datePickerEndDate: VGSDate? = nil) { + /// Setup custom picker start date + if let startDate = datePickerStartDate { + self.datePickerStartDate = startDate + } + /// Setup custom picker end date + if let endDate = datePickerEndDate { + self.datePickerEndDate = endDate + } + /// Super initializer + super.init(collector: vgs, fieldName: fieldName) + } + + // MARK: - Overridden methods and properties + public override var type: FieldType { + get { return .date } + set {} + } + + // MARK: - VGSDateConfigurationProtocol implementation + public var inputSource: VGSTextFieldInputSource = .datePicker + public var inputDateFormat: VGSDateFormat? + public var outputDateFormat: VGSDateFormat? + + // MARK: - VGSFormatSerializableProtocol implementation + public var serializers: [VGSFormatSerializerProtocol] = [] + func serialize(_ content: String) -> [String: Any] { + return DateFormatConvertor.serialize(content, serializers: serializers, outputFormat: outputDateFormat) + } + internal var shouldSerialize: Bool { + return !serializers.isEmpty + } + + // MARK: - VGSDateTokenizationParameters implementation + public var tokenizationParameters = VGSDateTokenizationParameters() + internal var tokenizationConfiguration: VGSTokenizationParametersProtocol { + return tokenizationParameters + } +} + +// MARK: - `TextFormatConvertable` implementation +extension VGSDateTokenizationConfiguration: VGSTextFormatConvertable { + + /// :nodoc: + var inputFormat: InputConvertableFormat? { + return inputDateFormat + } + + /// :nodoc: + var outputFormat: OutputConvertableFormat? { + return outputDateFormat + } + + /// :nodoc: + var convertor: TextFormatConvertor { + return DateFormatConvertor() + } +} diff --git a/Sources/VGSCollectSDK/Core/TokenizationConfiguration/VGSExpDateTokenizationConfiguration.swift b/Sources/VGSCollectSDK/Core/TokenizationConfiguration/VGSExpDateTokenizationConfiguration.swift index 679b35de..9efaba4c 100644 --- a/Sources/VGSCollectSDK/Core/TokenizationConfiguration/VGSExpDateTokenizationConfiguration.swift +++ b/Sources/VGSCollectSDK/Core/TokenizationConfiguration/VGSExpDateTokenizationConfiguration.swift @@ -49,7 +49,7 @@ public final class VGSExpDateTokenizationConfiguration: VGSConfiguration, VGSExp // MARK: - `VGSExpDateConfiguration` implementation /// Serialize Expiration Date internal func serialize(_ content: String) -> [String: Any] { - return ExpDateFormatConvertor.serialize(content, serializers: serializers, outputFormat: outputFormat) + return ExpDateFormatConvertor.serialize(content, serializers: serializers, outputFormat: outputDateFormat) } /// Returns if Content should be Serialized @@ -58,18 +58,18 @@ public final class VGSExpDateTokenizationConfiguration: VGSConfiguration, VGSExp } } -/// Implement `FormatConvertable` protocol. -extension VGSExpDateTokenizationConfiguration: FormatConvertable { - - internal var outputFormat: VGSCardExpDateFormat? { - return outputDateFormat - } - - internal var inputFormat: VGSCardExpDateFormat? { - return inputDateFormat - } +/// Implement `TextFormatConvertable` protocol. +extension VGSExpDateTokenizationConfiguration: VGSTextFormatConvertable { + + var inputFormat: InputConvertableFormat? { + return inputDateFormat + } + + var outputFormat: OutputConvertableFormat? { + return outputDateFormat + } - internal var convertor: TextFormatConvertor { - return ExpDateFormatConvertor() - } + internal var convertor: TextFormatConvertor { + return ExpDateFormatConvertor() + } } diff --git a/Sources/VGSCollectSDK/Core/VGSDate.swift b/Sources/VGSCollectSDK/Core/VGSDate.swift new file mode 100644 index 00000000..315e8dbd --- /dev/null +++ b/Sources/VGSCollectSDK/Core/VGSDate.swift @@ -0,0 +1,84 @@ +// +// VGSDate.swift +// VGSCollectSDK +// + +import Foundation + +/// `Struct` that represents a date including `year`, `month` and `day`. It doesn't include `hours`, `minutes` or `seconds`. +public struct VGSDate { + + // MARK: - Properties + public var day: Int + public var month: Int + public var year: Int + + /// Get the day formatted value, for example if the day is `1` it is returned as `01` + public var dayFormatted: String { + return String(format: "%02d", day) + } + + /// Get the month formatted value, for example if the month is `3` it is returned as `03` + public var monthFormatted: String { + return String(format: "%02d", month) + } + + // MARK: - Initialization + /// Create a new instance of a `VGSDate` object, if the date is not valid, it returns `nil` + /// - Parameters: + /// - day: `Int`. Represents the day in the date. + /// - month: `Int`. Represents the month in the date. + /// - year: `Int`. Represents the year in the date. + /// - Returns: `VGSDate`, date reference or nil if the date is invalid. + public init?(day: Int, month: Int, year: Int) { + // Make sure it is a valid date + guard DateComponents( + calendar: Calendar(identifier: .gregorian), + year: year, + month: month, + day: day + ).isValidDate else { + let message = "Invalid day, month or year to create date at VGSDate initializer" + let event = VGSLogEvent(level: .warning, text: message, severityLevel: .error) + VGSCollectLogger.shared.forwardLogEvent(event) + return nil + } + // Save date data + self.day = day + self.month = month + self.year = year + } +} + +// MARK: - Equatable and Comparable implementation +extension VGSDate: Comparable { + + /// :nodoc: + public static func == (lhs: Self, rhs: Self) -> Bool { + return lhs.year == rhs.year && + lhs.month == rhs.month && + lhs.day == rhs.day + } + + /// :nodoc: + public static func < (lhs: VGSDate, rhs: VGSDate) -> Bool { + // Check year + if lhs.year < rhs.year { + return true + } + // If the year is equal, check month + else if lhs.year == rhs.year { + // Check month + if lhs.month < rhs.month { + return true + } + // If the month is equal, check day + else if lhs.month == rhs.month { + // Check day + return lhs.day < rhs.day + } + } + // The date at left is not less than date at right + return false + } +} diff --git a/Sources/VGSCollectSDK/Core/VGSDateConfiguration.swift b/Sources/VGSCollectSDK/Core/VGSDateConfiguration.swift new file mode 100644 index 00000000..5b7b15d4 --- /dev/null +++ b/Sources/VGSCollectSDK/Core/VGSDateConfiguration.swift @@ -0,0 +1,132 @@ +// +// VGSDateConfiguration.swift +// VGSCollectSDK +// + +import Foundation + +/// Define the methods and properties the date configuration must have +public protocol VGSDateConfigurationProtocol { + + /// Input source type. + var inputSource: VGSTextFieldInputSource {get set} + + /// Input date format to convert. + var inputDateFormat: VGSDateFormat? {get set} + + /// Output date format to convert. + var outputDateFormat: VGSDateFormat? {get set} +} + +/// Class responsible for configuration `VGSDateTextField` or `VGSTextField` with `fieldType = .date`. Extends `VGSConfiguration` +public final class VGSDateConfiguration: VGSConfiguration, VGSDateConfigurationProtocol, VGSFormatSerializableProtocol { + + // MARK: - Properties + /// Start date used to fill out the date picker + private var datePickerStartDate: VGSDate = VGSDateConfiguration.minValidPickerStartDate + + /// End date used to fill out the date picker + private var datePickerEndDate: VGSDate = VGSDateConfiguration.maxValidPickerEndDate + + /// Get the list of years from `datePickerStartDate` to `datePickerEndDate`. + /// In case any of the dates are not set, it will use the default + /// values `minValidStartDate` and `maxValidEndDate` respectively + internal var years: [Int] { + Array(datePickerStartDate.year...datePickerEndDate.year) + } + + // MARK: - Constructor + /// Initialization + /// Date configuration initializer, if no `datePickerStartDate` is provided, + /// a default date will be used adding 100 years to the current date. + /// Similar approach will be used if `datePickerEndDate` is not provided, + /// it will be calculated removing 100 years from current date. + /// + /// - Parameters: + /// - vgs: `VGSCollect` instance. + /// - fieldName: associated `fieldName`. + /// - datePickerStartDate: optional `VGSDate` instance. + /// - datePickerEndDate: optional `VGSDate` instance. + public init(collector vgs: VGSCollect, + fieldName: String, + datePickerStartDate: VGSDate? = nil, + datePickerEndDate: VGSDate? = nil) { + /// Setup custom picker start date + if let startDate = datePickerStartDate { + self.datePickerStartDate = startDate + } + /// Setup custom picker end date + if let endDate = datePickerEndDate { + self.datePickerEndDate = endDate + } + /// Super initializer + super.init(collector: vgs, fieldName: fieldName) + } + + // MARK: - Overridden methods and properties + public override var type: FieldType { + get { return .date } + set {} + } + + // MARK: - VGSDateConfigurationProtocol implementation + public var inputSource: VGSTextFieldInputSource = .datePicker + public var inputDateFormat: VGSDateFormat? + public var outputDateFormat: VGSDateFormat? + + // MARK: - VGSFormatSerializableProtocol implementation + public var serializers: [VGSFormatSerializerProtocol] = [] + func serialize(_ content: String) -> [String: Any] { + return DateFormatConvertor.serialize(content, serializers: serializers, outputFormat: outputDateFormat) + } + internal var shouldSerialize: Bool { + return !serializers.isEmpty + } +} + +// MARK: - Static properties and methods +extension VGSDateConfiguration { + + /// Amount of years used to calculate the minimun and maximun date picker default dates + public static var validYearsCount = 100 + + /// Minimun date picker start date, current year minus `validYearsCount` + public static let minValidPickerStartDate = VGSDate( + day: 1, + month: 1, + year: Calendar.currentYear - validYearsCount + )! + + /// Maximun date picker valid end date, current year plus `validYearsCount` + public static var maxValidPickerEndDate = VGSDate( + day: 1, + month: 1, + year: Calendar.currentYear + validYearsCount + )! + + /// Get the array of years used as default when no start date or end date are defined + internal static var defaultYears: [Int] = { + let startYear = VGSDateConfiguration.minValidPickerStartDate.year + let endYear = VGSDateConfiguration.maxValidPickerEndDate.year + return Array(startYear...endYear) + }() +} + +// MARK: - `TextFormatConvertable` implementation +extension VGSDateConfiguration: VGSTextFormatConvertable { + + /// :nodoc: + var inputFormat: InputConvertableFormat? { + return inputDateFormat + } + + /// :nodoc: + var outputFormat: OutputConvertableFormat? { + return outputDateFormat + } + + /// :nodoc: + var convertor: TextFormatConvertor { + return DateFormatConvertor() + } +} diff --git a/Sources/VGSCollectSDK/Core/VGSExpDateConfiguration.swift b/Sources/VGSCollectSDK/Core/VGSExpDateConfiguration.swift index 9f441a29..9efb0006 100644 --- a/Sources/VGSCollectSDK/Core/VGSExpDateConfiguration.swift +++ b/Sources/VGSCollectSDK/Core/VGSExpDateConfiguration.swift @@ -51,7 +51,7 @@ public final class VGSExpDateConfiguration: VGSConfiguration, VGSExpDateConfigur // MARK: - `VGSExpDateConfiguration` implementation /// Serialize Expiration Date internal func serialize(_ content: String) -> [String: Any] { - return ExpDateFormatConvertor.serialize(content, serializers: serializers, outputFormat: outputFormat) + return ExpDateFormatConvertor.serialize(content, serializers: serializers, outputFormat: outputDateFormat) } /// Returns if Content should be Serialized @@ -60,18 +60,21 @@ public final class VGSExpDateConfiguration: VGSConfiguration, VGSExpDateConfigur } } -/// Implement `FormatConvertable` protocol. -extension VGSExpDateConfiguration: FormatConvertable { - - internal var outputFormat: VGSCardExpDateFormat? { - return outputDateFormat - } - - internal var inputFormat: VGSCardExpDateFormat? { - return inputDateFormat - } - - internal var convertor: TextFormatConvertor { - return ExpDateFormatConvertor() - } +/// Implement `TextFormatConvertable` protocol. +extension VGSExpDateConfiguration: VGSTextFormatConvertable { + + /// :nodoc: + var inputFormat: InputConvertableFormat? { + return inputDateFormat + } + + /// :nodoc: + var outputFormat: OutputConvertableFormat? { + return outputDateFormat + } + + /// :nodoc: + var convertor: TextFormatConvertor { + return ExpDateFormatConvertor() + } } diff --git a/Sources/VGSCollectSDK/Core/VGSPaymentCards/Core/VGSCustomPaymentCardModel.swift b/Sources/VGSCollectSDK/Core/VGSPaymentCards/Core/VGSCustomPaymentCardModel.swift index 23a1ac4e..f9ceb826 100644 --- a/Sources/VGSCollectSDK/Core/VGSPaymentCards/Core/VGSCustomPaymentCardModel.swift +++ b/Sources/VGSCollectSDK/Core/VGSPaymentCards/Core/VGSCustomPaymentCardModel.swift @@ -42,7 +42,7 @@ public struct VGSCustomPaymentCardModel: VGSPaymentCardModelProtocol { /// Image, associated with CVC for Payment Card Brand. public var cvcIcon: UIImage? - // MARK: - Initialzation + // MARK: - Initialization /// Initializer. /// - Parameters: diff --git a/Sources/VGSCollectSDK/UIElements/Text Field/VGSDateTextField.swift b/Sources/VGSCollectSDK/UIElements/Text Field/VGSDateTextField.swift new file mode 100644 index 00000000..906c5f6a --- /dev/null +++ b/Sources/VGSCollectSDK/UIElements/Text Field/VGSDateTextField.swift @@ -0,0 +1,361 @@ +// +// VGSDateTextField.swift +// VGSCollectSDK +// + +import UIKit + +/// An object that displays an editable text area. Can be use instead of a `VGSTextField` when need to show picker view with a Date. It support to define a range of valid dates to select from. +public final class VGSDateTextField: VGSTextField { + + // MARK: - Inner objects + /// Available month Label formats in `UIPickerView` + public enum MonthFormat { + /// Short month name, e.g.: `Jan` + case shortSymbols + /// Long month name, e.g.: `January` + case longSymbols + /// Month number: e.g.: `01` + case numbers + } + + // MARK: - Properties + /// UIPickerView month label format + public var monthPickerFormat: MonthFormat = .shortSymbols { + didSet { + updateMonthsDataSource() + } + } + /// UIPickerView components order, it is based on the input format of the configuration + internal var pickerDateFormat: VGSDateFormat? + /// Visual day data source + internal var daysDataSource = [String]() + /// Visual month data source + internal var monthsDataSource = [String]() + /// Visual year data source + internal var yearsDataSource = [String]() + /// Valid days range, it is updated when the Month or Year are selected + internal lazy var days = [Int]() + /// Valid months range + internal lazy var months = Array(1...12) + /// Valid years range, it is updated when the configuration is set + internal lazy var years = [Int]() + /// Store the components index in the picker + private let pickerComponent = (left: 0, center: 1, right: 2) + + // MARK: - Properties + /// `UIPickerView` reference + internal lazy var picker: UIPickerView = { + let picker = UIPickerView() + picker.delegate = self + picker.dataSource = self + return picker + }() + + // MARK: - Overridden methods and properties + public override var configuration: VGSConfiguration? { + didSet { + fieldType = .date + } + } + + override func mainInitialization() { + super.mainInitialization() + setupDatePicker() + } + + override func setupField(with configuration: VGSConfiguration) { + super.setupField(with: configuration) + guard let config = configuration as? VGSDateConfigurationProtocol else { + return + } + + // setup input source + switch config.inputSource { + case .datePicker: + setupDatePicker() + case .keyboard: + setupKeyboard(with: configuration) + } + } +} + +// MARK: - UIPickerViewDelegate and UIPickerViewDataSource implementation +extension VGSDateTextField: UIPickerViewDelegate, UIPickerViewDataSource { + + /// :nodoc: Picker view dataSource implementation. + public func numberOfComponents(in pickerView: UIPickerView) -> Int { + return 3 + } + + /// :nodoc: Picker view dataSource implementation. + public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { + switch component { + case pickerComponent.left: + switch pickerDateFormat { + case .ddmmyyyy: + return daysDataSource.count + case .mmddyyyy: + return monthsDataSource.count + case .yyyymmdd: + return yearsDataSource.count + default: + // Default format: .mmddyyyy + return monthsDataSource.count + } + + case pickerComponent.center: + switch pickerDateFormat { + case .ddmmyyyy, .yyyymmdd: + return monthsDataSource.count + case .mmddyyyy: + return daysDataSource.count + default: + // Default format: .mmddyyyy + return daysDataSource.count + } + + case pickerComponent.right: + switch pickerDateFormat { + case .ddmmyyyy, .mmddyyyy: + return yearsDataSource.count + case .yyyymmdd: + return daysDataSource.count + default: + // Default format: .mmddyyyy + return yearsDataSource.count + } + + default: + // This should never happend + assertionFailure("No valid component index for picker") + return 0 + } + } + + /// :nodoc: Picker view delegate implementation. + public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { + + switch component { + case pickerComponent.left: + switch pickerDateFormat { + case .ddmmyyyy: + return daysDataSource[row] + case .mmddyyyy: + return monthsDataSource[row] + case .yyyymmdd: + return yearsDataSource[row] + default: + // Default format: .mmddyyyy + return monthsDataSource[row] + } + + case pickerComponent.center: + switch pickerDateFormat { + case .ddmmyyyy, .yyyymmdd: + return monthsDataSource[row] + case .mmddyyyy: + return daysDataSource[row] + default: + // Default format: .mmddyyyy + return daysDataSource[row] + } + + case pickerComponent.right: + switch pickerDateFormat { + case .ddmmyyyy, .mmddyyyy: + return yearsDataSource[row] + case .yyyymmdd: + return daysDataSource[row] + default: + // Default format: .mmddyyyy + return yearsDataSource[row] + } + + default: + // This should never happend + assertionFailure("No valid component index for picker") + return "" + } + } + + /// :nodoc: Picker view delegate implementation. + public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { + switch component { + case pickerComponent.left: + if pickerDateFormat == .mmddyyyy || pickerDateFormat == .yyyymmdd { + updateDaysDataSource() + } + + case pickerComponent.center: + if pickerDateFormat == .ddmmyyyy || pickerDateFormat == .yyyymmdd { + updateDaysDataSource() + } + + case pickerComponent.right: + if pickerDateFormat == .ddmmyyyy || pickerDateFormat == .mmddyyyy { + updateDaysDataSource() + } + default: + // This should never happend + assertionFailure("No valid component index for picker") + } + + // Update text selection + updateTextFieldWithDatePickerSelection() + } +} + +// MARK: - Private methods +private extension VGSDateTextField { + + var pickerDayComponent: Int { + switch pickerDateFormat { + case .ddmmyyyy: + return pickerComponent.left + case .mmddyyyy: + return pickerComponent.center + case .yyyymmdd: + return pickerComponent.right + default: + // Default format: .mmddyyyy + return pickerComponent.center + } + } + + var pickerMonthComponent: Int { + switch pickerDateFormat { + case .ddmmyyyy, .yyyymmdd: + return pickerComponent.center + case .mmddyyyy: + return pickerComponent.left + default: + // Default format: .mmddyyyy + return pickerComponent.left + } + } + + var pickerYearComponent: Int { + switch pickerDateFormat { + case .ddmmyyyy, .mmddyyyy: + return pickerComponent.right + case .yyyymmdd: + return pickerComponent.left + default: + // Default format: .mmddyyyy + return pickerComponent.right + } + } + + func updateMonthsDataSource() { + switch monthPickerFormat { + case .shortSymbols: + monthsDataSource = DateFormatter().shortMonthSymbols + case .longSymbols: + monthsDataSource = DateFormatter().monthSymbols + case .numbers: + monthsDataSource = months.map { (String(format: "%02d", $0)) } + } + } + + func updateDaysDataSource() { + /// Make sure it has valid data for months and years + guard months.count > 0, years.count > 0 else { + return + } + /// Get month and year + var day = 0 + if days.count > 0 { + day = days[picker.selectedRow(inComponent: pickerDayComponent)] + } + let month = months[picker.selectedRow(inComponent: pickerMonthComponent)] + let year = years[picker.selectedRow(inComponent: pickerYearComponent)] + + /// Get amount of days in selected month and year + let dateComponents = DateComponents(year: year, month: month) + let calendar = Calendar(identifier: .gregorian) + let date = calendar.date(from: dateComponents)! + + // Get range of days in month + if let range = calendar.range(of: .day, in: .month, for: date) { + days = range.map { $0 } + } + daysDataSource = days.map { String($0) } + + // Reload days + picker.reloadComponent(pickerDayComponent) + + // If the day is not valid in the month and year, update it to the last one in the days collection + if day >= days.count { + picker.selectRow(days.count - 1, inComponent: pickerDayComponent, animated: true) + } + } + + func updateYearsDataSource() { + /// Make sure the configuration is valid + if let config = configuration as? VGSDateConfiguration { + years = config.years + } else if let tokenizationConfig = configuration as? VGSDateTokenizationConfiguration { + years = tokenizationConfig.years + } else { + years = VGSDateConfiguration.defaultYears + } + yearsDataSource = years.map { String($0) } + } + + func updateTextFieldWithDatePickerSelection() { + /// Get date components + let day = days[picker.selectedRow(inComponent: pickerDayComponent)] + let month = months[picker.selectedRow(inComponent: pickerMonthComponent)] + let year = years[picker.selectedRow(inComponent: pickerYearComponent)] + + /// Get input date format, if not set, use the default + var inputDateFormat = VGSDateFormat.default + if let config = configuration as? VGSDateConfigurationProtocol, + let fieldDateFormat = config.inputDateFormat { + inputDateFormat = fieldDateFormat + } + + /// Create the date string and update the display text + if let date = VGSDate(day: day, month: month, year: year) { + self.setText(inputDateFormat.mapDatePickerDataForFieldFormat(date)) + } + } + + func scrollToCurrentMonthAndYear(animated: Bool) { + let currentMonthIndex = Calendar.currentMonth - 1 + let currentYearIndex = Calendar.currentYear - 1 + picker.selectRow(currentMonthIndex, inComponent: pickerMonthComponent, animated: animated) + picker.selectRow(currentYearIndex, inComponent: pickerYearComponent, animated: animated) + } + + /// Setup date picker configuration + func setupDatePicker() { + textField.inputView = picker + updateMonthsDataSource() + updateYearsDataSource() + updateDaysDataSource() + + // If the date format change, reload the picker component + if let config = configuration as? VGSDateConfigurationProtocol, + let fieldDateFormat = config.inputDateFormat { + // Update the picker format only if it is different + if pickerDateFormat != fieldDateFormat { + pickerDateFormat = fieldDateFormat + picker.reloadAllComponents() + } + } + scrollToCurrentMonthAndYear(animated: false) + textField.inputAccessoryView = UIView() + } + + /// Setup keyboard configuration + func setupKeyboard(with configuration: VGSConfiguration) { + textField.keyboardType = configuration.keyboardType ?? configuration.type.keyboardType + textField.returnKeyType = configuration.returnKeyType ?? .default + textField.keyboardAppearance = configuration.keyboardAppearance ?? .default + // Remove date picker if any + textField.inputView = nil + textField.inputAccessoryView = nil + } +} diff --git a/Sources/VGSCollectSDK/UIElements/Text Field/VGSExpDateTextField.swift b/Sources/VGSCollectSDK/UIElements/Text Field/VGSExpDateTextField.swift index 229adbb3..569f7cd0 100644 --- a/Sources/VGSCollectSDK/UIElements/Text Field/VGSExpDateTextField.swift +++ b/Sources/VGSCollectSDK/UIElements/Text Field/VGSExpDateTextField.swift @@ -181,7 +181,8 @@ private extension VGSExpDateTextField { let inputDateFormat: VGSCardExpDateFormat /// Check if specific `.inputFormat` is set in field configuration - if let config = configuration as? VGSExpDateConfiguration, let fieldDateFormat = config.inputFormat { + if let config = configuration as? VGSExpDateConfiguration, + let fieldDateFormat = config.inputFormat as? VGSCardExpDateFormat { inputDateFormat = fieldDateFormat } else { /// Default format could be mm/yy or mm/yyyy. In other case `.inputDateFormat` should be specified diff --git a/Sources/VGSCollectSDK/UIElements/Text Field/VGSTextField.swift b/Sources/VGSCollectSDK/UIElements/Text Field/VGSTextField.swift index fd61038a..b6ce1663 100644 --- a/Sources/VGSCollectSDK/UIElements/Text Field/VGSTextField.swift +++ b/Sources/VGSCollectSDK/UIElements/Text Field/VGSTextField.swift @@ -10,6 +10,7 @@ import UIKit #endif +// swiftlint:disable file_length /// An object that displays an editable text area in user interface. public class VGSTextField: UIView { @@ -168,13 +169,16 @@ public class VGSTextField: UIView { public func isContentEqual(_ textField: VGSTextField) -> Bool { return self.textField.getSecureRawText == textField.textField.getSecureRawText } - - internal func getOutputText() -> String? { - if let config = configuration as? FormatConvertable, let input = textField.getSecureTextWithDivider, let outputFormat = config.outputFormat, let inputFormat = config.inputFormat { - return config.convertor.convert(input, inputFormat: inputFormat, outputFormat: outputFormat) + + internal func getOutputText() -> String? { + if let config = configuration as? VGSTextFormatConvertable, + let input = textField.getSecureTextWithDivider, + let inputFormat = config.inputFormat, + let outputFormat = config.outputFormat { + return config.convertor.convert(input, inputFormat: inputFormat, outputFormat: outputFormat) + } + return textField.getSecureTextWithDivider } - return textField.getSecureTextWithDivider - } /// Field Configuration internal func setupField(with configuration: VGSConfiguration) { @@ -385,7 +389,6 @@ internal extension VGSTextField { return !textField.formatPattern.isEmpty } } -// swiftlint:disable file_length // MARK: - MaskedTextFieldDelegate @@ -422,3 +425,4 @@ extension UIView { layer.cornerRadius = 4 } } +// swiftlint:enable file_length diff --git a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/AnyType/VGSValidationRuleLength.swift b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/AnyType/VGSValidationRuleLength.swift index 1381b28e..8b2fa615 100644 --- a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/AnyType/VGSValidationRuleLength.swift +++ b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/AnyType/VGSValidationRuleLength.swift @@ -22,7 +22,7 @@ public struct VGSValidationRuleLength: VGSValidationRuleProtocol { /// Validation Error public let error: VGSValidationError - /// Initialzation + /// Initialization /// /// - Parameters: /// - error:`VGSValidationError` - error on failed validation relust. diff --git a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/AnyType/VGSValidationRuleLengthMatch.swift b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/AnyType/VGSValidationRuleLengthMatch.swift index 547c370a..7efdfc31 100644 --- a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/AnyType/VGSValidationRuleLengthMatch.swift +++ b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/AnyType/VGSValidationRuleLengthMatch.swift @@ -19,7 +19,7 @@ public struct VGSValidationRuleLengthMatch: VGSValidationRuleProtocol { /// Validation Error public let error: VGSValidationError - /// Initialzation + /// Initialization /// /// - Parameters: /// - error:`VGSValidationError` - error on failed validation relust. diff --git a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/AnyType/VGSValidationRulePattern.swift b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/AnyType/VGSValidationRulePattern.swift index 30b2cd23..c79e8ac8 100644 --- a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/AnyType/VGSValidationRulePattern.swift +++ b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/AnyType/VGSValidationRulePattern.swift @@ -19,7 +19,7 @@ public struct VGSValidationRulePattern: VGSValidationRuleProtocol { /// Validation Error public let error: VGSValidationError - /// Initialzation + /// Initialization /// /// - Parameters: /// - error:`VGSValidationError` - error on failed validation relust. diff --git a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Card/VGSValidationRuleLuhnCheck.swift b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Card/VGSValidationRuleLuhnCheck.swift index 950dbf2e..49424366 100644 --- a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Card/VGSValidationRuleLuhnCheck.swift +++ b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Card/VGSValidationRuleLuhnCheck.swift @@ -16,7 +16,7 @@ public struct VGSValidationRuleLuhnCheck: VGSValidationRuleProtocol { /// Validation Error public var error: VGSValidationError - /// Initialzation + /// Initialization /// /// - Parameters: /// - error:`VGSValidationError` - error on failed validation relust. diff --git a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Card/VGSValidationRulePaymentCard.swift b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Card/VGSValidationRulePaymentCard.swift index 620fc99f..77884d15 100644 --- a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Card/VGSValidationRulePaymentCard.swift +++ b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Card/VGSValidationRulePaymentCard.swift @@ -21,7 +21,7 @@ public struct VGSValidationRulePaymentCard: VGSValidationRuleProtocol { /// Turn on/off validation of cards that are not defined in SDK - `CardBrand.unknown` public var validateUnknownCardBrand = false - /// Initialzation + /// Initialization /// /// - Parameters: /// - error:`VGSValidationError` - error on failed validation relust. @@ -29,7 +29,7 @@ public struct VGSValidationRulePaymentCard: VGSValidationRuleProtocol { self.error = error } - /// Initialzation + /// Initialization /// /// - Parameters: /// - error:`VGSValidationError` - error on failed validation relust. diff --git a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Date/VGSDateFormat.swift b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Date/VGSDateFormat.swift new file mode 100644 index 00000000..54c70463 --- /dev/null +++ b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Date/VGSDateFormat.swift @@ -0,0 +1,181 @@ +// +// VGSDateFormat.swift +// VGSCollectSDK +// + +/// Format used to validate a VGS date text input +public enum VGSDateFormat: InputConvertableFormat, OutputConvertableFormat { + case mmddyyyy + case ddmmyyyy + case yyyymmdd + + /// Initializer + /// - Parameter name: String object, date format name. + internal init?(name: String) { + switch name { + case "mmddyyyy": + self = .mmddyyyy + return + case "ddmmyyyy": + self = .ddmmyyyy + return + case "yyyymmdd": + self = .yyyymmdd + return + default: + print("WRONG name!: \(name)") + return nil + } + } + + /// Amount of expected characters for day date component + internal var daysCharacters: Int { + return 2 + } + + /// Amount of expected characters for month date component + internal var monthCharacters: Int { + return 2 + } + + /// Amount of expected characters for year date component + internal var yearCharacters: Int { + return 4 + } + + /// Amount of expected dividers in the formatted date + internal var dividerCharacters: Int { + return 2 + } + + /// Get the formatted date to be used as a string representation based + /// in the selected date format. + /// + /// - Returns: `String`, formatted date + internal func mapDatePickerDataForFieldFormat(_ date: VGSDate) -> String { + /// Day and month values + let dayString = String(format: "%02d", date.day) + let monthString = String(format: "%02d", date.month) + + /// Return the string of the date based on the format + switch self { + case .mmddyyyy: + return "\(monthString)\(dayString)\(date.year)" + case .ddmmyyyy: + return "\(dayString)\(monthString)\(date.year)" + case .yyyymmdd: + return "\(date.year)\(monthString)\(dayString)" + } + } + + /// Get the formatted date including the divider + internal func formatDate(_ date: VGSDate, divider: String) -> String { + /// Day and month values + let dayString = String(format: "%02d", date.day) + let monthString = String(format: "%02d", date.month) + + /// Return the string of the date based on the format + switch self { + case .mmddyyyy: + return "\(monthString)\(divider)\(dayString)\(divider)\(date.year)" + case .ddmmyyyy: + return "\(dayString)\(divider)\(monthString)\(divider)\(date.year)" + case .yyyymmdd: + return "\(date.year)\(divider)\(monthString)\(divider)\(dayString)" + } + } + + /// Format and validate an input string and try to convert it to `VGSDate` + /// - Parameter input: `String` object, input data. + /// - Returns: `VGSDate?`, date reference or `nil`. + internal func dateFromInput(_ input: String?) -> VGSDate? { + /// Make sure if is a valid input string + guard let input = input else { + return nil + } + /// Check the amount of chars per date component are correct + let expectedCount = daysCharacters + monthCharacters + yearCharacters + guard input.count == expectedCount else { + return nil + } + // Format the date + switch self { + case .mmddyyyy: + /// Get month, day and year + let month = Int(input.prefix(monthCharacters)) + let day = Int(input.prefix(monthCharacters + daysCharacters).dropFirst(monthCharacters)) + let year = Int(input.suffix(yearCharacters)) + /// Make sure the data is good to create the date + if let month = month, let day = day, let year = year { + return VGSDate(day: day, month: month, year: year) + } + + case .ddmmyyyy: + /// Get day, month and year + let day = Int(input.prefix(daysCharacters)) + let month = Int(input.prefix(daysCharacters + monthCharacters).dropFirst(daysCharacters)) + let year = Int(input.suffix(yearCharacters)) + /// Make sure the data is good to create the date + if let day = day, let month = month, let year = year { + return VGSDate(day: day, month: month, year: year) + } + + case .yyyymmdd: + /// Get year, month and day + let year = Int(input.prefix(yearCharacters)) + let month = Int(input.prefix(yearCharacters + monthCharacters).dropFirst(yearCharacters)) + let day = Int(input.suffix(daysCharacters)) + /// Make sure the data is good to create the date + if let year = year, let month = month, let day = day { + return VGSDate(day: day, month: month, year: year) + } + } + // By default return nil, no valid date + return nil + } + + /// Date format used for display in UI + public var displayFormat: String { + switch self { + case .mmddyyyy: + return "mm-dd-yyyy" + case .ddmmyyyy: + return "dd-mm-yyyy" + case .yyyymmdd: + return "yyyy-mm-dd" + } + } + + /// Date format pattern used to display in the text field + internal var formatPattern: String { + switch self { + case .mmddyyyy, .ddmmyyyy: + return "##-##-####" + case .yyyymmdd: + return "####-##-##" + } + } + + // MARK: - Static properties and methods + /// Default format + static public let `default`: VGSDateFormat = .mmddyyyy + + /// Search the separator used in the input + /// - Parameter input: `String` object, input data. + /// - Returns: `String`, divider reference or empty string. + static internal func dividerInInput(_ input: String) -> String { + /// Remove all digits + let dividers = input.components(separatedBy: CharacterSet.decimalDigits).split(separator: "") + /// There must be only 2 dividers + if dividers.count == 2, + let first = dividers.first?.first, + let second = dividers.last?.first { + /// The dividers must be the same + if String(first) == String(second) { + return String(first) + } + } + /// If no divider found, return empty + return "" + } +} diff --git a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Date/VGSValidationRuleDateRange.swift b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Date/VGSValidationRuleDateRange.swift new file mode 100644 index 00000000..5a6905b4 --- /dev/null +++ b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Date/VGSValidationRuleDateRange.swift @@ -0,0 +1,76 @@ +// +// VGSDateRangeValidationRule.swift +// VGSCollectSDK +// + +import Foundation + +/// Validation rule used to validate the date input in objects +/// like `VGSDateTextField`, `VGSTextField` and `VGSExpDateTextField` +public struct VGSValidationRuleDateRange: VGSValidationRuleProtocol { + + // MARK: - Properties + /// Store the start date, it can be null + internal let startDate: VGSDate? + + /// Store the end date, it can be null + internal let endDate: VGSDate? + + /// Date format used to validate the rule + public let dateFormat: VGSDateFormat + + /// Error used in case the validation is invalid + public let error: VGSValidationError + + // MARK: - Constructor + /// Initialization + /// + /// - Parameters: + /// - dateFormat: Format used to validate the rule, defaults to `VGSDateFormat.default`. + /// - error: Error used in case there is an error with the validation rule. + /// - startDate: optional `VGSDate` instance. + /// - endDate: optional `VGSDate` instance. + public init(dateFormat: VGSDateFormat = VGSDateFormat.default, + error: VGSValidationError, + start: VGSDate? = nil, + end: VGSDate? = nil) { + self.dateFormat = dateFormat + self.error = error + self.startDate = start + self.endDate = end + } +} + +// MARK: - VGSRuleValidator implementation +extension VGSValidationRuleDateRange: VGSRuleValidator { + + /// :nodoc: + internal func validate(input: String?) -> Bool { + /// Must have valid input + guard let input = input else { + return false + } + + /// Format input date match selected format + guard let inputDate = dateFormat.dateFromInput(input) else { + return false + } + + /// When startDate and endDate are set, validate that startDate `<=` inputDate `<=` endDate + if let startDate = startDate, let endDate = endDate { + return startDate <= inputDate && inputDate <= endDate + } + + /// When startDate is set, validate that startDate `<=` inputDate + if let startDate = startDate { + return startDate <= inputDate + } + + /// When endDate is set, validate that inputDate `<=` endDate + if let endDate = endDate { + return inputDate <= endDate + } + + return true + } +} diff --git a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Date/VGSValidationRuleExpirationDate.swift b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Date/VGSValidationRuleExpirationDate.swift index 98a7aa22..749d4f0e 100644 --- a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Date/VGSValidationRuleExpirationDate.swift +++ b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Date/VGSValidationRuleExpirationDate.swift @@ -9,7 +9,7 @@ import Foundation /// Payment Card Expiration Date Format -public enum VGSCardExpDateFormat { +public enum VGSCardExpDateFormat: InputConvertableFormat, OutputConvertableFormat { /// Exp.Date in format mm/yy: 01/22 case shortYear @@ -88,7 +88,7 @@ public struct VGSValidationRuleCardExpirationDate: VGSValidationRuleProtocol { /// Validation Error public let error: VGSValidationError - /// Initialzation + /// Initialization /// /// - Parameters: /// - error:`VGSValidationError` - error on failed validation relust. diff --git a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/VGSValidationError.swift b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/VGSValidationError.swift index aa36c81d..5305f02d 100644 --- a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/VGSValidationError.swift +++ b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/VGSValidationError.swift @@ -24,6 +24,9 @@ public enum VGSValidationErrorType: String { /// Default Validation error for `VGSValidationRuleCardExpirationDate` case expDate = "EXPIRATION_DATE_VALIDATION_ERROR" + + /// Default Validation error for `VGSValidationRuleDateRange` + case date = "DATE_VALIDATION_ERROR" /// Default Validation error for `VGSValidationRulePaymentCard` case cardNumber = "CARD_NUMBER_VALIDATION_ERROR" diff --git a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/VGSValidationRule.swift b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/VGSValidationRule.swift index 1afc01bc..7f9e92cb 100644 --- a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/VGSValidationRule.swift +++ b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/VGSValidationRule.swift @@ -20,10 +20,10 @@ public struct VGSValidationRuleSet { internal var rules = [AnyValidationRule]() - /// Initialzation + /// Initialization public init() { } - /// Initialzation + /// Initialization /// /// - Parameters: /// - rules: array of validation rules diff --git a/Sources/VGSCollectSDK/Utils/Convertors/DateFormatConvertor.swift b/Sources/VGSCollectSDK/Utils/Convertors/DateFormatConvertor.swift new file mode 100644 index 00000000..b6d85832 --- /dev/null +++ b/Sources/VGSCollectSDK/Utils/Convertors/DateFormatConvertor.swift @@ -0,0 +1,75 @@ +// +// DateFormatConvertor.swift +// VGSCollectSDK +// + +import Foundation + +/// Date format convertor +internal class DateFormatConvertor: TextFormatConvertor { + + /// Convert date string with input `VGSDateFormat` to output `VGSDateFormat` + func convert(_ input: String, + inputFormat: InputConvertableFormat, + outputFormat: OutputConvertableFormat) -> String { + /// Make sure the input and output formats are references to `VGSCardExpDateFormat` + guard let inputFormat = inputFormat as? VGSDateFormat, + let outputFormat = outputFormat as? VGSDateFormat else { + let text = "CANNOT CONVERT DATE FORMAT! NOT VALID INPUT OR OUTPUT FORMATS. WILL USE ORIGINAL(INPUT) DATE FORMAT!" + let event = VGSLogEvent(level: .warning, text: text, severityLevel: .warning) + VGSCollectLogger.shared.forwardLogEvent(event) + return input + } + + // Get digits + let result = input.digits + // Get output + if let inputDate = inputFormat.dateFromInput(result) { + /// Store the dividers + let divider = VGSDateFormat.dividerInInput(input) + // Return output date including the divider + return outputFormat.formatDate(inputDate, divider: divider) + } + + // Error, no valid input + let text = "CANNOT CONVERT DATE FORMAT! NOT VALID INPUT OR OUTPUT FORMATS. WILL USE ORIGINAL(INPUT) DATE FORMAT!" + let event = VGSLogEvent(level: .warning, text: text, severityLevel: .warning) + VGSCollectLogger.shared.forwardLogEvent(event) + return input + } + + /// Serializes date + /// - Parameters: + /// - content: `String` object, content to serialize + /// - serializers: `[VGSFormatSerializerProtocol]` object, an array of serializers. + /// - outputFormat: `VGSDateFormat` object, output date format, + /// - Returns: `[String: Any]` object, json with serialized data. + static internal func serialize(_ content: String, + serializers: [VGSFormatSerializerProtocol], + outputFormat: VGSDateFormat?) -> [String: Any] { + var result = [String: Any]() + for serializer in serializers { + if let serializer = serializer as? VGSDateSeparateSerializer { + /// Remove dividers + let dateDigitsString = content.digits + + /// Get output date format, or default if not set + let outputDateFormat = outputFormat ?? .default + + /// Check output date components length + if let outputDate = outputDateFormat.dateFromInput(dateDigitsString) { + /// Set result for specific field names + result[serializer.dayFieldName] = outputDate.dayFormatted + result[serializer.monthFieldName] = outputDate.monthFormatted + result[serializer.yearFieldName] = String(outputDate.year) + } else { + // Error, no valid output + let text = "CANNOT SERIALIZE DATE! NOT VALID OUTPUT FORMATS OR INPUT. WILL USE ORIGINAL(INPUT) DATE FORMAT!" + let event = VGSLogEvent(level: .warning, text: text, severityLevel: .warning) + VGSCollectLogger.shared.forwardLogEvent(event) + } + } + } + return result + } +} diff --git a/Sources/VGSCollectSDK/Utils/Convertors/ExpDateFormatConvertor.swift b/Sources/VGSCollectSDK/Utils/Convertors/ExpDateFormatConvertor.swift index da1b01b2..b6174a1c 100644 --- a/Sources/VGSCollectSDK/Utils/Convertors/ExpDateFormatConvertor.swift +++ b/Sources/VGSCollectSDK/Utils/Convertors/ExpDateFormatConvertor.swift @@ -11,89 +11,85 @@ import Foundation import UIKit #endif -internal protocol FormatConvertable { - /// Input text format - var inputFormat: VGSCardExpDateFormat? { get } - /// Output text format - var outputFormat: VGSCardExpDateFormat? { get } - /// Text convertor object - var convertor: TextFormatConvertor { get } -} - -internal protocol TextFormatConvertor { - func convert(_ input: String, inputFormat: VGSCardExpDateFormat, outputFormat: VGSCardExpDateFormat) -> String -} - /// Card Expiration date format convertor internal class ExpDateFormatConvertor: TextFormatConvertor { - - /// Convert Exp Date String with input `CardExpDateFormat` to Output `CardExpDateFormat` - func convert(_ input: String, inputFormat: VGSCardExpDateFormat, outputFormat: VGSCardExpDateFormat) -> String { - let inputYear = inputFormat.isYearFirst ? String(input.prefix(inputFormat.yearCharacters)) : String(input.suffix(inputFormat.yearCharacters)) - let inputMonth = inputFormat.isYearFirst ? input.suffix(inputFormat.monthCharacters) : input.prefix(inputFormat.monthCharacters) - let divider = inputFormat.isYearFirst ? String(input.dropLast(inputFormat.monthCharacters)).dropFirst(inputFormat.yearCharacters) : String(input.dropLast(inputFormat.yearCharacters)).dropFirst(inputFormat.monthCharacters) - - let dateFormatter = DateFormatter() - dateFormatter.calendar = Calendar(identifier: .gregorian) - dateFormatter.dateFormat = inputFormat.dateYearFormat - dateFormatter.locale = Locale(identifier: "en_US") - if let date = dateFormatter.date(from: inputYear) { - dateFormatter.dateFormat = outputFormat.dateYearFormat - let outputYear = dateFormatter.string(from: date) - let output = outputFormat.isYearFirst ? String(outputYear + divider + inputMonth) : - String(inputMonth + divider + outputYear) - return output + /// Convert Exp Date String with input `CardExpDateFormat` to Output `CardExpDateFormat` + func convert(_ input: String, inputFormat: InputConvertableFormat, outputFormat: OutputConvertableFormat) -> String { + /// Make sure the input and output formats are references to `VGSCardExpDateFormat` + guard let inputFormat = inputFormat as? VGSCardExpDateFormat, + let outputFormat = outputFormat as? VGSCardExpDateFormat else { + let text = "CANNOT CONVERT DATE FORMAT! NOT VALID INPUT OR OUTPUT FORMATS. WILL USE ORIGINAL(INPUT) DATE FORMAT!" + let event = VGSLogEvent(level: .warning, text: text, severityLevel: .warning) + VGSCollectLogger.shared.forwardLogEvent(event) + return input + } + /// Get input data + let inputYear = inputFormat.isYearFirst ? String(input.prefix(inputFormat.yearCharacters)) : String(input.suffix(inputFormat.yearCharacters)) + let inputMonth = inputFormat.isYearFirst ? input.suffix(inputFormat.monthCharacters) : input.prefix(inputFormat.monthCharacters) + let divider = inputFormat.isYearFirst ? String(input.dropLast(inputFormat.monthCharacters)).dropFirst(inputFormat.yearCharacters) : String(input.dropLast(inputFormat.yearCharacters)).dropFirst(inputFormat.monthCharacters) + + let dateFormatter = DateFormatter() + dateFormatter.calendar = Calendar(identifier: .gregorian) + dateFormatter.dateFormat = inputFormat.dateYearFormat + dateFormatter.locale = Locale(identifier: "en_US") + + if let date = dateFormatter.date(from: inputYear) { + dateFormatter.dateFormat = outputFormat.dateYearFormat + let outputYear = dateFormatter.string(from: date) + let output = outputFormat.isYearFirst ? String(outputYear + divider + inputMonth) : + String(inputMonth + divider + outputYear) + return output + } + let text = "CANNOT CONVERT DATE FORMAT! NOT VALID INPUT YEAR - \(inputYear). WILL USE ORIGINAL(INPUT) DATE FORMAT!" + let event = VGSLogEvent(level: .warning, text: text, severityLevel: .warning) + VGSCollectLogger.shared.forwardLogEvent(event) + + return input } - let text = "CANNOT CONVERT DATE FORMAT! NOT VALID INPUT YEAR - \(inputYear). WILL USE ORIGINAL(INPUT) DATE FORMAT!" - let event = VGSLogEvent(level: .warning, text: text, severityLevel: .warning) - VGSCollectLogger.shared.forwardLogEvent(event) - return input - } - - /// Serializes expiration date. - /// - Parameters: - /// - content: `String` object, content to serialize - /// - serializers: `[VGSFormatSerializerProtocol]` object, an array of serializers. - /// - outputFormat: `VGSCardExpDateFormat` object, output date format, - /// - Returns: `[String: Any]` object, json with serialized data. - static internal func serialize(_ content: String, serializers: [VGSFormatSerializerProtocol], outputFormat: VGSCardExpDateFormat?) -> [String: Any] { - var result = [String: Any]() - for serializer in serializers { - if let serializer = serializer as? VGSExpDateSeparateSerializer { - /// remove dividers - var dateDigitsString = content.digits - - /// get output date format, if not set - use default - let outputDateFormat = outputFormat ?? .shortYear - /// check output date components length - let outputMonthDigits = outputDateFormat.monthCharacters - let outputYearDigits = outputDateFormat.yearCharacters - - let mth: String - let year: String - if outputDateFormat.isYearFirst { - /// take month digitis - year = String(dateDigitsString.prefix(outputYearDigits)) - /// remove month digits - dateDigitsString = String(dateDigitsString.dropFirst(outputYearDigits)) - /// take year digitis - mth = String(dateDigitsString.prefix(outputMonthDigits)) - } else { - /// take month digitis - mth = String(dateDigitsString.prefix(outputMonthDigits)) - /// remove month digits - dateDigitsString = String(dateDigitsString.dropFirst(outputMonthDigits)) - /// take year digitis - year = String(dateDigitsString.prefix(outputYearDigits)) + /// Serializes expiration date. + /// - Parameters: + /// - content: `String` object, content to serialize + /// - serializers: `[VGSFormatSerializerProtocol]` object, an array of serializers. + /// - outputFormat: `VGSCardExpDateFormat` object, output date format, + /// - Returns: `[String: Any]` object, json with serialized data. + static internal func serialize(_ content: String, serializers: [VGSFormatSerializerProtocol], outputFormat: VGSCardExpDateFormat?) -> [String: Any] { + var result = [String: Any]() + for serializer in serializers { + if let serializer = serializer as? VGSExpDateSeparateSerializer { + /// remove dividers + var dateDigitsString = content.digits + + /// get output date format, if not set - use default + let outputDateFormat = outputFormat ?? .shortYear + /// check output date components length + let outputMonthDigits = outputDateFormat.monthCharacters + let outputYearDigits = outputDateFormat.yearCharacters + + let mth: String + let year: String + if outputDateFormat.isYearFirst { + /// take month digitis + year = String(dateDigitsString.prefix(outputYearDigits)) + /// remove month digits + dateDigitsString = String(dateDigitsString.dropFirst(outputYearDigits)) + /// take year digitis + mth = String(dateDigitsString.prefix(outputMonthDigits)) + } else { + /// take month digitis + mth = String(dateDigitsString.prefix(outputMonthDigits)) + /// remove month digits + dateDigitsString = String(dateDigitsString.dropFirst(outputMonthDigits)) + /// take year digitis + year = String(dateDigitsString.prefix(outputYearDigits)) + } + + /// set result for specific fieldnames + result[serializer.monthFieldName] = mth + result[serializer.yearFieldName] = year + } } - - /// set result for specific fieldnames - result[serializer.monthFieldName] = mth - result[serializer.yearFieldName] = year - } + return result } - return result - } } diff --git a/Sources/VGSCollectSDK/Utils/Convertors/VGSTextFormatConvertable.swift b/Sources/VGSCollectSDK/Utils/Convertors/VGSTextFormatConvertable.swift new file mode 100644 index 00000000..2a8242e5 --- /dev/null +++ b/Sources/VGSCollectSDK/Utils/Convertors/VGSTextFormatConvertable.swift @@ -0,0 +1,31 @@ +// +// VGSTextFormatConvertable.swift +// VGSCollectSDK +// + +import Foundation + +/// Base protocol describing the input format to conver a string value +protocol InputConvertableFormat { } + +/// Base protocol describing the output format to conver a string value +protocol OutputConvertableFormat { } + +/// Base protocol to implements the method to convert an `input` string +/// with input `InputConvertableFormat` to output `OutputConvertableFormat` +protocol TextFormatConvertor { + func convert(_ input: String, + inputFormat: InputConvertableFormat, + outputFormat: OutputConvertableFormat) -> String +} + +/// Base protocol to implement the input and output formats and +/// the convertor for input strings +protocol VGSTextFormatConvertable { + /// Input text format + var inputFormat: InputConvertableFormat? { get } + /// Output text format + var outputFormat: OutputConvertableFormat? { get } + /// Text convertor object + var convertor: TextFormatConvertor { get } +} diff --git a/Sources/VGSCollectSDK/Utils/Extensions/Utils.swift b/Sources/VGSCollectSDK/Utils/Extensions/Utils.swift index f6903331..defc0aef 100644 --- a/Sources/VGSCollectSDK/Utils/Extensions/Utils.swift +++ b/Sources/VGSCollectSDK/Utils/Extensions/Utils.swift @@ -46,7 +46,7 @@ internal class Utils { /// VGS Collect SDK Version. /// Necessary since SPM doesn't track info plist correctly: https://forums.swift.org/t/add-info-plist-on-spm-bundle/40274/5 - static let vgsCollectVersion: String = "1.13.0" + static let vgsCollectVersion: String = "1.14.0" } extension Dictionary { diff --git a/Sources/VGSCollectSDK/Utils/Helpers/Serializers/VGSDateSeparateSerializer.swift b/Sources/VGSCollectSDK/Utils/Helpers/Serializers/VGSDateSeparateSerializer.swift new file mode 100644 index 00000000..737aeaa9 --- /dev/null +++ b/Sources/VGSCollectSDK/Utils/Helpers/Serializers/VGSDateSeparateSerializer.swift @@ -0,0 +1,32 @@ +// +// VGSDateSeparateSerializer.swift +// VGSCollectSDK +// + +import Foundation + +public struct VGSDateSeparateSerializer: VGSFormatSerializerProtocol { + + // MARK: - Properties + /// Field Name that will be used as a JSON key with day value from date string on send request. + public let dayFieldName: String + + /// Field Name that will be used as a JSON key with month value from date string on send request. + public let monthFieldName: String + + /// Field Name that will be used as a JSON key with year value from date string on send request. + public let yearFieldName: String + + // MARK: - Initialization + /// Initialization + /// + /// - Parameters: + /// - dayFielddName: key, that should be associated with day value in request JSON. + /// - monthFieldName: key, that should be associated with month value in request JSON. + /// - yearFieldName: key, that should be associated with year value in request JSON. + public init(dayFieldName: String, monthFieldName: String, yearFieldName: String) { + self.dayFieldName = dayFieldName + self.monthFieldName = monthFieldName + self.yearFieldName = yearFieldName + } +} diff --git a/Tests/FrameworkTests/ConvertorsTests/DateConvertorTests.swift b/Tests/FrameworkTests/ConvertorsTests/DateConvertorTests.swift new file mode 100644 index 00000000..289bdf02 --- /dev/null +++ b/Tests/FrameworkTests/ConvertorsTests/DateConvertorTests.swift @@ -0,0 +1,309 @@ +// +// DateConvertorTests.swift +// FrameworkTests +// + +import XCTest +@testable import VGSCollectSDK + +class DateConvertorTests: VGSCollectBaseTestCase { + + // MARK: - Properties + private var collector: VGSCollect! + private var textField: VGSDateTextField! + + // MARK: - Inner objects + struct TestDataType { + let input: String + let output: String + } + + // MARK: - Overrides + override func setUp() { + super.setUp() + + collector = VGSCollect(id: "any") + textField = VGSDateTextField() + } + + override func tearDown() { + collector = nil + textField = nil + } + + // MARK: - Tests + /// Test to convert a date from default format + func testConvertDate() { + /// Setup configuration + let config = VGSDateConfiguration(collector: collector, fieldName: "test_field") + textField.configuration = config + + /// Test dates + let testDates: [TestDataType] = [ + TestDataType(input: "12/10/2021", output: "12/10/2021"), + TestDataType(input: "01/04/2050", output: "01/04/2050"), + TestDataType(input: "05/07/2100", output: "05/07/2100") + ] + + /// Assert: Test dates output + for date in testDates { + textField.setText(date.input) + XCTAssertEqual(textField.getOutputText(), date.output) + } + } + + /// Test to convert a date from ddmmyyy to ddmmyyy + func testConvertDate_ddmmyyyy_to_ddmmyyyy() { + /// Setup configuration + let config = VGSDateConfiguration(collector: collector, fieldName: "test_field") + config.formatPattern = VGSDateFormat.ddmmyyyy.formatPattern + config.inputDateFormat = .ddmmyyyy + config.outputDateFormat = .ddmmyyyy + textField.configuration = config + + /// Test dates + let testDates: [TestDataType] = [ + TestDataType(input: "12/10/2021", output: "12/10/2021"), + TestDataType(input: "01/04/2050", output: "01/04/2050"), + TestDataType(input: "05/07/2100", output: "05/07/2100") + ] + + /// Assert: Test dates + for date in testDates { + textField.setText(date.input) + XCTAssertEqual(textField.getOutputText(), date.output) + } + } + + /// Test to convert a date from ddmmyyy to mmddyyyy + func testConvertDate_ddmmyyyy_to_mmddyyyy() { + /// Setup configuration + let config = VGSDateConfiguration(collector: collector, fieldName: "test_field") + config.formatPattern = VGSDateFormat.ddmmyyyy.formatPattern + config.inputDateFormat = .ddmmyyyy + config.outputDateFormat = .mmddyyyy + textField.configuration = config + + /// Test dates + let testDates: [TestDataType] = [ + TestDataType(input: "12/10/2021", output: "10/12/2021"), + TestDataType(input: "01/04/2050", output: "04/01/2050"), + TestDataType(input: "05/07/2100", output: "07/05/2100") + ] + + /// Assert: Test dates + for date in testDates { + textField.setText(date.input) + XCTAssertEqual(textField.getOutputText(), date.output) + } + } + + /// Test to convert a date from ddmmyyy to yyyymmdd + func testConvertDate_ddmmyyyy_to_yyyymmdd() { + /// Setup configuration + let config = VGSDateConfiguration(collector: collector, fieldName: "test_field") + config.formatPattern = VGSDateFormat.ddmmyyyy.formatPattern + config.inputDateFormat = .ddmmyyyy + config.outputDateFormat = .yyyymmdd + textField.configuration = config + + /// Test dates + let testDates: [TestDataType] = [ + TestDataType(input: "12/10/2021", output: "2021/10/12"), + TestDataType(input: "01/04/2050", output: "2050/04/01"), + TestDataType(input: "05/07/2100", output: "2100/07/05") + ] + + /// Assert: Test dates + for date in testDates { + textField.setText(date.input) + XCTAssertEqual(textField.getOutputText(), date.output) + } + } + + /// Test to convert a date from mmddyyyy to mmddyyyy + func testConvertDate_mmddyyyy_to_mmddyyyy() { + /// Setup configuration + let config = VGSDateConfiguration(collector: collector, fieldName: "test_field") + config.formatPattern = VGSDateFormat.mmddyyyy.formatPattern + config.inputDateFormat = .mmddyyyy + config.outputDateFormat = .mmddyyyy + textField.configuration = config + + /// Test dates + let testDates: [TestDataType] = [ + TestDataType(input: "10/12/2021", output: "10/12/2021"), + TestDataType(input: "04/01/2050", output: "04/01/2050"), + TestDataType(input: "07/05/2100", output: "07/05/2100") + ] + + /// Assert: Test dates + for date in testDates { + textField.setText(date.input) + XCTAssertEqual(textField.getOutputText(), date.output) + } + } + + /// Test to convert a date from mmddyyyy to ddmmyyy + func testConvertDate_mmddyyyy_to_ddmmyyy() { + /// Setup configuration + let config = VGSDateConfiguration(collector: collector, fieldName: "test_field") + config.formatPattern = VGSDateFormat.mmddyyyy.formatPattern + config.inputDateFormat = .mmddyyyy + config.outputDateFormat = .ddmmyyyy + textField.configuration = config + + /// Test dates + let testDates: [TestDataType] = [ + TestDataType(input: "10/12/2021", output: "12/10/2021"), + TestDataType(input: "04/01/2050", output: "01/04/2050"), + TestDataType(input: "07/05/2100", output: "05/07/2100") + ] + + /// Assert: Test dates + for date in testDates { + textField.setText(date.input) + XCTAssertEqual(textField.getOutputText(), date.output) + } + } + + /// Test to convert a date from mmddyyyy to yyyymmdd + func testConvertDate_mmddyyyy_to_yyyymmdd() { + /// Setup configuration + let config = VGSDateConfiguration(collector: collector, fieldName: "test_field") + config.formatPattern = VGSDateFormat.mmddyyyy.formatPattern + config.inputDateFormat = .mmddyyyy + config.outputDateFormat = .yyyymmdd + textField.configuration = config + + /// Test dates + let testDates: [TestDataType] = [ + TestDataType(input: "10/12/2021", output: "2021/10/12"), + TestDataType(input: "04/01/2050", output: "2050/04/01"), + TestDataType(input: "07/05/2100", output: "2100/07/05") + ] + + /// Assert: Test dates + for date in testDates { + textField.setText(date.input) + XCTAssertEqual(textField.getOutputText(), date.output) + } + } + + /// Test to convert a date from yyyymmdd to yyyymmdd + func testConvertDate_yyyymmdd_to_yyyymmdd() { + /// Setup configuration + let config = VGSDateConfiguration(collector: collector, fieldName: "test_field") + config.formatPattern = VGSDateFormat.yyyymmdd.formatPattern + config.inputDateFormat = .yyyymmdd + config.outputDateFormat = .yyyymmdd + textField.configuration = config + + /// Test dates + let testDates: [TestDataType] = [ + TestDataType(input: "2021/10/12", output: "2021/10/12"), + TestDataType(input: "2050/04/01", output: "2050/04/01"), + TestDataType(input: "2100/07/05", output: "2100/07/05") + ] + + /// Assert: Test dates + for date in testDates { + textField.setText(date.input) + XCTAssertEqual(textField.getOutputText(), date.output) + } + } + + /// Test to convert a date from yyyymmdd to mmddyyyy + func testConvertDate_yyyymmdd_to_mmddyyyy() { + /// Setup configuration + let config = VGSDateConfiguration(collector: collector, fieldName: "test_field") + config.formatPattern = VGSDateFormat.yyyymmdd.formatPattern + config.inputDateFormat = .yyyymmdd + config.outputDateFormat = .mmddyyyy + textField.configuration = config + + /// Test dates + let testDates: [TestDataType] = [ + TestDataType(input: "2021/10/12", output: "10/12/2021"), + TestDataType(input: "2050/04/01", output: "04/01/2050"), + TestDataType(input: "2100/07/05", output: "07/05/2100") + ] + + /// Assert: Test dates + for date in testDates { + textField.setText(date.input) + XCTAssertEqual(textField.getOutputText(), date.output) + } + } + + /// Test to convert a date from yyyymmdd to ddmmyyy + func testConvertDate_yyyymmdd_to_ddmmyyy() { + /// Setup configuration + let config = VGSDateConfiguration(collector: collector, fieldName: "test_field") + config.formatPattern = VGSDateFormat.yyyymmdd.formatPattern + config.inputDateFormat = .yyyymmdd + config.outputDateFormat = .ddmmyyyy + textField.configuration = config + + /// Test dates + let testDates: [TestDataType] = [ + TestDataType(input: "2021/10/12", output: "12/10/2021"), + TestDataType(input: "2050/04/01", output: "01/04/2050"), + TestDataType(input: "2100/07/05", output: "05/07/2100") + ] + + /// Assert: Test dates + for date in testDates { + textField.setText(date.input) + XCTAssertEqual(textField.getOutputText(), date.output) + } + } + + /// Test to convert a date with an empty divider + func testConvertDateEmptyDivider() { + /// Setup configuration + let config = VGSDateConfiguration(collector: collector, fieldName: "test_field") + config.formatPattern = VGSDateFormat.ddmmyyyy.formatPattern + config.divider = "" + config.inputDateFormat = .ddmmyyyy + config.outputDateFormat = .ddmmyyyy + textField.configuration = config + + /// Test dates + let testDates: [TestDataType] = [ + TestDataType(input: "12/10/2021", output: "12102021"), + TestDataType(input: "01/04/2050", output: "01042050"), + TestDataType(input: "05/07/2100", output: "05072100") + ] + + /// Assert: Test dates + for date in testDates { + textField.setText(date.input) + XCTAssertEqual(textField.getOutputText(), date.output) + } + } + + /// Test to convert a date with a custom divider + func testConvertDateCustomDivider() { + /// Setup configuration + let config = VGSDateConfiguration(collector: collector, fieldName: "test_field") + config.formatPattern = VGSDateFormat.ddmmyyyy.formatPattern + config.divider = "-/-" + config.inputDateFormat = .ddmmyyyy + config.outputDateFormat = .ddmmyyyy + textField.configuration = config + + /// Test dates + let testDates: [TestDataType] = [ + TestDataType(input: "12/10/2021", output: "12-/-10-/-2021"), + TestDataType(input: "01/04/2050", output: "01-/-04-/-2050"), + TestDataType(input: "05/07/2100", output: "05-/-07-/-2100") + ] + + /// Assert: Test dates + for date in testDates { + textField.setText(date.input) + XCTAssertEqual(textField.getOutputText(), date.output) + } + } +} diff --git a/Tests/FrameworkTests/Core/DateTests.swift b/Tests/FrameworkTests/Core/DateTests.swift new file mode 100644 index 00000000..3f2bba9d --- /dev/null +++ b/Tests/FrameworkTests/Core/DateTests.swift @@ -0,0 +1,53 @@ +// +// DateTests.swift +// FrameworkTests +// + +import XCTest +@testable import VGSCollectSDK + +class DateTests: VGSCollectBaseTestCase { + + // MARK: - Tests + /// Test date initialization + func testDateInitialization() { + /// Valid date + let validDate = VGSDate(day: 1, month: 1, year: 2010) + XCTAssertNotNil(validDate) + + /// Invalid date + let invalidDate = VGSDate(day: 50, month: 50, year: 2) + XCTAssertNil(invalidDate) + } + + /// Test date formatted + func testFormatters() { + /// Date + let date = VGSDate(day: 2, month: 6, year: 2010) + XCTAssertNotNil(date) + + /// Validate formatted month and day + XCTAssertEqual(date?.dayFormatted, "02") + XCTAssertEqual(date?.monthFormatted, "06") + } + + /// Test date comparable + func testDateComparable() { + /// Dates + let dateA = VGSDate(day: 12, month: 5, year: 2010)! + var dateB = VGSDate(day: 12, month: 5, year: 2010)! + + /// Validate equals + XCTAssertEqual(dateA, dateB) + + /// Validate not equals + dateB.year = 2011 + XCTAssertNotEqual(dateA, dateB) + + /// Validate less than + XCTAssertLessThan(dateA, dateB) + + /// Validate greater than + XCTAssertGreaterThan(dateB, dateA) + } +} diff --git a/Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_CustomConfig.json b/Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_CustomConfig.json new file mode 100644 index 00000000..71caacf9 --- /dev/null +++ b/Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_CustomConfig.json @@ -0,0 +1,44 @@ +{ + "test_data":[ + { + "monthFieldName":"month", + "dayFieldName":"day", + "yearFieldName":"year", + "fieldValue":"2030-/-01-/-15", + "expectedResult":{ + "month":"01", + "day":"15", + "year":"2030" + }, + "comment":"Single key fieldNames." + }, + { + "monthFieldName":"date.month", + "dayFieldName":"date.day", + "yearFieldName":"date.year", + "fieldValue":"2026-/-10-/-18", + "expectedResult":{ + "date":{ + "month":"10", + "day":"18", + "year":"2026" + } + }, + "comment":"Map to dot JSON" + }, + { + "monthFieldName":"date.month", + "dayFieldName":"day", + "yearFieldName":"year", + "fieldValue":"2015-/-05-/-25", + "expectedResult":{ + "date":{ + "month":"05" + }, + "day":"25", + "year":"2015" + }, + "comment":"Map to dot JSON with single key" + } + ] +} \ No newline at end of file diff --git a/Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_CustomExpDateOutputConfig.json b/Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_CustomExpDateOutputConfig.json new file mode 100644 index 00000000..7e07148a --- /dev/null +++ b/Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_CustomExpDateOutputConfig.json @@ -0,0 +1,44 @@ +{ + "test_data":[ + { + "monthFieldName":"month", + "dayFieldName":"day", + "yearFieldName":"year", + "fieldValue":"2030-/-01-/-15", + "expectedResult":{ + "month":"01", + "day":"15", + "year":"2030" + }, + "comment":"Single key fieldNames." + }, + { + "monthFieldName":"date.month", + "dayFieldName":"date.day", + "yearFieldName":"date.year", + "fieldValue":"2033-/-10-/-18", + "expectedResult":{ + "date":{ + "month":"10", + "day":"18", + "year":"2033" + } + }, + "comment":"Map to dot JSON" + }, + { + "monthFieldName":"date.month", + "dayFieldName":"day", + "yearFieldName":"year", + "fieldValue":"2025-/-05-/-25", + "expectedResult":{ + "date":{ + "month":"05" + }, + "day":"25", + "year":"2025" + }, + "comment":"Map to dot JSON with single key" + } + ] +} \ No newline at end of file diff --git a/Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_DefaultConfig.json b/Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_DefaultConfig.json new file mode 100644 index 00000000..2e0e4613 --- /dev/null +++ b/Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_DefaultConfig.json @@ -0,0 +1,44 @@ +{ + "test_data":[ + { + "monthFieldName":"month", + "dayFieldName":"day", + "yearFieldName":"year", + "fieldValue":"01/02/2030", + "expectedResult":{ + "month":"01", + "day":"02", + "year":"2030" + }, + "comment":"Single key fieldNames." + }, + { + "monthFieldName":"date.month", + "dayFieldName":"date.day", + "yearFieldName":"date.year", + "fieldValue":"10/02/2033", + "expectedResult":{ + "date":{ + "month":"10", + "day":"02", + "year":"2033" + } + }, + "comment":"Map to dot JSON" + }, + { + "monthFieldName":"date.month", + "dayFieldName":"day", + "yearFieldName":"year", + "fieldValue":"05/15/2025", + "expectedResult":{ + "date":{ + "month":"05" + }, + "day":"15", + "year":"2025" + }, + "comment":"Map to dot JSON with single key" + } + ] +} \ No newline at end of file diff --git a/Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_MapWithArrayMerge.json b/Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_MapWithArrayMerge.json new file mode 100644 index 00000000..6ea8d9b7 --- /dev/null +++ b/Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_MapWithArrayMerge.json @@ -0,0 +1,72 @@ +{ + "test_data":[ + { + "monthFieldName":"card_data[0].month", + "dayFieldName":"card_data[0].day", + "yearFieldName":"card_data[0].year", + "fieldValue":"01/30/2020", + "expectedResult":{ + "card_data":[ + { + "user_id":"123", + "month":"01", + "day":"30", + "year":"2020" + } + ] + }, + "comment":"Map to array with JSON." + }, + { + "monthFieldName":"card_data[1].month", + "dayFieldName":"card_data[1].day", + "yearFieldName":"card_data[1].year", + "fieldValue":"01/30/2020", + "expectedResult":{ + "card_data":[ + { + "user_id":"123" + }, + { + "month":"01", + "day":"30", + "year":"2020" + } + ] + }, + "comment":"Map to array with JSON adjusting array capacity." + }, + { + "monthFieldName":"card_data[2]", + "dayFieldName":"card_data[3]", + "yearFieldName":"card_data[4]", + "fieldValue":"01/30/2020", + "expectedResult":{ + "card_data":[ + { + "user_id":"123" + }, + null, + "01", + "30", + "2020" + ] + }, + "comment":"Map to array with primitive values and adjusting array capacity." + }, + { + "monthFieldName":"card_data.month", + "dayFieldName":"card_data.day", + "yearFieldName":"card_data.year", + "fieldValue":"10/30/2020", + "expectedResult":{ + "card_data":{ + "month":"10", + "day":"30", + "year":"2020" + } + }, + "comment":"Map to nested JSON. Merge fieldData as JSON with more priority as extra data array." + } + ] +} \ No newline at end of file diff --git a/Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_MapWithArrayOverwrite.json b/Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_MapWithArrayOverwrite.json new file mode 100644 index 00000000..50532ab9 --- /dev/null +++ b/Tests/FrameworkTests/Resources/DateSplitSerializerTestJSONs/VGSDateSerialization_MapWithArrayOverwrite.json @@ -0,0 +1,53 @@ +{ + "test_data":[ + { + "monthFieldName":"card_data[0].month", + "dayFieldName":"card_data[0].day", + "yearFieldName":"card_data[0].year", + "fieldValue":"01/30/2020", + "expectedResult":{ + "card_data":[ + { + "month":"01", + "day":"30", + "year":"2020" + } + ] + }, + "comment":"Map to array with JSON." + }, + { + "monthFieldName":"card_data[1].month", + "dayFieldName":"card_data[1].day", + "yearFieldName":"card_data[1].year", + "fieldValue":"01/30/2020", + "expectedResult":{ + "card_data":[ + null, + { + "month":"01", + "day":"30", + "year":"2020" + } + ] + }, + "comment":"Map to array with JSON adjusting array capacity." + }, + { + "monthFieldName":"card_data[0].month", + "dayFieldName":"card_data[0].day", + "yearFieldName":"card_data[0].year", + "fieldValue":"01/12/2035", + "expectedResult":{ + "card_data":[ + { + "month":"01", + "day":"12", + "year":"2035" + } + ] + }, + "comment":"Map to nested JSON." + } + ] +} \ No newline at end of file diff --git a/Tests/FrameworkTests/Resources/DateTokenizationJSON/VGSDateTokenizationSerialization_DefaultConfig.json b/Tests/FrameworkTests/Resources/DateTokenizationJSON/VGSDateTokenizationSerialization_DefaultConfig.json new file mode 100644 index 00000000..2e95ea84 --- /dev/null +++ b/Tests/FrameworkTests/Resources/DateTokenizationJSON/VGSDateTokenizationSerialization_DefaultConfig.json @@ -0,0 +1,85 @@ +{ + "test_data":[ + { + "monthFieldName":"month", + "dayFieldName":"day", + "yearFieldName":"year", + "fieldValue":"04/26/2016", + "outputFormat":"mmddyyyy", + "expectedResult":{ + "data":[ + { + "format":"UUID", + "value":"04", + "storage":"PERSISTENT" + }, + { + "format":"UUID", + "value":"26", + "storage":"PERSISTENT" + }, + { + "value":"2016", + "storage":"PERSISTENT", + "format":"UUID" + } + ] + }, + "comment":"Serialized date mmddyyyy." + }, + { + "monthFieldName":"month", + "dayFieldName":"day", + "yearFieldName":"year", + "fieldValue":"04/26/2016", + "outputFormat":"ddmmyyyy", + "expectedResult":{ + "data":[ + { + "format":"UUID", + "value":"04", + "storage":"PERSISTENT" + }, + { + "format":"UUID", + "value":"26", + "storage":"PERSISTENT" + }, + { + "value":"2016", + "storage":"PERSISTENT", + "format":"UUID" + } + ] + }, + "comment":"Serialized date ddmmyyyy." + }, + { + "monthFieldName":"month", + "dayFieldName":"day", + "yearFieldName":"year", + "fieldValue":"04/26/2016", + "outputFormat":"yyyymmdd", + "expectedResult":{ + "data":[ + { + "format":"UUID", + "value":"04", + "storage":"PERSISTENT" + }, + { + "format":"UUID", + "value":"26", + "storage":"PERSISTENT" + }, + { + "value":"2016", + "storage":"PERSISTENT", + "format":"UUID" + } + ] + }, + "comment":"Serialized date yyyymmdd." + } + ] +} diff --git a/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/DateTextFieldTest.swift b/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/DateTextFieldTest.swift new file mode 100644 index 00000000..8b48fb37 --- /dev/null +++ b/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/DateTextFieldTest.swift @@ -0,0 +1,225 @@ +// +// DateTextField.swift +// VGSCollectSDK +// + +import XCTest +@testable import VGSCollectSDK + +class DateTextFieldTest: VGSCollectBaseTestCase { + + // MARK: - Properties + private var collector: VGSCollect! + private var textField: VGSDateTextField! + + // MARK: - Overrides + override func setUp() { + super.setUp() + + collector = VGSCollect(id: "any") + textField = VGSDateTextField() + + let config = VGSConfiguration(collector: collector, fieldName: "textField") + config.formatPattern = VGSDateFormat.default.formatPattern + textField.configuration = config + } + + override func tearDown() { + collector = nil + textField = nil + } + + // MARK: - Tests + /// Test when different month formats are selected + func testMonthFormat() { + /// Define the first month `January` for each month format + let firstLongAr = "يناير" + var validLongMonth = "January" + var validShortMonth = "Jan" + + /// For Arabic long and short month is the same. + if Locale.current.languageCode == "ar" { + validLongMonth = firstLongAr + validShortMonth = firstLongAr + } + + /// Asserts + textField.monthPickerFormat = .longSymbols + XCTAssertEqual(textField.monthsDataSource.first, validLongMonth) + textField.monthPickerFormat = .shortSymbols + XCTAssertEqual(textField.monthsDataSource.first, validShortMonth) + textField.monthPickerFormat = .numbers + XCTAssertEqual(textField.monthsDataSource.last, "12") + } + + /// Test when a valid date is selected using the default start and end date range + func testSelectDateWithDefaultDateRange() { + /// Select month + let monthSelected = 0 + textField.picker.selectRow(monthSelected, inComponent: 0, animated: false) + textField.pickerView(textField.picker, didSelectRow: monthSelected, inComponent: 0) + + /// Select day + let daySelected = 8 + textField.picker.selectRow(daySelected, inComponent: 1, animated: false) + textField.pickerView(textField.picker, didSelectRow: daySelected, inComponent: 1) + + /// Select year + let yearSelected = 61 + textField.picker.selectRow(yearSelected, inComponent: 2, animated: false) + textField.pickerView(textField.picker, didSelectRow: yearSelected, inComponent: 2) + + /// Get selected date + let currentValue = textField.textField.secureText + let monthComponent = currentValue?.components(separatedBy: "-").first ?? "0" + let dayComponent = currentValue?.components(separatedBy: "-")[1] ?? "0" + let yearComponent = currentValue?.components(separatedBy: "-").last ?? "0" + + /// Asserts: Validate the selected date is correct + XCTAssertEqual(Int(monthComponent), monthSelected + 1) + XCTAssertEqual(Int(dayComponent), daySelected + 1) + XCTAssertEqual(Int(yearComponent), (Calendar.currentYear - VGSDateConfiguration.validYearsCount) + yearSelected) + } + + /// Test when an invalid date is selected using the default start and end date range + func testSelectWrongDateWithDefaultDateRange() { + /// Select month + let monthSelected = 0 + textField.picker.selectRow(monthSelected, inComponent: 0, animated: false) + textField.pickerView(textField.picker, didSelectRow: monthSelected, inComponent: 0) + + /// Select day + let daySelected = 8 + textField.picker.selectRow(daySelected, inComponent: 1, animated: false) + textField.pickerView(textField.picker, didSelectRow: daySelected, inComponent: 1) + + /// Select invalid year, outside valid default range + let yearSelected = VGSDateConfiguration.validYearsCount * 3 + textField.picker.selectRow(yearSelected, inComponent: 2, animated: false) + textField.pickerView(textField.picker, didSelectRow: yearSelected, inComponent: 2) + + /// Get selected date + let currentValue = textField.textField.secureText + let monthComponent = currentValue?.components(separatedBy: "-").first ?? "0" + let dayComponent = currentValue?.components(separatedBy: "-")[1] ?? "0" + let yearComponent = currentValue?.components(separatedBy: "-").last ?? "0" + + /// Asserts: Selecting invalid day, month or year should be ignored + XCTAssertEqual(Int(monthComponent), monthSelected + 1) + XCTAssertEqual(Int(dayComponent), daySelected + 1) + XCTAssertEqual(Int(yearComponent), Calendar.currentYear - VGSDateConfiguration.validYearsCount) + } + + /// Test when a valid date is selected with a configuration that has custom start and end dates + func testSelectDateWithCustomDateRange() { + /// Define custom dates + let startDate = VGSDate(day: 1, month: 1, year: 2000)! + let endDate = VGSDate(day: 1, month: 1, year: 2030)! + + /// Setup custom configuration + let customConfig = VGSDateConfiguration( + collector: collector, + fieldName: "textField", + datePickerStartDate: startDate, + datePickerEndDate: endDate + ) + textField.configuration = customConfig + + /// Select month + let monthSelected = 6 + textField.picker.selectRow(monthSelected, inComponent: 0, animated: false) + textField.pickerView(textField.picker, didSelectRow: monthSelected, inComponent: 0) + + /// Select day + let daySelected = 15 + textField.picker.selectRow(daySelected, inComponent: 1, animated: false) + textField.pickerView(textField.picker, didSelectRow: daySelected, inComponent: 1) + + /// Select year, exactly the middle between start and end dates + let yearSelected = (endDate.year - startDate.year) / 2 + textField.picker.selectRow(yearSelected, inComponent: 2, animated: false) + textField.pickerView(textField.picker, didSelectRow: yearSelected, inComponent: 2) + + /// Get current date + let currentValue = textField.textField.secureText + let monthComponent = currentValue?.components(separatedBy: "-").first ?? "0" + let dayComponent = currentValue?.components(separatedBy: "-")[1] ?? "0" + let yearComponent = currentValue?.components(separatedBy: "-").last ?? "0" + + /// Asserts: The selected year should be the same selected in the textField + XCTAssertEqual(Int(monthComponent), monthSelected + 1) + XCTAssertEqual(Int(dayComponent), daySelected + 1) + XCTAssertEqual(Int(yearComponent), startDate.year + yearSelected) + XCTAssertEqual(Int(yearComponent), endDate.year - yearSelected) + } + + /// Test when an invalid date is selected with a configuration that has custom start and end dates + func testSelectWrongDateWithCustomDateRange() { + /// Define custom dates + let startDate = VGSDate(day: 1, month: 1, year: 2000)! + let endDate = VGSDate(day: 1, month: 1, year: 2030)! + + /// Setup custom configuration + let customConfig = VGSDateConfiguration( + collector: collector, + fieldName: "textField", + datePickerStartDate: startDate, + datePickerEndDate: endDate + ) + textField.configuration = customConfig + + /// Select month + let monthSelected = 6 + textField.picker.selectRow(monthSelected, inComponent: 0, animated: false) + textField.pickerView(textField.picker, didSelectRow: monthSelected, inComponent: 0) + + /// Select invalid day, outside the custom range + let daySelected = 50 + textField.picker.selectRow(daySelected, inComponent: 1, animated: false) + textField.pickerView(textField.picker, didSelectRow: daySelected, inComponent: 1) + + /// Select year + let yearSelected = 5 + textField.picker.selectRow(yearSelected, inComponent: 2, animated: false) + textField.pickerView(textField.picker, didSelectRow: yearSelected, inComponent: 2) + + /// Get current date + let currentValue = textField.textField.secureText + let monthComponent = currentValue?.components(separatedBy: "-").first ?? "0" + let dayComponent = currentValue?.components(separatedBy: "-")[1] ?? "0" + let yearComponent = currentValue?.components(separatedBy: "-").last ?? "0" + + /// Asserts: Selecting invalid day, month or year should be ignored + XCTAssertEqual(Int(monthComponent), monthSelected + 1) + XCTAssertEqual(Int(dayComponent), 1) + XCTAssertEqual(Int(yearComponent), startDate.year + yearSelected) + } + + /// Test when the keyboard configuration is selected in the configuration + func testDateKeyboardConfiguration() { + /// Setup custom configuration with keyboard + let customConfig = VGSDateConfiguration(collector: collector, fieldName: "textField") + customConfig.inputSource = .keyboard + customConfig.keyboardType = .namePhonePad + customConfig.returnKeyType = .go + customConfig.keyboardAppearance = .dark + textField.configuration = customConfig + + /// Asserts + XCTAssertTrue(textField.textField.keyboardType == customConfig.keyboardType, "Wrong keyboardType!") + XCTAssertTrue(textField.textField.returnKeyType == customConfig.returnKeyType, "Wrong returnKeyType!") + XCTAssertTrue(textField.textField.keyboardAppearance == customConfig.keyboardAppearance, "Wrong keyboardAppearance!") + } + + /// Test when the picker configuration is selected in the configuration + func testDateDatePickerConfiguration() { + /// Setup custom configuration with date picker + let customConfig = VGSDateConfiguration(collector: collector, fieldName: "textField") + customConfig.inputSource = .datePicker + textField.configuration = customConfig + + /// Asserts + XCTAssertTrue(textField.textField.inputView != nil, "Date picker not set!") + XCTAssertTrue(textField.textField.inputView is UIPickerView, "Wrong date picker view!") + } +} diff --git a/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/VGSDateFormatTests.swift b/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/VGSDateFormatTests.swift new file mode 100644 index 00000000..6d7faec8 --- /dev/null +++ b/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/VGSDateFormatTests.swift @@ -0,0 +1,178 @@ +// +// VGSDateFormatTests.swift +// FrameworkTests +// + +import XCTest +@testable import VGSCollectSDK + +class VGSDateFormatTests: VGSCollectBaseTestCase { + + // MARK: - Tests + /// Test date format initialization + func testDateFormatInitialization() { + /// Date format mmddyyyy + let mmddyyyyFormat = VGSDateFormat(name: "mmddyyyy") + XCTAssertEqual(mmddyyyyFormat, .mmddyyyy) + + /// Date format ddmmyyyy + let ddmmyyyyFormat = VGSDateFormat(name: "ddmmyyyy") + XCTAssertEqual(ddmmyyyyFormat, .ddmmyyyy) + + /// Date format yyyymmdd + let yyyymmddFormat = VGSDateFormat(name: "yyyymmdd") + XCTAssertEqual(yyyymmddFormat, .yyyymmdd) + + /// Invalid format + let invalidFormat = VGSDateFormat(name: "any") + XCTAssertNil(invalidFormat) + } + + /// Test the amount of expected characters for each part of the date + func testAmountOfCharacters() { + /// Expected values + let expectedDays = 2 + let expectedMonths = 2 + let expectedYears = 4 + let expectedDivider = 2 + + /// Days + XCTAssertEqual(VGSDateFormat.mmddyyyy.daysCharacters, expectedDays) + XCTAssertEqual(VGSDateFormat.ddmmyyyy.daysCharacters, expectedDays) + XCTAssertEqual(VGSDateFormat.yyyymmdd.daysCharacters, expectedDays) + + /// Months + XCTAssertEqual(VGSDateFormat.mmddyyyy.monthCharacters, expectedMonths) + XCTAssertEqual(VGSDateFormat.ddmmyyyy.monthCharacters, expectedMonths) + XCTAssertEqual(VGSDateFormat.yyyymmdd.monthCharacters, expectedMonths) + + /// Years + XCTAssertEqual(VGSDateFormat.mmddyyyy.yearCharacters, expectedYears) + XCTAssertEqual(VGSDateFormat.ddmmyyyy.yearCharacters, expectedYears) + XCTAssertEqual(VGSDateFormat.yyyymmdd.yearCharacters, expectedYears) + + /// Divider + XCTAssertEqual(VGSDateFormat.mmddyyyy.dividerCharacters, expectedDivider) + XCTAssertEqual(VGSDateFormat.ddmmyyyy.dividerCharacters, expectedDivider) + XCTAssertEqual(VGSDateFormat.yyyymmdd.dividerCharacters, expectedDivider) + } + + /// Test when the map picker data is formatted + func testMapDatePickerDataForFieldFormat() { + /// Expected date + let date = VGSDate(day: 2, month: 5, year: 2016)! + + /// mmddyyyy + XCTAssertEqual(VGSDateFormat.mmddyyyy.mapDatePickerDataForFieldFormat(date), "05022016") + + /// ddmmyyyy + XCTAssertEqual(VGSDateFormat.ddmmyyyy.mapDatePickerDataForFieldFormat(date), "02052016") + + /// yyyymmdd + XCTAssertEqual(VGSDateFormat.yyyymmdd.mapDatePickerDataForFieldFormat(date), "20160502") + } + + /// Test when the format date is called + func testFormatDate() { + /// Expected date + let date = VGSDate(day: 2, month: 5, year: 2016)! + + /// Divider A + var divider = "_" + XCTAssertEqual(VGSDateFormat.mmddyyyy.formatDate(date, divider: divider), "05\(divider)02\(divider)2016") + XCTAssertEqual(VGSDateFormat.ddmmyyyy.formatDate(date, divider: divider), "02\(divider)05\(divider)2016") + XCTAssertEqual(VGSDateFormat.yyyymmdd.formatDate(date, divider: divider), "2016\(divider)05\(divider)02") + + /// Divider B + divider = "+_+" + XCTAssertEqual(VGSDateFormat.mmddyyyy.formatDate(date, divider: divider), "05\(divider)02\(divider)2016") + XCTAssertEqual(VGSDateFormat.ddmmyyyy.formatDate(date, divider: divider), "02\(divider)05\(divider)2016") + XCTAssertEqual(VGSDateFormat.yyyymmdd.formatDate(date, divider: divider), "2016\(divider)05\(divider)02") + + /// Divider C + divider = "/" + XCTAssertEqual(VGSDateFormat.mmddyyyy.formatDate(date, divider: divider), "05\(divider)02\(divider)2016") + XCTAssertEqual(VGSDateFormat.ddmmyyyy.formatDate(date, divider: divider), "02\(divider)05\(divider)2016") + XCTAssertEqual(VGSDateFormat.yyyymmdd.formatDate(date, divider: divider), "2016\(divider)05\(divider)02") + + /// Divider C + divider = "..." + XCTAssertEqual(VGSDateFormat.mmddyyyy.formatDate(date, divider: divider), "05\(divider)02\(divider)2016") + XCTAssertEqual(VGSDateFormat.ddmmyyyy.formatDate(date, divider: divider), "02\(divider)05\(divider)2016") + XCTAssertEqual(VGSDateFormat.yyyymmdd.formatDate(date, divider: divider), "2016\(divider)05\(divider)02") + } + + /// Test when a date is created from an input string + func testDateFromInput() { + /// Expected date + let date = VGSDate(day: 2, month: 5, year: 2016)! + + /// mmddyyyy + XCTAssertEqual(VGSDateFormat.mmddyyyy.dateFromInput("05022016"), date) + + /// ddmmyyyy + XCTAssertEqual(VGSDateFormat.ddmmyyyy.dateFromInput("02052016"), date) + + /// yyyymmdd + XCTAssertEqual(VGSDateFormat.yyyymmdd.dateFromInput("20160502"), date) + + /// Invalid input + XCTAssertNil(VGSDateFormat.mmddyyyy.dateFromInput("any")) + } + + /// Test the display format + func testDisplayFormat() { + /// mmddyyyy + XCTAssertEqual(VGSDateFormat.mmddyyyy.displayFormat, "mm-dd-yyyy") + + /// ddmmyyyy + XCTAssertEqual(VGSDateFormat.ddmmyyyy.displayFormat, "dd-mm-yyyy") + + /// yyyymmdd + XCTAssertEqual(VGSDateFormat.yyyymmdd.displayFormat, "yyyy-mm-dd") + } + + /// Test format pattern + func testFormatPattern() { + /// mmddyyyy + XCTAssertEqual(VGSDateFormat.mmddyyyy.formatPattern, "##-##-####") + + /// ddmmyyyy + XCTAssertEqual(VGSDateFormat.ddmmyyyy.formatPattern, "##-##-####") + + /// yyyymmdd + XCTAssertEqual(VGSDateFormat.yyyymmdd.formatPattern, "####-##-##") + } + + /// Test to get the divider in an input date string + func testDividerInInput() { + /// Divider A + var divider = "_" + XCTAssertEqual(VGSDateFormat.dividerInInput("05\(divider)02\(divider)2016"), divider) + XCTAssertEqual(VGSDateFormat.dividerInInput("02\(divider)05\(divider)2016"), divider) + XCTAssertEqual(VGSDateFormat.dividerInInput("2016\(divider)05\(divider)02"), divider) + + /// Divider B + divider = "+_+" + XCTAssertEqual(VGSDateFormat.dividerInInput("05\(divider)02\(divider)2016"), divider) + XCTAssertEqual(VGSDateFormat.dividerInInput("02\(divider)05\(divider)2016"), divider) + XCTAssertEqual(VGSDateFormat.dividerInInput("2016\(divider)05\(divider)02"), divider) + + /// Divider C + divider = "/" + XCTAssertEqual(VGSDateFormat.dividerInInput("05\(divider)02\(divider)2016"), divider) + XCTAssertEqual(VGSDateFormat.dividerInInput("02\(divider)05\(divider)2016"), divider) + XCTAssertEqual(VGSDateFormat.dividerInInput("2016\(divider)05\(divider)02"), divider) + + /// Divider C + divider = "..." + XCTAssertEqual(VGSDateFormat.dividerInInput("05\(divider)02\(divider)2016"), divider) + XCTAssertEqual(VGSDateFormat.dividerInInput("02\(divider)05\(divider)2016"), divider) + XCTAssertEqual(VGSDateFormat.dividerInInput("2016\(divider)05\(divider)02"), divider) + + /// Invalid input + XCTAssertEqual(VGSDateFormat.dividerInInput("05|02-2016"), "") + XCTAssertEqual(VGSDateFormat.dividerInInput("05-02*2016"), "") + XCTAssertEqual(VGSDateFormat.dividerInInput("05-..-022016"), "") + } +} diff --git a/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/ValidationRuleDateTests.swift b/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/ValidationRuleDateTests.swift new file mode 100644 index 00000000..736adccd --- /dev/null +++ b/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/ValidationRuleDateTests.swift @@ -0,0 +1,204 @@ +// +// ValidationRuleDateTests.swift +// FrameworkTests +// + +import XCTest +@testable import VGSCollectSDK + +class ValidationRuleDateTests: VGSCollectBaseTestCase { + + // MARK: - Constants + /// Default error + private let error = "date_error" + + // MARK: - Properties + private var collector: VGSCollect! + private var textField: VGSTextField! + private var config: VGSConfiguration! + + // MARK: - Overrides + override func setUp() { + super.setUp() + + collector = VGSCollect(id: "any") + textField = VGSTextField() + config = VGSConfiguration(collector: collector, fieldName: "test_field") + config.type = .date + } + + override func tearDown() { + collector = nil + textField = nil + config = nil + } + + // MARK: - Tests + /// Test date validation rule with default configuration + func testDateRule() { + /// Test validation success + textField.configuration = config + textField.textField.secureText = "10102004" + XCTAssertTrue(textField.state.isValid) + XCTAssertEqual(textField.state.validationErrors.count, 0) + + /// Test invalid format + textField.textField.secureText = "102024" + XCTAssertFalse(textField.state.isValid) + XCTAssertEqual(textField.state.validationErrors.count, 1) + + /// Test invalid date, in this case month is `50` + textField.textField.secureText = "50012024" + XCTAssertFalse(textField.state.isValid) + XCTAssertEqual(textField.state.validationErrors.count, 1) + } + + /// Test each of the date formats + func testRuleDateFormats() { + /// Use `ddmmyyy` format + config.validationRules = VGSValidationRuleSet(rules: [ + VGSValidationRuleDateRange( + dateFormat: .ddmmyyyy, + error: error + ) + ]) + + /// Test validation success + textField.configuration = config + textField.textField.secureText = "20111984" + XCTAssertTrue(textField.state.isValid) + XCTAssertEqual(textField.state.validationErrors.count, 0) + + /// Test validation fails + textField.configuration = config + textField.textField.secureText = "19841120" + XCTAssertFalse(textField.state.isValid) + XCTAssertEqual(textField.state.validationErrors.count, 1) + + /// Use `mmddyyyy` format + config.validationRules = VGSValidationRuleSet(rules: [ + VGSValidationRuleDateRange( + dateFormat: .mmddyyyy, + error: error + ) + ]) + + // Test validation success + textField.configuration = config + textField.textField.secureText = "11201984" + XCTAssertTrue(textField.state.isValid) + XCTAssertEqual(textField.state.validationErrors.count, 0) + + /// Test validation fails + textField.configuration = config + textField.textField.secureText = "19842011" + XCTAssertFalse(textField.state.isValid) + XCTAssertEqual(textField.state.validationErrors.count, 1) + + /// Use `yyyymmdd` format + config.validationRules = VGSValidationRuleSet(rules: [ + VGSValidationRuleDateRange( + dateFormat: .yyyymmdd, + error: error + ) + ]) + + // Test validation success + textField.configuration = config + textField.textField.secureText = "19841120" + XCTAssertTrue(textField.state.isValid) + XCTAssertEqual(textField.state.validationErrors.count, 0) + + /// Test validation fails + textField.configuration = config + textField.textField.secureText = "20111984" + XCTAssertFalse(textField.state.isValid) + XCTAssertEqual(textField.state.validationErrors.count, 1) + } + + /// Test when start date and end date are set + func testRuleWithStartAndEndDate() { + /// Setup start and end dates + let startDate = VGSDate(day: 10, month: 11, year: 2015) + let endDate = VGSDate(day: 08, month: 12, year: 2030) + + /// Use default format + config.validationRules = VGSValidationRuleSet(rules: [ + VGSValidationRuleDateRange( + error: error, + start: startDate, + end: endDate + ) + ]) + + /// Test validation success + textField.configuration = config + textField.textField.secureText = "10122020" + XCTAssertTrue(textField.state.isValid) + XCTAssertEqual(textField.state.validationErrors.count, 0) + + /// Test validation fails, date before start date + textField.configuration = config + textField.textField.secureText = "1012215" + XCTAssertFalse(textField.state.isValid) + XCTAssertEqual(textField.state.validationErrors.count, 1) + + /// Test validation fails, date after end date + textField.configuration = config + textField.textField.secureText = "12102030" + XCTAssertFalse(textField.state.isValid) + XCTAssertEqual(textField.state.validationErrors.count, 1) + } + + /// Test when only start date is set + func testRuleWithStartDate() { + /// Setup start date + let startDate = VGSDate(day: 10, month: 11, year: 2015) + + /// Use default format + config.validationRules = VGSValidationRuleSet(rules: [ + VGSValidationRuleDateRange( + error: error, + start: startDate + ) + ]) + + /// Test validation success + textField.configuration = config + textField.textField.secureText = "10122020" + XCTAssertTrue(textField.state.isValid) + XCTAssertEqual(textField.state.validationErrors.count, 0) + + /// Test validation fails, date before start date + textField.configuration = config + textField.textField.secureText = "1012215" + XCTAssertFalse(textField.state.isValid) + XCTAssertEqual(textField.state.validationErrors.count, 1) + } + + /// Test when only end date is set + func testRuleWithEndDate() { + /// Setup end date + let endDate = VGSDate(day: 08, month: 12, year: 2030) + + /// Use default format + config.validationRules = VGSValidationRuleSet(rules: [ + VGSValidationRuleDateRange( + error: error, + end: endDate + ) + ]) + + /// Test validation success + textField.configuration = config + textField.textField.secureText = "10122020" + XCTAssertTrue(textField.state.isValid) + XCTAssertEqual(textField.state.validationErrors.count, 0) + + /// Test validation fails, date after end date + textField.configuration = config + textField.textField.secureText = "12102030" + XCTAssertFalse(textField.state.isValid) + XCTAssertEqual(textField.state.validationErrors.count, 1) + } +} diff --git a/Tests/FrameworkTests/SerializersTest/SerializersDataProvider.swift b/Tests/FrameworkTests/SerializersTest/SerializersDataProvider.swift new file mode 100644 index 00000000..1baa750b --- /dev/null +++ b/Tests/FrameworkTests/SerializersTest/SerializersDataProvider.swift @@ -0,0 +1,47 @@ +// +// SerializersDataProvider.swift +// FrameworkTests +// + +import XCTest +@testable import VGSCollectSDK + +/// Define the methods required to parse test JSON data +protocol TestJSONDataProtocol { + init?(json: JsonData) +} + +/// Class with the methods required to read and parse JSON files for testing +final class SerializersDataProvider { + + /// Method that reads and parse `JSON` file with data for testing. It define an abstract + /// parameter that must implement the `TestJSONDataProtocol` + /// + /// - Parameters: + /// - fileName: `String` with the name of the `JSON` file to read the data from. + /// - rootName: `String` with the name of the root node of the `JSON` file, by defaul it is defined as `test_data` + static func provideTestData(for fileName: String, rootNodeName: String = "test_data") -> [T] { + /// Read json data from file + guard let rootTestJSON = JsonData(jsonFileName: fileName) else { + XCTFail("Cannot build data for file \(fileName)") + return [] + } + + /// Get root node + guard let testDataJSONArray = rootTestJSON[rootNodeName] as? [JsonData] else { + XCTFail("\(rootNodeName) JSON array not found in \(fileName)") + return [] + } + + /// Parse test data + var testData = [T]() + for json in testDataJSONArray { + if let testItem = T(json: json) { + testData.append(testItem) + } else { + XCTFail("Cannot build test data for JSON: \(json)") + } + } + return testData + } +} diff --git a/Tests/FrameworkTests/SerializersTest/VGSDateSeparateSerializerTests.swift b/Tests/FrameworkTests/SerializersTest/VGSDateSeparateSerializerTests.swift new file mode 100644 index 00000000..663a0e4b --- /dev/null +++ b/Tests/FrameworkTests/SerializersTest/VGSDateSeparateSerializerTests.swift @@ -0,0 +1,256 @@ +// +// VGSDateSeparateSerializerTests.swift +// FrameworkTests +// + +import XCTest +@testable import VGSCollectSDK + +class VGSDateSeparateSerializerTests: VGSCollectBaseTestCase { + + // MARK: - Properties + private var collector: VGSCollect! + private var textField: VGSDateTextField! + + // MARK: - Inner objects + /// Define the file names with JSON data for testing + private enum TestFlow { + case defaultConfig + case customConfig + case customExpDateOutputConfig + case mapWithArrayOverwrite + case mapWithArrayMerge + + /// Name of the JSON file + var jsonFileName: String { + return "VGSDateSerialization_" + jsonFileNameSuffix + } + + /// JSON file name + private var jsonFileNameSuffix: String { + switch self { + case .defaultConfig: + return "DefaultConfig" + case .customConfig: + return "CustomConfig" + case .customExpDateOutputConfig: + return "CustomExpDateOutputConfig" + case .mapWithArrayOverwrite: + return "MapWithArrayOverwrite" + case .mapWithArrayMerge: + return "MapWithArrayMerge" + } + } + } + + /// Store the JSON data for testing + private struct TestJSONData: TestJSONDataProtocol { + + // MARK: - Properties + let fieldValue: String + let monthFieldName: String + let dayFieldName: String + let yearFieldName: String + let submitJSON: JsonData + + /// Initializer + init?(json: JsonData) { + guard let submitJSON = json["expectedResult"] as? JsonData else { + XCTFail("Cannot parse test data.") + return nil + } + self.fieldValue = json["fieldValue"] as? String ?? "" + self.monthFieldName = json["monthFieldName"] as? String ?? "" + self.dayFieldName = json["dayFieldName"] as? String ?? "" + self.yearFieldName = json["yearFieldName"] as? String ?? "" + self.submitJSON = submitJSON + } + } + + // MARK: - Overrides + override func setUp() { + super.setUp() + + collector = VGSCollect(id: "any") + textField = VGSDateTextField() + } + + override func tearDown() { + collector = nil + textField = nil + } + + // MARK: - Tests + /// Test default configuration + func testSplitDateSerializerWithDefaultConfig() { + /// Get JSON test data + let fileName = TestFlow.defaultConfig.jsonFileName + let testData: [TestJSONData] = SerializersDataProvider.provideTestData(for: fileName) + + /// Prepare configuration + let config = VGSDateConfiguration(collector: collector, fieldName: "date") + config.formatPattern = VGSDateFormat.default.formatPattern + + /// Run test for each case from JSON + for test in testData { + /// Prepare serializer + config.serializers = [ + VGSDateSeparateSerializer( + dayFieldName: test.dayFieldName, + monthFieldName: test.monthFieldName, + yearFieldName: test.yearFieldName + ) + ] + /// Update configuration + textField.configuration = config + /// Setup test value + textField.setText(test.fieldValue) + /// Get JSON from collector using serializer + let submitJSON = collector.mapFieldsToBodyJSON(with: .nestedJSON, extraData: nil) + /// Assert: Test JSON content should be equals to the JSON from the collector + XCTAssertTrue(NSDictionary(dictionary: submitJSON).isEqual(to: test.submitJSON)) + } + } + + /// Test custom configuration + func testSplitDateSerializerWithCustomConfig() { + /// Get JSON test data + let fileName = TestFlow.customConfig.jsonFileName + let testData: [TestJSONData] = SerializersDataProvider.provideTestData(for: fileName) + + /// Prepare configuration + let config = VGSDateConfiguration(collector: collector, fieldName: "card.date") + config.formatPattern = VGSDateFormat.default.formatPattern + config.inputDateFormat = .yyyymmdd + config.outputDateFormat = .ddmmyyyy + config.divider = "-/-" + + /// Run test for each case from JSON + for test in testData { + /// Prepare serializer + config.serializers = [ + VGSDateSeparateSerializer( + dayFieldName: test.dayFieldName, + monthFieldName: test.monthFieldName, + yearFieldName: test.yearFieldName + ) + ] + /// Update configuration + textField.configuration = config + /// Setup test value + textField.setText(test.fieldValue) + /// Get JSON from collector using serializer + let submitJSON = collector.mapFieldsToBodyJSON(with: .nestedJSON, extraData: nil) + /// Assert: Test JSON content should be equals to the JSON from the collector + XCTAssertTrue(NSDictionary(dictionary: submitJSON).isEqual(to: test.submitJSON)) + } + } + + /// Test custom output format. + func testSplitCustomDateOutputSerializerWithCustomConfig() { + /// Get JSON test data + let fileName = TestFlow.customExpDateOutputConfig.jsonFileName + let testData: [TestJSONData] = SerializersDataProvider.provideTestData(for: fileName) + + /// Prepare configuration + let config = VGSDateConfiguration(collector: collector, fieldName: "card.date") + config.formatPattern = VGSDateFormat.default.formatPattern + config.inputDateFormat = .yyyymmdd + config.outputDateFormat = .ddmmyyyy + config.divider = "-/-" + + /// Run test for each case from JSON + for test in testData { + /// Prepare serializer + config.serializers = [ + VGSDateSeparateSerializer( + dayFieldName: test.dayFieldName, + monthFieldName: test.monthFieldName, + yearFieldName: test.yearFieldName + ) + ] + /// Update configuration + textField.configuration = config + /// Setup test value + textField.setText(test.fieldValue) + /// Get JSON from collector using serializer + let submitJSON = collector.mapFieldsToBodyJSON(with: .nestedJSON, extraData: nil) + /// Assert: Test JSON content should be equals to the JSON from the collector + XCTAssertTrue(NSDictionary(dictionary: submitJSON).isEqual(to: test.submitJSON)) + } + } + + /// Test map with array merge. + func testSplitExpDateSerializersMapWithArray() { + /// Get JSON test data + let fileName = TestFlow.mapWithArrayMerge.jsonFileName + let testData: [TestJSONData] = SerializersDataProvider.provideTestData(for: fileName) + + /// Prepare configuration + let config = VGSDateConfiguration(collector: collector, fieldName: "date") + config.formatPattern = VGSDateFormat.default.formatPattern + config.inputDateFormat = .mmddyyyy + config.outputDateFormat = .mmddyyyy + config.divider = "/" + + /// Setup extra data + let extraData = ["card_data": [["user_id": "123"]]] + + /// Run test for each case from JSON + for test in testData { + /// Prepare serializer + config.serializers = [ + VGSDateSeparateSerializer( + dayFieldName: test.dayFieldName, + monthFieldName: test.monthFieldName, + yearFieldName: test.yearFieldName + ) + ] + /// Update configuration + textField.configuration = config + /// Setup test value + textField.setText(test.fieldValue) + /// Get JSON from collector using serializer + let submitJSON = collector.mapFieldsToBodyJSON(with: .nestedJSONWithArrayMerge, extraData: extraData) + /// Assert: Test JSON content should be equals to the JSON from the collector + XCTAssertTrue(NSDictionary(dictionary: submitJSON).isEqual(to: test.submitJSON)) + } + } + + /// Test map with array overwrite. + func testSplitExpDateSerializersMapWithArrayOverwrite() { + /// Get JSON test data + let fileName = TestFlow.mapWithArrayOverwrite.jsonFileName + let testData: [TestJSONData] = SerializersDataProvider.provideTestData(for: fileName) + + /// Prepare configuration + let config = VGSDateConfiguration(collector: collector, fieldName: "date") + config.formatPattern = VGSDateFormat.default.formatPattern + config.inputDateFormat = .mmddyyyy + config.outputDateFormat = .mmddyyyy + config.divider = "/" + + /// Setup extra data + let extraData = ["card_data": [["month": "3", "year": "2033"]]] + + /// Run test for each case from JSON + for test in testData { + /// Prepare serializer + config.serializers = [ + VGSDateSeparateSerializer( + dayFieldName: test.dayFieldName, + monthFieldName: test.monthFieldName, + yearFieldName: test.yearFieldName + ) + ] + /// Update configuration + textField.configuration = config + /// Setup test value + textField.setText(test.fieldValue) + /// Get JSON from collector using serializer + let submitJSON = collector.mapFieldsToBodyJSON(with: .nestedJSONWithArrayOverwrite, extraData: extraData) + /// Assert: Test JSON content should be equals to the JSON from the collector + XCTAssertTrue(NSDictionary(dictionary: submitJSON).isEqual(to: test.submitJSON)) + } + } +} diff --git a/Tests/FrameworkTests/SerializersTest/VGSDateTokenizationSerializerTests.swift b/Tests/FrameworkTests/SerializersTest/VGSDateTokenizationSerializerTests.swift new file mode 100644 index 00000000..75ffb216 --- /dev/null +++ b/Tests/FrameworkTests/SerializersTest/VGSDateTokenizationSerializerTests.swift @@ -0,0 +1,135 @@ +// +// VGSDateTokenizationSerializerTests.swift +// FrameworkTests +// + +import XCTest +@testable import VGSCollectSDK + +class VGSDateTokenizationSerializerTests: VGSCollectBaseTestCase { + + // MARK: - Properties + private var collector: VGSCollect! + private var textField: VGSDateTextField! + + // MARK: - Inner objects + /// Define the file names with JSON data for testing + private enum TestFlow { + case defaultConfig + + /// Name of the JSON file + var jsonFileName: String { + return "VGSDateTokenizationSerialization_" + jsonFileNameSuffix + } + + /// JSON file name + private var jsonFileNameSuffix: String { + switch self { + case .defaultConfig: + return "DefaultConfig" + } + } + } + + /// Store the JSON data for testing + private struct TestJSONData: TestJSONDataProtocol { + + // MARK: - Properties + let fieldValue: String + let monthFieldName: String + let dayFieldName: String + let yearFieldName: String + let submitJSON: JsonData + let outputFormat: VGSDateFormat + let comment: String + let tokenizedPayloads: [JsonData] + + /// Initializer + init?(json: JsonData) { + guard let submitJSON = json["expectedResult"] as? JsonData else { + XCTFail("Cannot parse test data.") + return nil + } + guard let formatName = json["outputFormat"] as? String, + let format = VGSDateFormat(name: formatName) else { + XCTFail("Cannot parse output format from test json") + return nil + } + self.fieldValue = json["fieldValue"] as? String ?? "" + self.monthFieldName = json["monthFieldName"] as? String ?? "" + self.dayFieldName = json["dayFieldName"] as? String ?? "" + self.yearFieldName = json["yearFieldName"] as? String ?? "" + self.submitJSON = submitJSON + self.outputFormat = format + self.comment = json["comment"] as? String ?? "" + guard let tokenizedPayloads = submitJSON["data"] as? [JsonData] else { + XCTFail("Invalid payload") + return nil + } + self.tokenizedPayloads = tokenizedPayloads + } + } + + // MARK: - Overrides + override func setUp() { + super.setUp() + + collector = VGSCollect(id: "any") + textField = VGSDateTextField() + } + + override func tearDown() { + collector = nil + textField = nil + } + + // MARK: - Tests + /// Test default configuration + func testSplitDateSerializerWithDefaultConfig() { + /// Get JSON test data + let fileName = TestFlow.defaultConfig.jsonFileName + let testData: [TestJSONData] = SerializersDataProvider.provideTestData(for: fileName) + + /// Prepare configuration + let config = VGSDateTokenizationConfiguration(collector: collector, fieldName: "date") + config.inputDateFormat = VGSDateFormat.default + config.formatPattern = VGSDateFormat.default.formatPattern + + /// Run test for each case from JSON + for test in testData { + /// Prepare serializer + config.serializers = [ + VGSDateSeparateSerializer( + dayFieldName: test.dayFieldName, + monthFieldName: test.monthFieldName, + yearFieldName: test.yearFieldName + ) + ] + config.outputDateFormat = test.outputFormat + /// Update configuration + textField.configuration = config + /// Setup test value + textField.setText(test.fieldValue) + /// Get JSON from collector using serializer + let submitJSON = collector.mapFieldsToTokenizationRequestBodyJSON(collector.textFields) + + /// Get payloads + guard let tokenizedPayloads = submitJSON["data"] as? [JsonData] else { + XCTFail("Cannot find tokenized data array.") + return + } + var matchedPayloads = 0 + /// mapFieldsToTokenizationRequestBodyJSON can produce array of tokenized data in different + /// order. So we need to iterate through payloads and check them one by one to get 3 matches + /// (one is for month, one for day and another one for year). + for payload in tokenizedPayloads { + for expectedPayload in test.tokenizedPayloads where payload == expectedPayload { + matchedPayloads += 1 + } + } + + /// Assert: Should be at least 3 matches of payloads + XCTAssertEqual(matchedPayloads, 3) + } + } +} diff --git a/Tests/FrameworkTests/SerializersTest/VGSExpDateSeparateSerializerTests.swift b/Tests/FrameworkTests/SerializersTest/VGSExpDateSeparateSerializerTests.swift index 0fb484be..554ce30e 100644 --- a/Tests/FrameworkTests/SerializersTest/VGSExpDateSeparateSerializerTests.swift +++ b/Tests/FrameworkTests/SerializersTest/VGSExpDateSeparateSerializerTests.swift @@ -11,175 +11,242 @@ import XCTest @testable import VGSCollectSDK class VGSExpDateSeparateSerializerTests: VGSCollectBaseTestCase { - var collector: VGSCollect! - var textField: VGSExpDateTextField! - - enum TestFlow { - case defaultConfiguration - case customConfiguration - case customExpDateOutputConfiguration - case mapWithArrayOverwrite - case mapWithArrayMerge - - var jsonFileName: String { - return "VGSExpDateSerialization_" + jsonFileNameSuffix - } - - var jsonFileNameSuffix: String { - switch self { - case .defaultConfiguration: - return "DefaultConfig" - case .customConfiguration: - return "CustomConfig" - case .customExpDateOutputConfiguration: - return "CustomExpDateOutputConfig" - case .mapWithArrayOverwrite: - return "MapWithArrayOverwrite" - case .mapWithArrayMerge: - return "MapWithArrayMerge" - } - } - } - - struct TestJSONData { - let fieldValue: String - let monthFieldName: String - let yearFieldName: String - let submitJSON: JsonData - init?(json: JsonData) { - guard let submitJSON = json["expectedResult"] as? JsonData else { - XCTFail("Cannot parse test data.") - return nil - } - self.fieldValue = json["fieldValue"] as? String ?? "" - self.monthFieldName = json["monthFieldName"] as? String ?? "" - self.yearFieldName = json["yearFieldName"] as? String ?? "" - self.submitJSON = submitJSON + // MARK: - Properties + private var collector: VGSCollect! + private var textField: VGSExpDateTextField! + + // MARK: - Inner objects + /// Define the file names with JSON data for testing + private enum TestFlow { + case defaultConfig + case customConfig + case customExpDateOutputConfig + case mapWithArrayOverwrite + case mapWithArrayMerge + + /// Name of the JSON file + var jsonFileName: String { + return "VGSExpDateSerialization_" + jsonFileNameSuffix + } + + /// JSON file name + var jsonFileNameSuffix: String { + switch self { + case .defaultConfig: + return "DefaultConfig" + case .customConfig: + return "CustomConfig" + case .customExpDateOutputConfig: + return "CustomExpDateOutputConfig" + case .mapWithArrayOverwrite: + return "MapWithArrayOverwrite" + case .mapWithArrayMerge: + return "MapWithArrayMerge" + } + } } - } - - // MARK: - Override - - override func setUp() { - super.setUp() - collector = VGSCollect(id: "any") - textField = VGSExpDateTextField() - } - - override func tearDown() { - collector = nil - textField = nil - } - - // MARK: - Tests - - /// Test default configuration. - func testSplitExpDateSerializerWithDefaultConfig() { - let fileName = TestFlow.defaultConfiguration.jsonFileName - let testData = VGSExpDateSerializersDataProvider.provideTestData(for: fileName) - let config = VGSExpDateConfiguration(collector: collector, fieldName: "expDate") - config.formatPattern = "##/##" + /// Store the JSON data for testing + private struct TestJSONData: TestJSONDataProtocol { + + // MARK: - Properties + let fieldValue: String + let monthFieldName: String + let yearFieldName: String + let submitJSON: JsonData + + /// Initializer + init?(json: JsonData) { + guard let submitJSON = json["expectedResult"] as? JsonData else { + XCTFail("Cannot parse test data.") + return nil + } + self.fieldValue = json["fieldValue"] as? String ?? "" + self.monthFieldName = json["monthFieldName"] as? String ?? "" + self.yearFieldName = json["yearFieldName"] as? String ?? "" + self.submitJSON = submitJSON + } + } - for test in testData { - config.serializers = [VGSExpDateSeparateSerializer(monthFieldName: test.monthFieldName, yearFieldName: test.yearFieldName)] - textField.configuration = config - textField.setText(test.fieldValue) - - let submitJSON = collector.mapFieldsToBodyJSON(with: .nestedJSON, extraData: nil) - XCTAssertTrue(submitJSON == test.submitJSON, "Expiration date convert error:\n - Input: \(test.fieldValue)\n - Output: \(test.submitJSON)\n - Result: \(submitJSON)") + // MARK: - Override + override func setUp() { + super.setUp() + + collector = VGSCollect(id: "any") + textField = VGSExpDateTextField() + } + + override func tearDown() { + collector = nil + textField = nil } - } - - /// Test custom exp date configuration. - func testSplitExpDateSerializerWithCustomConfig() { - let fileName = TestFlow.customConfiguration.jsonFileName - let testData = VGSExpDateSerializersDataProvider.provideTestData(for: fileName) - let config = VGSExpDateConfiguration(collector: collector, fieldName: "card.expDate") - config.formatPattern = "##/##" - config.inputDateFormat = .shortYear - config.outputDateFormat = .longYear - config.divider = "-/-" + // MARK: - Tests + /// Test default configuration. + func testSplitExpDateSerializerWithDefaultConfig() { + /// Get JSON test data + let fileName = TestFlow.defaultConfig.jsonFileName + let testData: [TestJSONData] = SerializersDataProvider.provideTestData(for: fileName) + + /// Prepare configuration + let config = VGSExpDateConfiguration(collector: collector, fieldName: "expDate") + config.formatPattern = "##/##" + + /// Run test for each case from JSON + for test in testData { + /// Prepare serializer + config.serializers = [ + VGSExpDateSeparateSerializer( + monthFieldName: test.monthFieldName, + yearFieldName: test.yearFieldName + ) + ] + /// Update configuration + textField.configuration = config + /// Setup test value + textField.setText(test.fieldValue) + /// Get JSON from collector using serializer + let submitJSON = collector.mapFieldsToBodyJSON(with: .nestedJSON, extraData: nil) + /// Assert: Test JSON content should be equals to the JSON from the collector + XCTAssertTrue(submitJSON == test.submitJSON, + "Expiration date convert error:\n - Input: \(test.fieldValue)\n - Output: \(test.submitJSON)\n - Result: \(submitJSON)") + } + } - for test in testData { - config.serializers = [VGSExpDateSeparateSerializer(monthFieldName: test.monthFieldName, yearFieldName: test.yearFieldName)] - textField.configuration = config - textField.setText(test.fieldValue) - - let submitJSON = collector.mapFieldsToBodyJSON(with: .nestedJSON, extraData: nil) - XCTAssertTrue(submitJSON == test.submitJSON, "Expiration date convert error:\n - Input: \(test.fieldValue)\n - Output: \(test.submitJSON)\n - Result: \(submitJSON)") - + /// Test custom exp date configuration. + func testSplitExpDateSerializerWithCustomConfig() { + /// Get JSON test data + let fileName = TestFlow.customConfig.jsonFileName + let testData: [TestJSONData] = SerializersDataProvider.provideTestData(for: fileName) + + /// Prepare configuration + let config = VGSExpDateConfiguration(collector: collector, fieldName: "card.expDate") + config.formatPattern = "##/##" + config.inputDateFormat = .shortYear + config.outputDateFormat = .longYear + config.divider = "-/-" + + /// Run test for each case from JSON + for test in testData { + /// Prepare serializer + config.serializers = [ + VGSExpDateSeparateSerializer( + monthFieldName: test.monthFieldName, + yearFieldName: test.yearFieldName + ) + ] + /// Update configuration + textField.configuration = config + /// Setup test value + textField.setText(test.fieldValue) + /// Get JSON from collector using serializer + let submitJSON = collector.mapFieldsToBodyJSON(with: .nestedJSON, extraData: nil) + /// Assert: Test JSON content should be equals to the JSON from the collector + XCTAssertTrue(submitJSON == test.submitJSON, + "Expiration date convert error:\n - Input: \(test.fieldValue)\n - Output: \(test.submitJSON)\n - Result: \(submitJSON)") + } } - } - - /// Test custom exp date output format. - func testSplitCustomExpDateOutputSerializerWithCustomConfig() { - let fileName = TestFlow.customExpDateOutputConfiguration.jsonFileName - let testData = VGSExpDateSerializersDataProvider.provideTestData(for: fileName) - let config = VGSExpDateConfiguration(collector: collector, fieldName: "card.expDate") - config.formatPattern = "####/##" - config.inputDateFormat = .longYearThenMonth - config.outputDateFormat = .shortYearThenMonth - config.divider = "-/-" + /// Test custom exp date output format. + func testSplitCustomExpDateOutputSerializerWithCustomConfig() { + /// Get JSON test data + let fileName = TestFlow.customExpDateOutputConfig.jsonFileName + let testData: [TestJSONData] = SerializersDataProvider.provideTestData(for: fileName) + + /// Prepare configuration + let config = VGSExpDateConfiguration(collector: collector, fieldName: "card.expDate") + config.formatPattern = "####/##" + config.inputDateFormat = .longYearThenMonth + config.outputDateFormat = .shortYearThenMonth + config.divider = "-/-" + + /// Run test for each case from JSON + for test in testData { + /// Prepare serializer + config.serializers = [ + VGSExpDateSeparateSerializer( + monthFieldName: test.monthFieldName, + yearFieldName: test.yearFieldName + ) + ] + /// Update configuration + textField.configuration = config + /// Setup test value + textField.setText(test.fieldValue) + /// Get JSON from collector using serializer + let submitJSON = collector.mapFieldsToBodyJSON(with: .nestedJSON, extraData: nil) + /// Assert: Test JSON content should be equals to the JSON from the collector + XCTAssertTrue(submitJSON == test.submitJSON, + "Expiration date convert error:\n - Input: \(test.fieldValue)\n - Output: \(test.submitJSON)\n - Result: \(submitJSON)") + } + } - for test in testData { - config.serializers = [VGSExpDateSeparateSerializer(monthFieldName: test.monthFieldName, yearFieldName: test.yearFieldName)] - textField.configuration = config - textField.setText(test.fieldValue) - - let submitJSON = collector.mapFieldsToBodyJSON(with: .nestedJSON, extraData: nil) - XCTAssertTrue(submitJSON == test.submitJSON, "Expiration date convert error:\n - Input: \(test.fieldValue)\n - Output: \(test.submitJSON)\n - Result: \(submitJSON)") - + /// Test map with array merge. + func testSplitExpDateSerializersMapWithArray() { + /// Get JSON test data + let fileName = TestFlow.mapWithArrayMerge.jsonFileName + let testData: [TestJSONData] = SerializersDataProvider.provideTestData(for: fileName) + + /// Prepare configuration + let config = VGSExpDateConfiguration(collector: collector, fieldName: "expDate") + config.formatPattern = "##/##" + + /// Setup extra data + let extraData = ["card_data": [["user_id": "123"]]] + + /// Run test for each case from JSON + for test in testData { + /// Prepare serializer + config.serializers = [ + VGSExpDateSeparateSerializer( + monthFieldName: test.monthFieldName, + yearFieldName: test.yearFieldName + ) + ] + /// Update configuration + textField.configuration = config + /// Setup test value + textField.setText(test.fieldValue) + /// Get JSON from collector using serializer + let submitJSON = collector.mapFieldsToBodyJSON(with: .nestedJSONWithArrayMerge, extraData: extraData) + /// Assert: Test JSON content should be equals to the JSON from the collector + XCTAssertTrue(submitJSON == test.submitJSON, + "Expiration date convert error:\n - Input: \(test.fieldValue)\n - Output: \(test.submitJSON)\n - Result: \(submitJSON)") + } + } + + /// Test map with array overwrite. + func testSplitExpDateSerializersMapWithArrayOverwrite() { + /// Get JSON test data + let fileName = TestFlow.mapWithArrayOverwrite.jsonFileName + let testData: [TestJSONData] = SerializersDataProvider.provideTestData(for: fileName) + + /// Prepare configuration + let config = VGSExpDateConfiguration(collector: collector, fieldName: "expDate") + config.formatPattern = "##/##" + + /// Setup extra data + let extraData = ["card_data": [["month": "3", "year": "2033"]]] + + /// Run test for each case from JSON + for test in testData { + /// Prepare serializer + config.serializers = [ + VGSExpDateSeparateSerializer( + monthFieldName: test.monthFieldName, + yearFieldName: test.yearFieldName + ) + ] + /// Update configuration + textField.configuration = config + /// Setup test value + textField.setText(test.fieldValue) + /// Get JSON from collector using serializer + let submitJSON = collector.mapFieldsToBodyJSON(with: .nestedJSONWithArrayOverwrite, extraData: extraData) + /// Assert: Test JSON content should be equals to the JSON from the collector + XCTAssertTrue(submitJSON == test.submitJSON, + "Expiration date convert error:\n - Input: \(test.fieldValue)\n - Output: \(test.submitJSON)\n - Result: \(submitJSON)") + } } - } - - /// Test map with array merge. - func testSplitExpDateSerializersMapWithArray() { - let fileName = TestFlow.mapWithArrayMerge.jsonFileName - let testData = VGSExpDateSerializersDataProvider.provideTestData(for: fileName) - - let config = VGSExpDateConfiguration(collector: collector, fieldName: "expDate") - config.formatPattern = "##/##" - - let extraData = ["card_data": - [ - ["user_id": "123"] - ]] - - for test in testData { - config.serializers = [VGSExpDateSeparateSerializer(monthFieldName: test.monthFieldName, yearFieldName: test.yearFieldName)] - textField.configuration = config - textField.setText(test.fieldValue) - - let submitJSON = collector.mapFieldsToBodyJSON(with: .nestedJSONWithArrayMerge, extraData: extraData) - XCTAssertTrue(submitJSON == test.submitJSON, "Expiration date convert error:\n - Input: \(test.fieldValue)\n - Output: \(test.submitJSON)\n - Result: \(submitJSON)") - } - } - - /// Test map with array overwrite. - func testSplitExpDateSerializersMapWithArrayOverwrite() { - let fileName = TestFlow.mapWithArrayOverwrite.jsonFileName - let testData = VGSExpDateSerializersDataProvider.provideTestData(for: fileName) - - let config = VGSExpDateConfiguration(collector: collector, fieldName: "expDate") - config.formatPattern = "##/##" - - let extraData = ["card_data": - [ - ["month": "3", - "year": "2033"] - ]] - - for test in testData { - config.serializers = [VGSExpDateSeparateSerializer(monthFieldName: test.monthFieldName, yearFieldName: test.yearFieldName)] - textField.configuration = config - textField.setText(test.fieldValue) - - let submitJSON = collector.mapFieldsToBodyJSON(with: .nestedJSONWithArrayOverwrite, extraData: extraData) - XCTAssertTrue(submitJSON == test.submitJSON, "Expiration date convert error:\n - Input: \(test.fieldValue)\n - Output: \(test.submitJSON)\n - Result: \(submitJSON)") - } - } } diff --git a/Tests/FrameworkTests/SerializersTest/VGSExpDateSerializersDataProvider.swift b/Tests/FrameworkTests/SerializersTest/VGSExpDateSerializersDataProvider.swift deleted file mode 100644 index effde585..00000000 --- a/Tests/FrameworkTests/SerializersTest/VGSExpDateSerializersDataProvider.swift +++ /dev/null @@ -1,59 +0,0 @@ -// -// VGSExpDateSerializersDataProvider.swift -// FrameworkTests -// -// Copyright © 2021 VGS. All rights reserved. -// - -import Foundation -import XCTest -@testable import VGSCollectSDK - -final class VGSExpDateSerializersDataProvider { - - static func provideTestData(for fileName: String) -> [VGSExpDateSeparateSerializerTests.TestJSONData] { - guard let rootTestJSON = JsonData(jsonFileName: fileName) else { - XCTFail("cannot build data for file \(fileName)") - return [] - } - - guard let testDataJSONArray = rootTestJSON["test_data"] as? [JsonData] else { - XCTFail("test_data JSON array not found in \(fileName)") - return [] - } - - var testData = [VGSExpDateSeparateSerializerTests.TestJSONData]() - - for json in testDataJSONArray { - if let testItem = VGSExpDateSeparateSerializerTests.TestJSONData(json: json) { - testData.append(testItem) - } else { - XCTFail("Cannot build test data for json: \(json)") - } - } - return testData - } - - static func provideTokenizationTestData(for fileName: String) -> [VGSExpDateTokenizationSerializerTests.TestJSONData] { - guard let rootTestJSON = JsonData(jsonFileName: fileName) else { - XCTFail("cannot build data for file \(fileName)") - return [] - } - - guard let testDataJSONArray = rootTestJSON["test_data"] as? [JsonData] else { - XCTFail("test_data JSON array not found in \(fileName)") - return [] - } - - var testData = [VGSExpDateTokenizationSerializerTests.TestJSONData]() - - for json in testDataJSONArray { - if let testItem = VGSExpDateTokenizationSerializerTests.TestJSONData(json: json) { - testData.append(testItem) - } else { - XCTFail("Cannot build test data for json: \(json)") - } - } - return testData - } -} diff --git a/Tests/FrameworkTests/SerializersTest/VGSExpDateTokenizationSerializerTests.swift b/Tests/FrameworkTests/SerializersTest/VGSExpDateTokenizationSerializerTests.swift index f1f2c494..8339d219 100644 --- a/Tests/FrameworkTests/SerializersTest/VGSExpDateTokenizationSerializerTests.swift +++ b/Tests/FrameworkTests/SerializersTest/VGSExpDateTokenizationSerializerTests.swift @@ -7,105 +7,105 @@ import XCTest @testable import VGSCollectSDK class VGSExpDateTokenizationSerializerTests: VGSCollectBaseTestCase { - var collector: VGSCollect! - var textField: VGSExpDateTextField! - - enum TestFlow { - case defaultConfiguration - - var jsonFileName: String { - return "VGSExpDateTokenizationSerialization_" + jsonFileNameSuffix + var collector: VGSCollect! + var textField: VGSExpDateTextField! + + enum TestFlow { + case defaultConfiguration + + var jsonFileName: String { + return "VGSExpDateTokenizationSerialization_" + jsonFileNameSuffix + } + + var jsonFileNameSuffix: String { + switch self { + case .defaultConfiguration: + return "DefaultConfig" + } + } } - - var jsonFileNameSuffix: String { - switch self { - case .defaultConfiguration: - return "DefaultConfig" - } + + struct TestJSONData: TestJSONDataProtocol { + let fieldValue: String + let monthFieldName: String + let yearFieldName: String + let submitJSON: JsonData + let outputFormat: VGSCardExpDateFormat + let comment: String + let tokenizedPayloads: [JsonData] + + init?(json: JsonData) { + guard let submitJSON = json["expectedResult"] as? JsonData else { + XCTFail("Cannot parse test data.") + return nil + } + guard let formatName = json["outputFormat"] as? String, + let format = VGSCardExpDateFormat(name: formatName) else { + XCTFail("Cannot parse output format from test json") + return nil + } + self.fieldValue = json["fieldValue"] as? String ?? "" + self.monthFieldName = json["monthFieldName"] as? String ?? "" + self.yearFieldName = json["yearFieldName"] as? String ?? "" + self.submitJSON = submitJSON + self.outputFormat = format + self.comment = json["comment"] as? String ?? "" + guard let tokenizedPayloads = submitJSON["data"] as? [JsonData] else { + XCTFail("Invalid payload") + return nil + } + self.tokenizedPayloads = tokenizedPayloads + } } - } - - struct TestJSONData { - let fieldValue: String - let monthFieldName: String - let yearFieldName: String - let submitJSON: JsonData - let outputFormat: VGSCardExpDateFormat - let comment: String - let tokenizedPayloads: [JsonData] - - init?(json: JsonData) { - guard let submitJSON = json["expectedResult"] as? JsonData else { - XCTFail("Cannot parse test data.") - return nil - } - guard let formatName = json["outputFormat"] as? String, - let format = VGSCardExpDateFormat(name: formatName) else { - XCTFail("Cannot parse output format from test json") - return nil - } - self.fieldValue = json["fieldValue"] as? String ?? "" - self.monthFieldName = json["monthFieldName"] as? String ?? "" - self.yearFieldName = json["yearFieldName"] as? String ?? "" - self.submitJSON = submitJSON - self.outputFormat = format - self.comment = json["comment"] as? String ?? "" - guard let tokenizedPayloads = submitJSON["data"] as? [JsonData] else { - XCTFail("Invalid payload") - return nil - } - self.tokenizedPayloads = tokenizedPayloads + + // MARK: - Override + + override func setUp() { + super.setUp() + collector = VGSCollect(id: "any") + textField = VGSExpDateTextField() } - } - - // MARK: - Override - - override func setUp() { - super.setUp() - collector = VGSCollect(id: "any") - textField = VGSExpDateTextField() - } - - override func tearDown() { - collector = nil - textField = nil - } - - // MARK: - Tests - - /// Test default configuration. - func testSplitExpDateSerializerWithDefaultConfig() { - let fileName = TestFlow.defaultConfiguration.jsonFileName - let testData = VGSExpDateSerializersDataProvider.provideTokenizationTestData(for: fileName) - - let config = VGSExpDateTokenizationConfiguration(collector: collector, fieldName: "expDate") - config.formatPattern = "##/##" - config.inputDateFormat = .shortYear - - for test in testData { - config.serializers = [VGSExpDateSeparateSerializer(monthFieldName: test.monthFieldName, yearFieldName: test.yearFieldName)] - config.outputDateFormat = test.outputFormat - textField.configuration = config - - textField.setText(test.fieldValue) - - let submitJSON = collector.mapFieldsToTokenizationRequestBodyJSON(collector.textFields) - - guard let tokenizedPayloads = submitJSON["data"] as? [JsonData] else { - XCTFail("Cannot find tokenized data array.") - return - } - - var matchedPayloads = 0 - // mapFieldsToTokenizationRequestBodyJSON can produce array of tokenized data in different order. So we need to iterate through payloads and check them one by one to get 2 matches (one is for month, another one is for year). - for payload in tokenizedPayloads { - for expectedPayload in test.tokenizedPayloads where payload == expectedPayload { - matchedPayloads += 1 + + override func tearDown() { + collector = nil + textField = nil + } + + // MARK: - Tests + + /// Test default configuration. + func testSplitExpDateSerializerWithDefaultConfig() { + let fileName = TestFlow.defaultConfiguration.jsonFileName + let testData: [TestJSONData] = SerializersDataProvider.provideTestData(for: fileName) + + let config = VGSExpDateTokenizationConfiguration(collector: collector, fieldName: "expDate") + config.formatPattern = "##/##" + config.inputDateFormat = .shortYear + + for test in testData { + config.serializers = [VGSExpDateSeparateSerializer(monthFieldName: test.monthFieldName, yearFieldName: test.yearFieldName)] + config.outputDateFormat = test.outputFormat + textField.configuration = config + + textField.setText(test.fieldValue) + + let submitJSON = collector.mapFieldsToTokenizationRequestBodyJSON(collector.textFields) + + guard let tokenizedPayloads = submitJSON["data"] as? [JsonData] else { + XCTFail("Cannot find tokenized data array.") + return + } + + var matchedPayloads = 0 + // mapFieldsToTokenizationRequestBodyJSON can produce array of tokenized data in different order. So we need to iterate through payloads and check them one by one to get 2 matches (one is for month, another one is for year). + for payload in tokenizedPayloads { + for expectedPayload in test.tokenizedPayloads where payload == expectedPayload { + matchedPayloads += 1 + } + } + + // Should be at least 2 matches of payloads. + XCTAssertTrue(matchedPayloads == 2, "Expiration date convert error:\n - Input: \(test.fieldValue)\n - Output: \(test.submitJSON)\n - Result: \(submitJSON) \nComment: \(test.comment)") } - } - - // Should be at least 2 matches of payloads. - XCTAssertTrue(matchedPayloads == 2, "Expiration date convert error:\n - Input: \(test.fieldValue)\n - Output: \(test.submitJSON)\n - Result: \(submitJSON) \nComment: \(test.comment)") } - } } diff --git a/VGSCollectSDK.podspec b/VGSCollectSDK.podspec index e6653582..4528b3ec 100644 --- a/VGSCollectSDK.podspec +++ b/VGSCollectSDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'VGSCollectSDK' - spec.version = '1.13.0' + spec.version = '1.14.0' spec.summary = 'VGS Collect - is a product suite that allows customers to collect information securely without possession of it.' spec.swift_version = '5.0' spec.description = <<-DESC diff --git a/VGSCollectSDK.xcodeproj/project.pbxproj b/VGSCollectSDK.xcodeproj/project.pbxproj index 606762b3..28806752 100644 --- a/VGSCollectSDK.xcodeproj/project.pbxproj +++ b/VGSCollectSDK.xcodeproj/project.pbxproj @@ -109,7 +109,6 @@ 443FDDC225DD4B2B006932C4 /* VGSCollectBaseTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 443FDDC125DD4B2B006932C4 /* VGSCollectBaseTestCase.swift */; }; 44447F7725F74CCC00D4CE68 /* VGSFieldNameMapUtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44447F7625F74CCC00D4CE68 /* VGSFieldNameMapUtilsTests.swift */; }; 44447F8025F7651100D4CE68 /* JSONData+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44447F7F25F7651100D4CE68 /* JSONData+Extensions.swift */; }; - 4459728A26135BE600139EAA /* VGSExpDateSerializersDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4459728926135BE600139EAA /* VGSExpDateSerializersDataProvider.swift */; }; 4479453E25F8C032006CB371 /* VGSCollect+fieldNameMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4479453D25F8C032006CB371 /* VGSCollect+fieldNameMapping.swift */; }; 4479456525F8EB93006CB371 /* VGSCollectFieldNameMappingPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4479456425F8EB93006CB371 /* VGSCollectFieldNameMappingPolicy.swift */; }; 449C89D525F0AB9F00BE009F /* VGSDeepMergeUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 449C89D425F0AB9F00BE009F /* VGSDeepMergeUtils.swift */; }; @@ -147,6 +146,29 @@ 44ECD60627D9E87000460FDF /* CardIcon.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 44ECD60527D9E87000460FDF /* CardIcon.xcassets */; }; 44F8F51C25DBD1950052647A /* VGSCollectSatelliteUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44F8F51B25DBD1950052647A /* VGSCollectSatelliteUtils.swift */; }; 44F8F52F25DBE8770052647A /* VGSCollectSatelliteUtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44F8F52325DBE7E40052647A /* VGSCollectSatelliteUtilsTests.swift */; }; + A01CE3F729E5D67E0059700F /* VGSDateTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = A01CE3F629E5D67E0059700F /* VGSDateTextField.swift */; }; + A0752C7329EF373400337C99 /* VGSTextFormatConvertable.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0752C7229EF373400337C99 /* VGSTextFormatConvertable.swift */; }; + A0752C7529EF376100337C99 /* VGSDateSeparateSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0752C7429EF376100337C99 /* VGSDateSeparateSerializer.swift */; }; + A0752C7829EF3C9200337C99 /* DateTextFieldTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0752C7629EF3AC300337C99 /* DateTextFieldTest.swift */; }; + A08DA9F329F1B03A00DA62A5 /* VGSDateTokenizationConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = A08DA9F229F1B03A00DA62A5 /* VGSDateTokenizationConfiguration.swift */; }; + A08DA9FC29F1CE0B00DA62A5 /* VGSDateTokenizationSerializerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A08DA9FB29F1CE0B00DA62A5 /* VGSDateTokenizationSerializerTests.swift */; }; + A08DA9FD29F1D1E000DA62A5 /* VGSDateTokenizationSerialization_DefaultConfig.json in Resources */ = {isa = PBXBuildFile; fileRef = A08DA9F929F1CC2A00DA62A5 /* VGSDateTokenizationSerialization_DefaultConfig.json */; }; + A08DA9FF29F1D4D500DA62A5 /* VGSDateFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = A08DA9FE29F1D4D500DA62A5 /* VGSDateFormat.swift */; }; + A08DAA0129F1D52A00DA62A5 /* VGSDateFormatTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A08DAA0029F1D52A00DA62A5 /* VGSDateFormatTests.swift */; }; + A08E91B529F04600007EDA49 /* ValidationRuleDateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A08E91B429F04600007EDA49 /* ValidationRuleDateTests.swift */; }; + A093FE1729F0AA76002C6ABC /* VGSDateSeparateSerializerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A093FE1629F0AA76002C6ABC /* VGSDateSeparateSerializerTests.swift */; }; + A093FE1E29F0BD38002C6ABC /* VGSDateSerialization_CustomExpDateOutputConfig.json in Resources */ = {isa = PBXBuildFile; fileRef = A093FE1929F0BD38002C6ABC /* VGSDateSerialization_CustomExpDateOutputConfig.json */; }; + A093FE1F29F0BD38002C6ABC /* VGSDateSerialization_CustomConfig.json in Resources */ = {isa = PBXBuildFile; fileRef = A093FE1A29F0BD38002C6ABC /* VGSDateSerialization_CustomConfig.json */; }; + A093FE2029F0BD38002C6ABC /* VGSDateSerialization_MapWithArrayMerge.json in Resources */ = {isa = PBXBuildFile; fileRef = A093FE1B29F0BD38002C6ABC /* VGSDateSerialization_MapWithArrayMerge.json */; }; + A093FE2129F0BD38002C6ABC /* VGSDateSerialization_DefaultConfig.json in Resources */ = {isa = PBXBuildFile; fileRef = A093FE1C29F0BD38002C6ABC /* VGSDateSerialization_DefaultConfig.json */; }; + A093FE2229F0BD38002C6ABC /* VGSDateSerialization_MapWithArrayOverwrite.json in Resources */ = {isa = PBXBuildFile; fileRef = A093FE1D29F0BD38002C6ABC /* VGSDateSerialization_MapWithArrayOverwrite.json */; }; + A093FE2429F0BDC7002C6ABC /* SerializersDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A093FE2329F0BDC7002C6ABC /* SerializersDataProvider.swift */; }; + A0988FA129F9739600FAFA67 /* VGSValidationRuleDateRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0988FA029F9739600FAFA67 /* VGSValidationRuleDateRange.swift */; }; + A0BCC67229F064D4009F1118 /* DateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0BCC67129F064D4009F1118 /* DateTests.swift */; }; + A0BCC67429F06CF6009F1118 /* DateConvertorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0BCC67329F06CF6009F1118 /* DateConvertorTests.swift */; }; + A0C1F09A29EE30AB00EE8447 /* VGSDate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0C1F09829EE30AB00EE8447 /* VGSDate.swift */; }; + A0C1F09C29EE30AB00EE8447 /* VGSDateConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0C1F09929EE30AB00EE8447 /* VGSDateConfiguration.swift */; }; + A0C1F0A329EE319D00EE8447 /* DateFormatConvertor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0C1F0A129EE319D00EE8447 /* DateFormatConvertor.swift */; }; FD05F9472316CE5A000EAF52 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD05F9392316CE5A000EAF52 /* Storage.swift */; }; FD05F94A2316CE5A000EAF52 /* VGSConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD05F93C2316CE5A000EAF52 /* VGSConfiguration.swift */; }; FD05F94C2316CE5A000EAF52 /* VGSCollectSDK.h in Headers */ = {isa = PBXBuildFile; fileRef = FD05F93F2316CE5A000EAF52 /* VGSCollectSDK.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -298,7 +320,6 @@ 443FDDC125DD4B2B006932C4 /* VGSCollectBaseTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VGSCollectBaseTestCase.swift; sourceTree = ""; }; 44447F7625F74CCC00D4CE68 /* VGSFieldNameMapUtilsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VGSFieldNameMapUtilsTests.swift; sourceTree = ""; }; 44447F7F25F7651100D4CE68 /* JSONData+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSONData+Extensions.swift"; sourceTree = ""; }; - 4459728926135BE600139EAA /* VGSExpDateSerializersDataProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VGSExpDateSerializersDataProvider.swift; sourceTree = ""; }; 4479453D25F8C032006CB371 /* VGSCollect+fieldNameMapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VGSCollect+fieldNameMapping.swift"; sourceTree = ""; }; 4479456425F8EB93006CB371 /* VGSCollectFieldNameMappingPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VGSCollectFieldNameMappingPolicy.swift; sourceTree = ""; }; 449C89D425F0AB9F00BE009F /* VGSDeepMergeUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VGSDeepMergeUtils.swift; sourceTree = ""; }; @@ -337,6 +358,29 @@ 44ECD60527D9E87000460FDF /* CardIcon.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = CardIcon.xcassets; sourceTree = ""; }; 44F8F51B25DBD1950052647A /* VGSCollectSatelliteUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VGSCollectSatelliteUtils.swift; sourceTree = ""; }; 44F8F52325DBE7E40052647A /* VGSCollectSatelliteUtilsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VGSCollectSatelliteUtilsTests.swift; sourceTree = ""; }; + A01CE3F629E5D67E0059700F /* VGSDateTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VGSDateTextField.swift; sourceTree = ""; }; + A0752C7229EF373400337C99 /* VGSTextFormatConvertable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VGSTextFormatConvertable.swift; sourceTree = ""; }; + A0752C7429EF376100337C99 /* VGSDateSeparateSerializer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VGSDateSeparateSerializer.swift; sourceTree = ""; }; + A0752C7629EF3AC300337C99 /* DateTextFieldTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTextFieldTest.swift; sourceTree = ""; }; + A08DA9F229F1B03A00DA62A5 /* VGSDateTokenizationConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VGSDateTokenizationConfiguration.swift; sourceTree = ""; }; + A08DA9F929F1CC2A00DA62A5 /* VGSDateTokenizationSerialization_DefaultConfig.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = VGSDateTokenizationSerialization_DefaultConfig.json; sourceTree = ""; }; + A08DA9FB29F1CE0B00DA62A5 /* VGSDateTokenizationSerializerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VGSDateTokenizationSerializerTests.swift; sourceTree = ""; }; + A08DA9FE29F1D4D500DA62A5 /* VGSDateFormat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VGSDateFormat.swift; sourceTree = ""; }; + A08DAA0029F1D52A00DA62A5 /* VGSDateFormatTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VGSDateFormatTests.swift; sourceTree = ""; }; + A08E91B429F04600007EDA49 /* ValidationRuleDateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidationRuleDateTests.swift; sourceTree = ""; }; + A093FE1629F0AA76002C6ABC /* VGSDateSeparateSerializerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VGSDateSeparateSerializerTests.swift; sourceTree = ""; }; + A093FE1929F0BD38002C6ABC /* VGSDateSerialization_CustomExpDateOutputConfig.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = VGSDateSerialization_CustomExpDateOutputConfig.json; sourceTree = ""; }; + A093FE1A29F0BD38002C6ABC /* VGSDateSerialization_CustomConfig.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = VGSDateSerialization_CustomConfig.json; sourceTree = ""; }; + A093FE1B29F0BD38002C6ABC /* VGSDateSerialization_MapWithArrayMerge.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = VGSDateSerialization_MapWithArrayMerge.json; sourceTree = ""; }; + A093FE1C29F0BD38002C6ABC /* VGSDateSerialization_DefaultConfig.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = VGSDateSerialization_DefaultConfig.json; sourceTree = ""; }; + A093FE1D29F0BD38002C6ABC /* VGSDateSerialization_MapWithArrayOverwrite.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = VGSDateSerialization_MapWithArrayOverwrite.json; sourceTree = ""; }; + A093FE2329F0BDC7002C6ABC /* SerializersDataProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SerializersDataProvider.swift; sourceTree = ""; }; + A0988FA029F9739600FAFA67 /* VGSValidationRuleDateRange.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VGSValidationRuleDateRange.swift; sourceTree = ""; }; + A0BCC67129F064D4009F1118 /* DateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTests.swift; sourceTree = ""; }; + A0BCC67329F06CF6009F1118 /* DateConvertorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateConvertorTests.swift; sourceTree = ""; }; + A0C1F09829EE30AB00EE8447 /* VGSDate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VGSDate.swift; sourceTree = ""; }; + A0C1F09929EE30AB00EE8447 /* VGSDateConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VGSDateConfiguration.swift; sourceTree = ""; }; + A0C1F0A129EE319D00EE8447 /* DateFormatConvertor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateFormatConvertor.swift; sourceTree = ""; }; FD05F9392316CE5A000EAF52 /* Storage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Storage.swift; sourceTree = ""; }; FD05F93A2316CE5A000EAF52 /* Enums.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Enums.swift; sourceTree = ""; }; FD05F93B2316CE5A000EAF52 /* VGSCollect.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VGSCollect.swift; sourceTree = ""; }; @@ -434,6 +478,7 @@ 035179A0285920F100394BFC /* VGSCardTokenizationConfiguration.swift */, 035179A22859BABC00394BFC /* VGSSSNTokenizationConfiguration.swift */, 035179A42859BB7D00394BFC /* VGSExpDateTokenizationConfiguration.swift */, + A08DA9F229F1B03A00DA62A5 /* VGSDateTokenizationConfiguration.swift */, 035179A62859BCC400394BFC /* VGSCardHolderNameTokenizationConfiguration.swift */, 035179A82859BD5500394BFC /* VGSTokenizationConfiguration.swift */, ); @@ -478,6 +523,13 @@ path = CardDataMappers; sourceTree = ""; }; + 24A3321F33CCBCFBF0C01580 /* Pods */ = { + isa = PBXGroup; + children = ( + ); + path = Pods; + sourceTree = ""; + }; 32093D7225CD9F88006CD242 /* Loggers */ = { isa = PBXGroup; children = ( @@ -506,6 +558,7 @@ children = ( 3215C4BB260DAF3D00F21259 /* VGSFormatSerializerProtocol.swift */, 3215C4C7260DAF9400F21259 /* VGSExpDateSeparateSerializer.swift */, + A0752C7429EF376100337C99 /* VGSDateSeparateSerializer.swift */, ); path = Serializers; sourceTree = ""; @@ -513,10 +566,12 @@ 3215C4E72611B4B900F21259 /* SerializersTest */ = { isa = PBXGroup; children = ( + A093FE2329F0BDC7002C6ABC /* SerializersDataProvider.swift */, + A093FE1629F0AA76002C6ABC /* VGSDateSeparateSerializerTests.swift */, + A08DA9FB29F1CE0B00DA62A5 /* VGSDateTokenizationSerializerTests.swift */, 3215C4E82611B50A00F21259 /* VGSExpDateSeparateSerializerTests.swift */, - 4459728926135BE600139EAA /* VGSExpDateSerializersDataProvider.swift */, - 44168FBE2632945D0088E515 /* VGSExpirationDateTextFieldUtilsTests.swift */, 44EAE09D28FE8B2700FC6BBB /* VGSExpDateTokenizationSerializerTests.swift */, + 44168FBE2632945D0088E515 /* VGSExpirationDateTextFieldUtilsTests.swift */, ); path = SerializersTest; sourceTree = ""; @@ -524,6 +579,8 @@ 322F94B925BABE82001CDF12 /* Convertors */ = { isa = PBXGroup; children = ( + A0752C7229EF373400337C99 /* VGSTextFormatConvertable.swift */, + A0C1F0A129EE319D00EE8447 /* DateFormatConvertor.swift */, 322F94BA25BABE97001CDF12 /* ExpDateFormatConvertor.swift */, ); path = Convertors; @@ -533,6 +590,7 @@ isa = PBXGroup; children = ( 322F94D625BAC3E0001CDF12 /* ExpDateConvertorTests.swift */, + A0BCC67329F06CF6009F1118 /* DateConvertorTests.swift */, ); path = ConvertorsTests; sourceTree = ""; @@ -540,6 +598,8 @@ 324B5E6224A235BC0036867E /* Date */ = { isa = PBXGroup; children = ( + A0988FA029F9739600FAFA67 /* VGSValidationRuleDateRange.swift */, + A08DA9FE29F1D4D500DA62A5 /* VGSDateFormat.swift */, 324B5E7424A23FA60036867E /* VGSValidationRuleExpirationDate.swift */, ); path = Date; @@ -777,10 +837,12 @@ 44D5210B2681B803005AB588 /* Resources */ = { isa = PBXGroup; children = ( - 442A391129097167007CCC58 /* VGSTokenizationJSONs */, + A093FE1829F0ACA2002C6ABC /* DateSplitSerializerTestJSONs */, + A08DA9F829F1CC2A00DA62A5 /* DateTokenizationJSON */, + 44D521152681B803005AB588 /* ExpDateSplitSerializerTestJSONs */, 44EAE09A28FE65B900FC6BBB /* ExpDateTokenizationJSON */, 44D5210C2681B803005AB588 /* TestJSONs */, - 44D521152681B803005AB588 /* ExpDateSplitSerializerTestJSONs */, + 442A391129097167007CCC58 /* VGSTokenizationJSONs */, 442BB2C5287314DC001FD26B /* MockedData.plist */, ); path = Resources; @@ -832,11 +894,11 @@ 44D521152681B803005AB588 /* ExpDateSplitSerializerTestJSONs */ = { isa = PBXGroup; children = ( - 44D521162681B803005AB588 /* VGSExpDateSerialization_DefaultConfig.json */, + 44D5211A2681B803005AB588 /* VGSExpDateSerialization_CustomConfig.json */, 44D521172681B803005AB588 /* VGSExpDateSerialization_CustomExpDateOutputConfig.json */, - 44D521182681B803005AB588 /* VGSExpDateSerialization_MapWithArrayOverwrite.json */, + 44D521162681B803005AB588 /* VGSExpDateSerialization_DefaultConfig.json */, 44D521192681B803005AB588 /* VGSExpDateSerialization_MapWithArrayMerge.json */, - 44D5211A2681B803005AB588 /* VGSExpDateSerialization_CustomConfig.json */, + 44D521182681B803005AB588 /* VGSExpDateSerialization_MapWithArrayOverwrite.json */, ); path = ExpDateSplitSerializerTestJSONs; sourceTree = ""; @@ -899,6 +961,34 @@ path = "Satellite Tests"; sourceTree = ""; }; + A08DA9F829F1CC2A00DA62A5 /* DateTokenizationJSON */ = { + isa = PBXGroup; + children = ( + A08DA9F929F1CC2A00DA62A5 /* VGSDateTokenizationSerialization_DefaultConfig.json */, + ); + path = DateTokenizationJSON; + sourceTree = ""; + }; + A093FE1829F0ACA2002C6ABC /* DateSplitSerializerTestJSONs */ = { + isa = PBXGroup; + children = ( + A093FE1A29F0BD38002C6ABC /* VGSDateSerialization_CustomConfig.json */, + A093FE1929F0BD38002C6ABC /* VGSDateSerialization_CustomExpDateOutputConfig.json */, + A093FE1C29F0BD38002C6ABC /* VGSDateSerialization_DefaultConfig.json */, + A093FE1B29F0BD38002C6ABC /* VGSDateSerialization_MapWithArrayMerge.json */, + A093FE1D29F0BD38002C6ABC /* VGSDateSerialization_MapWithArrayOverwrite.json */, + ); + path = DateSplitSerializerTestJSONs; + sourceTree = ""; + }; + A0BCC67029F064C0009F1118 /* Core */ = { + isa = PBXGroup; + children = ( + A0BCC67129F064D4009F1118 /* DateTests.swift */, + ); + path = Core; + sourceTree = ""; + }; FD05F9372316CE5A000EAF52 /* VGSCollectSDK */ = { isa = PBXGroup; children = ( @@ -922,9 +1012,11 @@ 44ECD5F427D9C18C00460FDF /* VGSPaymentCards */, 035179992858B39100394BFC /* TokenizationConfiguration */, FD05F93A2316CE5A000EAF52 /* Enums.swift */, + A0C1F09829EE30AB00EE8447 /* VGSDate.swift */, FD05F9392316CE5A000EAF52 /* Storage.swift */, FD05F93C2316CE5A000EAF52 /* VGSConfiguration.swift */, 322F94B025BABD9D001CDF12 /* VGSExpDateConfiguration.swift */, + A0C1F09929EE30AB00EE8447 /* VGSDateConfiguration.swift */, 3219D73C2404279700F4A7E5 /* VGSError.swift */, 327C9E132407EF92004C641C /* VGSErrorInfo.swift */, 327C9E152407F43A004C641C /* VGSErrorInfoKey.swift */, @@ -952,6 +1044,7 @@ 03B10BB028E20A3A009B409B /* VGSBlinkCardCollector */, FD12B9B02304619100B670DD /* Products */, 32CFC72324EBF3B500457B17 /* Frameworks */, + 24A3321F33CCBCFBF0C01580 /* Pods */, ); sourceTree = ""; }; @@ -987,6 +1080,7 @@ FD2495522330CB49009024E6 /* FrameworkTests */ = { isa = PBXGroup; children = ( + A0BCC67029F064C0009F1118 /* Core */, 442A391529097408007CCC58 /* TokenizationTests */, 44447F7D25F7648700D4CE68 /* Test Helpers */, 449C89E225F0AFAE00BE009F /* DeepMergeUtils Tests */, @@ -1078,6 +1172,7 @@ children = ( FD24956F2330E834009024E6 /* CardNumerTextFieldTests.swift */, FDAAB6AA249A8844001F5C1A /* ExpDateTextField.swift */, + A0752C7629EF3AC300337C99 /* DateTextFieldTest.swift */, FDE8907C2333A1D400FA170D /* CVVTextFieldTests.swift */, 3270D3F0248155B200004E3B /* SSNTextFieldTests.swift */, FDE8907A2333A16A00FA170D /* ExpDateTextFieldTests.swift */, @@ -1088,6 +1183,8 @@ FDF696E023463ACA00063507 /* TextFielsStyleUI.swift */, FDA680DE239844FC00372817 /* CardTextFieldTests.swift */, 324B5E7924A3A34F0036867E /* ValidationRulesTest.swift */, + A08DAA0029F1D52A00DA62A5 /* VGSDateFormatTests.swift */, + A08E91B429F04600007EDA49 /* ValidationRuleDateTests.swift */, 32AFB93624FFD218007FFCAE /* VGSTextFieldTests.swift */, 441A727C272AAEEA0036BECB /* TextFieldMaxInputLengthTests.swift */, ); @@ -1102,6 +1199,7 @@ FD2495622330E313009024E6 /* Validation */, FDD398ED247D776600B55057 /* VGSCardTextField.swift */, FD8B62462497CD580097C9AB /* VGSExpDateTextField.swift */, + A01CE3F629E5D67E0059700F /* VGSDateTextField.swift */, FD05F9442316CE5A000EAF52 /* VGSTextField.swift */, 321FE73925DE45FC00B138E9 /* VGSCVCTextField.swift */, FD3C01C223AFC0980096B4A4 /* VGSTextField+CVC.swift */, @@ -1321,13 +1419,19 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + A093FE1F29F0BD38002C6ABC /* VGSDateSerialization_CustomConfig.json in Resources */, 44D521212681B803005AB588 /* VGSExpDateSerialization_MapWithArrayOverwrite.json in Resources */, 44D5211C2681B803005AB588 /* FlatPolicyTestJSONs.json in Resources */, 44D521202681B803005AB588 /* VGSExpDateSerialization_CustomExpDateOutputConfig.json in Resources */, 442BB2C6287314DC001FD26B /* MockedData.plist in Resources */, 44D5210A2681B7F6005AB588 /* FrameworkTests.xctestplan in Resources */, + A093FE2229F0BD38002C6ABC /* VGSDateSerialization_MapWithArrayOverwrite.json in Resources */, + A093FE1E29F0BD38002C6ABC /* VGSDateSerialization_CustomExpDateOutputConfig.json in Resources */, + A093FE2029F0BD38002C6ABC /* VGSDateSerialization_MapWithArrayMerge.json in Resources */, 44D521232681B803005AB588 /* VGSExpDateSerialization_CustomConfig.json in Resources */, + A08DA9FD29F1D1E000DA62A5 /* VGSDateTokenizationSerialization_DefaultConfig.json in Resources */, 44D5211F2681B803005AB588 /* VGSExpDateSerialization_DefaultConfig.json in Resources */, + A093FE2129F0BD38002C6ABC /* VGSDateSerialization_DefaultConfig.json in Resources */, 44D5211D2681B803005AB588 /* OverwriteArraysTestJSONs.json in Resources */, 442A39132909718F007CCC58 /* VGSTokenizationTestJSON_DefaultConfig.json in Resources */, 44EAE09C28FE666200FC6BBB /* VGSExpDateTokenizationSerialization_DefaultConfig.json in Resources */, @@ -1454,6 +1558,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + A0752C7329EF373400337C99 /* VGSTextFormatConvertable.swift in Sources */, 324B5E7124A23E670036867E /* VGSValidationRuleLength.swift in Sources */, FDD42A3D233F67BA0005D631 /* VGSTextField+UIBuilder.swift in Sources */, 3219D73D2404279700F4A7E5 /* VGSError.swift in Sources */, @@ -1462,6 +1567,7 @@ 033C979729D5BDC60088E045 /* VGSTextField+statePublisher.swift in Sources */, 32093D7E25CD9F88006CD242 /* VGSCollectRequestLogger.swift in Sources */, FD3C01C423AFCEEE0096B4A4 /* Enums.swift in Sources */, + A08DA9F329F1B03A00DA62A5 /* VGSDateTokenizationConfiguration.swift in Sources */, 441B26D425DB88C50099AA3A /* APIHostURLPolicy.swift in Sources */, 44ECD60227D9C18C00460FDF /* CardType+icon.swift in Sources */, 449C8A3825F2513300BE009F /* VGSFieldNameToSubscriptMapper.swift in Sources */, @@ -1472,20 +1578,24 @@ 32093D7A25CD9F88006CD242 /* VGSCollectLoggingConfiguration.swift in Sources */, 44ECD5FF27D9C18C00460FDF /* VGSPaymentCards.swift in Sources */, FD05F94A2316CE5A000EAF52 /* VGSConfiguration.swift in Sources */, + A0C1F0A329EE319D00EE8447 /* DateFormatConvertor.swift in Sources */, 324B5E6F24A23D530036867E /* VGSValidationRule.swift in Sources */, 324B5E7524A23FA60036867E /* VGSValidationRuleExpirationDate.swift in Sources */, 441B26F025DB956B0099AA3A /* URL+Extensions.swift in Sources */, 0351799B2858B3B700394BFC /* VGSTextFieldTokenizationProtocol.swift in Sources */, + A0988FA129F9739600FAFA67 /* VGSValidationRuleDateRange.swift in Sources */, 441B26DD25DB88DB0099AA3A /* VGSResponse.swift in Sources */, 325AB9CB2420C5410024134B /* VGSFilePickerControllerDelegate.swift in Sources */, 328B5C7023C8DA2600A39515 /* String+extension.swift in Sources */, 32093D7D25CD9F88006CD242 /* VGSCollectLogEvent.swift in Sources */, 44ECD60427D9C18C00460FDF /* CheckSumAlgoritmType.swift in Sources */, 3215C4BC260DAF3D00F21259 /* VGSFormatSerializerProtocol.swift in Sources */, + A0752C7529EF376100337C99 /* VGSDateSeparateSerializer.swift in Sources */, 441B4E9B293EFD050011EFAC /* VGSCollectHTTPMethod.swift in Sources */, 32093D8625CDA3E6006CD242 /* VGSReadWriteSafeContainer.swift in Sources */, FD3C01C323AFC0980096B4A4 /* VGSTextField+CVC.swift in Sources */, 44F8F51C25DBD1950052647A /* VGSCollectSatelliteUtils.swift in Sources */, + A0C1F09C29EE30AB00EE8447 /* VGSDateConfiguration.swift in Sources */, 326FFB0424F90B940024A4F9 /* CrardScannerInteractionProtocol.swift in Sources */, 44ECD5FE27D9C18C00460FDF /* VGSPaymentCardModel.swift in Sources */, FD8B62472497CD580097C9AB /* VGSExpDateTextField.swift in Sources */, @@ -1503,6 +1613,7 @@ FD05F9472316CE5A000EAF52 /* Storage.swift in Sources */, 449C8A4025F2521900BE009F /* VGSFieldNameSubscriptType.swift in Sources */, 3259B39D263079AD008EECE0 /* VGSExpirationDateTextFieldUtils.swift in Sources */, + A01CE3F729E5D67E0059700F /* VGSDateTextField.swift in Sources */, 4479453E25F8C032006CB371 /* VGSCollect+fieldNameMapping.swift in Sources */, 441B26D625DB88C50099AA3A /* APICustomHostStatus.swift in Sources */, 441B26D225DB88C50099AA3A /* APIClient.swift in Sources */, @@ -1518,10 +1629,12 @@ 324B5E9D24A64A600036867E /* VGSValidationRulePaymentCard.swift in Sources */, 327C9E142407EF92004C641C /* VGSErrorInfo.swift in Sources */, 32F4B7F424C881FA006086F3 /* Calendar+extension.swift in Sources */, + A08DA9FF29F1D4D500DA62A5 /* VGSDateFormat.swift in Sources */, 32F23A6D24B60E1100E389F7 /* VGSValidationRuleLengthMatch.swift in Sources */, 321300172417F2B70062FEF0 /* VGSTextField.swift in Sources */, 328A574023FADC3500714675 /* VGSFilePickerConfiguration.swift in Sources */, 449C89DC25F0ABB000BE009F /* Collection+Extensions.swift in Sources */, + A0C1F09A29EE30AB00EE8447 /* VGSDate.swift in Sources */, 328A574223FADD3D00714675 /* VGSFilePickerController+internal.swift in Sources */, 32093D7B25CD9F88006CD242 /* VGSCollectLogger.swift in Sources */, FD1489FF232D4F8000FD7781 /* MaskedTextField.swift in Sources */, @@ -1559,7 +1672,9 @@ FDF696E3234643F300063507 /* LuhnTests.swift in Sources */, 44C23A7925F7B7EF000EA556 /* VGSFieldNameToJSONTests.swift in Sources */, 3270D3F1248155B200004E3B /* SSNTextFieldTests.swift in Sources */, + A08DAA0129F1D52A00DA62A5 /* VGSDateFormatTests.swift in Sources */, 44D520AE2672218A005AB588 /* VGSFlatJSONStructMappingTests.swift in Sources */, + A0752C7829EF3C9200337C99 /* DateTextFieldTest.swift in Sources */, FDF696E123463ACB00063507 /* TextFielsStyleUI.swift in Sources */, 442A391729097425007CCC58 /* VGSTokenizationResponseMappingTests.swift in Sources */, 3213005B241FA0BE0062FEF0 /* VGSCollectTest+Validation.swift in Sources */, @@ -1573,10 +1688,13 @@ FDA680DF239844FC00372817 /* CardTextFieldTests.swift in Sources */, 44447F8025F7651100D4CE68 /* JSONData+Extensions.swift in Sources */, 32F23A7924B752E200E389F7 /* PaymentCardsTest.swift in Sources */, + A0BCC67229F064D4009F1118 /* DateTests.swift in Sources */, FDAAB6AD249A9257001F5C1A /* FileInfoTest.swift in Sources */, 44168FBF2632945D0088E515 /* VGSExpirationDateTextFieldUtilsTests.swift in Sources */, 327C9E172407FC58004C641C /* VGSErrorInfo.swift in Sources */, FDAAB6AB249A8844001F5C1A /* ExpDateTextField.swift in Sources */, + A093FE1729F0AA76002C6ABC /* VGSDateSeparateSerializerTests.swift in Sources */, + A093FE2429F0BDC7002C6ABC /* SerializersDataProvider.swift in Sources */, FDF696E52346461D00063507 /* StorageTests.swift in Sources */, FD1BE48823462F1E006D8658 /* ExpDateTextFieldTests.swift in Sources */, FD790B97243BB403006A30CB /* CardBrandTest.swift in Sources */, @@ -1584,17 +1702,19 @@ 32AFB93724FFD218007FFCAE /* VGSTextFieldTests.swift in Sources */, 0313A1202975A22700DB2F2C /* VGSTokenizationConfigurationTests.swift in Sources */, 449C89E925F0AFF400BE009F /* VGSDeepMergeUtilsTests.swift in Sources */, + A0BCC67429F06CF6009F1118 /* DateConvertorTests.swift in Sources */, 322F94D725BAC3E0001CDF12 /* ExpDateConvertorTests.swift in Sources */, FD4ED0E52373666500AEAD24 /* TextFieldSecurity.swift in Sources */, + A08DA9FC29F1CE0B00DA62A5 /* VGSDateTokenizationSerializerTests.swift in Sources */, FD24955E2330CC62009024E6 /* VGSCollectTests.swift in Sources */, 324B5E7B24A3A5880036867E /* ValidationRulesTest.swift in Sources */, 44447F7725F74CCC00D4CE68 /* VGSFieldNameMapUtilsTests.swift in Sources */, 442BB2C82873158A001FD26B /* MockedDataProvider.swift in Sources */, 4404600F256801890064BEA0 /* APIHostnameValidatorTests.swift in Sources */, + A08E91B529F04600007EDA49 /* ValidationRuleDateTests.swift in Sources */, 3299585D23DF043D0018FA50 /* MaskedTextFieldTest.swift in Sources */, 324CDEE323FB12E200653890 /* FilePickerTests.swift in Sources */, 443FDDC225DD4B2B006932C4 /* VGSCollectBaseTestCase.swift in Sources */, - 4459728A26135BE600139EAA /* VGSExpDateSerializersDataProvider.swift in Sources */, 327C9E182407FC62004C641C /* VGSErrorInfoKey.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1830,7 +1950,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MARKETING_VERSION = 1.13.0; + MARKETING_VERSION = 1.14.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -1892,7 +2012,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MARKETING_VERSION = 1.13.0; + MARKETING_VERSION = 1.14.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; diff --git a/demoapp/demoapp.xcodeproj/project.pbxproj b/demoapp/demoapp.xcodeproj/project.pbxproj index 1af5cd1d..3a5c6e16 100644 --- a/demoapp/demoapp.xcodeproj/project.pbxproj +++ b/demoapp/demoapp.xcodeproj/project.pbxproj @@ -52,6 +52,7 @@ 44D8691C26205F670014645F /* SSNCollectingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44D8691426205F670014645F /* SSNCollectingViewController.swift */; }; 44D8691D26205F670014645F /* CustomDataCollectingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44D8691526205F670014645F /* CustomDataCollectingViewController.swift */; }; 44D8692026205F670014645F /* FilePickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44D8691926205F670014645F /* FilePickerViewController.swift */; }; + A01CE3F529E5C50D0059700F /* DateValidationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A01CE3F429E5C50D0059700F /* DateValidationViewController.swift */; }; C8CBAAC0A0A75BF9CF5A7FA4 /* Pods_demoapp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DAC2D9D525DA573788F57B /* Pods_demoapp.framework */; }; FD12B9782304616C00B670DD /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD12B9772304616C00B670DD /* AppDelegate.swift */; }; FD12B97F2304616E00B670DD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FD12B97E2304616E00B670DD /* Assets.xcassets */; }; @@ -130,6 +131,7 @@ 7D9EC63EB636126947A436E7 /* libPods-demoappUITests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-demoappUITests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 971F95F0CD23156BC2F071A3 /* Pods-demoappUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-demoappUITests.release.xcconfig"; path = "Target Support Files/Pods-demoappUITests/Pods-demoappUITests.release.xcconfig"; sourceTree = ""; }; 9E14BE9AC3107988B3A45EBF /* Pods-demoapp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-demoapp.release.xcconfig"; path = "Target Support Files/Pods-demoapp/Pods-demoapp.release.xcconfig"; sourceTree = ""; }; + A01CE3F429E5C50D0059700F /* DateValidationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateValidationViewController.swift; sourceTree = ""; }; B96EAC87AAF5BF889451003A /* Pods-demoapp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-demoapp.debug.xcconfig"; path = "Target Support Files/Pods-demoapp/Pods-demoapp.debug.xcconfig"; sourceTree = ""; }; C0DAC2D9D525DA573788F57B /* Pods_demoapp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_demoapp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; FD12B9742304616C00B670DD /* demoapp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = demoapp.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -347,6 +349,7 @@ 44D8691926205F670014645F /* FilePickerViewController.swift */, 03DBB7B3292FBFDA00F4DCA2 /* CollectApplePayDataViewController.swift */, 03B992D729C8A5BF00B10A70 /* CombineExamplesViewController.swift */, + A01CE3F429E5C50D0059700F /* DateValidationViewController.swift */, ); path = UseCases; sourceTree = ""; @@ -719,6 +722,7 @@ 44D8692026205F670014645F /* FilePickerViewController.swift in Sources */, 446FE1D625D557080021C7C0 /* UIDevice+Extensions.swift in Sources */, 44D8691C26205F670014645F /* SSNCollectingViewController.swift in Sources */, + A01CE3F529E5C50D0059700F /* DateValidationViewController.swift in Sources */, 44D8691D26205F670014645F /* CustomDataCollectingViewController.swift in Sources */, 449FFCBE28A517E200FE4A1F /* UITableView+Extensions.swift in Sources */, 0351799F2858D53C00394BFC /* CardsDataTokenizationViewController.swift in Sources */, @@ -911,7 +915,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 35; - DEVELOPMENT_TEAM = 4445Y664U5; + DEVELOPMENT_TEAM = 7S7622HN85; INFOPLIST_FILE = demoapp/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.1; LD_RUNPATH_SEARCH_PATHS = ( @@ -937,7 +941,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 35; - DEVELOPMENT_TEAM = 4445Y664U5; + DEVELOPMENT_TEAM = 7S7622HN85; INFOPLIST_FILE = demoapp/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.1; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/demoapp/demoapp/Main.storyboard b/demoapp/demoapp/Main.storyboard index 4b2159ea..d971ec2d 100644 --- a/demoapp/demoapp/Main.storyboard +++ b/demoapp/demoapp/Main.storyboard @@ -1,9 +1,9 @@ - + - + @@ -100,14 +100,14 @@ - + - + - - + - + - + - - + - + - + - - + - + - + - - + - + + + + + + + + + + + + + + + @@ -423,7 +443,7 @@ - + @@ -918,7 +938,7 @@ - + @@ -1313,25 +1333,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - + - + - + - - - + - + - + - + - - - - - - - - - - - + + + + + + + + + + - + - - - - - - - - - - + + + + + + + + + + - - + + - - - - + + + + - + - + diff --git a/demoapp/demoapp/UseCases/DateValidationViewController.swift b/demoapp/demoapp/UseCases/DateValidationViewController.swift new file mode 100644 index 00000000..11f20738 --- /dev/null +++ b/demoapp/demoapp/UseCases/DateValidationViewController.swift @@ -0,0 +1,186 @@ +// +// DateValidationViewController.swift +// demoapp +// + +import UIKit +import VGSCollectSDK + +class DateValidationViewController: UIViewController { + + // MARK: - Outlets + @IBOutlet weak var containerStackView: UIStackView! + @IBOutlet weak var consoleStatusLabel: UILabel! + @IBOutlet weak var consoleLabel: UILabel! + + // MARK: - Properties + /// Init VGS Collector + var vgsCollect = VGSCollect( + id: AppCollectorConfiguration.shared.vaultId, + environment: AppCollectorConfiguration.shared.environment + ) + /// VGS UI Elements + var dateField = VGSDateTextField() + var consoleMessage: String = "" { + didSet { + consoleLabel.text = consoleMessage + } + } + + // MARK: - View life cycle + override func viewDidLoad() { + super.viewDidLoad() + + /// Configuration + setupUI() + setupElementsConfiguration() + + /// Set custom headers + vgsCollect.customHeaders = [ + "my custome header": "some custom data" + ] + + /// Observe VGSTextFields changes + vgsCollect.observeStates = { [weak self] form in + + self?.consoleMessage = "" + self?.consoleStatusLabel.text = "STATE" + + form.forEach({ textField in + self?.consoleMessage.append(textField.state.description) + self?.consoleMessage.append("\n") + }) + } + } +} + +// MARK: - Private methods +private extension DateValidationViewController { + + func setupUI() { + containerStackView.addArrangedSubview(dateField) + let tapGesture = UITapGestureRecognizer( + target: self, + action: #selector(hideKeyboard) + ) + consoleLabel.addGestureRecognizer(tapGesture) + consoleLabel.isUserInteractionEnabled = true + view.addGestureRecognizer(tapGesture) + } + + @objc + func hideKeyboard() { + view.endEditing(true) + consoleLabel.endEditing(true) + } + + func setupElementsConfiguration() { + + /// Start and end dates + let startDate = VGSDate(day: 1, month: 1, year: 2010) + let endDate = VGSDate(day: 20, month: 12, year: 2025) + + // Date format + let inputDateFormat = VGSDateFormat.mmddyyyy + + /// Create configuration + let dateFieldConfiguration = VGSDateConfiguration( + collector: vgsCollect, + fieldName: "date_field", + datePickerStartDate: startDate, + datePickerEndDate: endDate + ) + dateFieldConfiguration.inputDateFormat = inputDateFormat + dateFieldConfiguration.outputDateFormat = .yyyymmdd + dateFieldConfiguration.inputSource = .datePicker + dateFieldConfiguration.divider = "-" + dateFieldConfiguration.formatPattern = "##/##/####" + + /// Setup validation rules, it is important to set the same start and + /// end date used in the configuration + dateFieldConfiguration.validationRules = VGSValidationRuleSet( + rules: [ + VGSValidationRuleDateRange( + dateFormat: inputDateFormat, + error: VGSValidationErrorType.date.rawValue, + start: startDate, + end: endDate + ) + ] + ) + + /// Update configuration in the text field + dateField.configuration = dateFieldConfiguration + dateField.placeholder = "MM-DD-YYYY" + dateField.monthPickerFormat = .longSymbols + + /// Add logging + vgsCollect.textFields.forEach { textField in + textField.textColor = UIColor.inputBlackTextColor + textField.font = .systemFont(ofSize: 22) + textField.padding = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8) + textField.tintColor = .lightGray + /// Implement VGSTextFieldDelegate methods + textField.delegate = self + } + } + + // Upload data from TextFields to VGS + @IBAction func uploadAction(_ sender: Any) { + // Hide kayboard + hideKeyboard() + + // Check if textfields are valid + vgsCollect.textFields.forEach { textField in + textField.borderColor = textField.state.isValid ? .lightGray : .red + } + + // Send extra data + var extraData = [String: Any]() + extraData["customKey"] = "Custom Value" + + /// New sendRequest func + vgsCollect.sendData(path: "/post", extraData: extraData) { [weak self] (response) in + self?.consoleStatusLabel.text = "RESPONSE" + switch response { + case .success(_, let data, _): + if let data = data, let jsonData = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] { + // swiftlint:disable force_try + let response = ( + String(data: try! JSONSerialization.data(withJSONObject: jsonData["json"]!, + options: .prettyPrinted), encoding: .utf8)! + ) + self?.consoleLabel.text = "Success: \n\(response)" + print(response) + // swiftlint:enable force_try + } + return + + case .failure(let code, _, _, let error): + switch code { + case 400..<499: + // Wrong request. This also can happend when your Routs not setup yet or your is wrong + self?.consoleLabel.text = "Error: Wrong Request, code: \(code)" + + case VGSErrorType.inputDataIsNotValid.rawValue: + if let error = error as? VGSError { + self?.consoleLabel.text = "Error: Input data is not valid. Details:\n \(error)" + } + + default: + self?.consoleLabel.text = "Error: Something went wrong. Code: \(code)" + } + print("Submit request error: \(code), \(String(describing: error))") + return + } + } + } +} + +// MARK: - VGSTextFieldDelegate implementation +extension DateValidationViewController: VGSTextFieldDelegate { + + func vgsTextFieldDidChange(_ textField: VGSTextField) { + textField.borderColor = textField.state.isValid ? .gray : .red + } +} From 1ef0a6b9ba4c3d49a18c952221dea886f7929133 Mon Sep 17 00:00:00 2001 From: Dima Khludkov <57712402+dmytrokhl@users.noreply.github.com> Date: Tue, 4 Jul 2023 12:25:38 +0300 Subject: [PATCH 2/4] Fix SwiftUI preview. --- .../UIElements/Text Field/Validation/Date/VGSDateFormat.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Date/VGSDateFormat.swift b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Date/VGSDateFormat.swift index 54c70463..ca691b8c 100644 --- a/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Date/VGSDateFormat.swift +++ b/Sources/VGSCollectSDK/UIElements/Text Field/Validation/Date/VGSDateFormat.swift @@ -2,6 +2,7 @@ // VGSDateFormat.swift // VGSCollectSDK // +import Foundation /// Format used to validate a VGS date text input public enum VGSDateFormat: InputConvertableFormat, OutputConvertableFormat { From 4c1a8c3fa1e854836f06df13817418d263dbc35e Mon Sep 17 00:00:00 2001 From: Donald Rodriguez Gutierrez <129230521+DonaldRG@users.noreply.github.com> Date: Wed, 19 Jul 2023 07:12:50 -0600 Subject: [PATCH 3/4] Accessibility Improvements. --- .../UIElements/Text Field/VGSTextField.swift | 44 +++++++++++++------ .../Text Fields Tests/CVVTextFieldTests.swift | 25 +++++++++++ .../CardHolderNameFieldTests.swift | 25 +++++++++++ .../CardNumerTextFieldTests.swift | 25 +++++++++++ .../Text Fields Tests/DateTextFieldTest.swift | 25 +++++++++++ .../Text Fields Tests/ExpDateTextField.swift | 25 +++++++++++ .../Text Fields Tests/SSNTextFieldTests.swift | 25 +++++++++++ demoapp/demoapp.xcodeproj/project.pbxproj | 4 +- .../CardsDataCollectingViewController.swift | 1 - .../CardsDataTokenizationViewController.swift | 1 - .../CombineExamplesViewController.swift | 1 - .../CustomDataCollectingViewController.swift | 1 - .../CustomPaymentCardsViewController.swift | 1 - .../DateValidationViewController.swift | 4 +- .../SSNCollectingViewController.swift | 1 - 15 files changed, 186 insertions(+), 22 deletions(-) diff --git a/Sources/VGSCollectSDK/UIElements/Text Field/VGSTextField.swift b/Sources/VGSCollectSDK/UIElements/Text Field/VGSTextField.swift index b6ce1663..5d3ffe44 100644 --- a/Sources/VGSCollectSDK/UIElements/Text Field/VGSTextField.swift +++ b/Sources/VGSCollectSDK/UIElements/Text Field/VGSTextField.swift @@ -93,19 +93,37 @@ public class VGSTextField: UIView { } } - /// A succinct label in a localized string that identifies the accessibility text field. - public var textFieldAccessibilityLabel: String? { - didSet { - textField.accessibilityLabel = textFieldAccessibilityLabel - } - } - - /// A localized string that contains a brief description of the result of performing an action on the accessibility text field. - public var textFieldAccessibilityHint: String? { - didSet { - textField.accessibilityHint = textFieldAccessibilityHint - } - } + // MARK: - Accessibility Attributes + /// A succinct label in a localized string that identifies the accessibility text field. + public var textFieldAccessibilityLabel: String? { + get { + return textField.accessibilityLabel + } + set { + textField.accessibilityLabel = newValue + } + } + + /// A localized string that contains a brief description of the result of + /// performing an action on the accessibility text field. + public var textFieldAccessibilityHint: String? { + get { + return textField.accessibilityHint + } + set { + textField.accessibilityHint = newValue + } + } + + /// Boolean value that determinates if the text field should be exposed as an accesibility element. + public var textFieldIsAccessibilityElement: Bool { + get { + return textField.isAccessibilityElement + } + set { + textField.isAccessibilityElement = newValue + } + } // MARK: - Functional Attributes diff --git a/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/CVVTextFieldTests.swift b/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/CVVTextFieldTests.swift index 63084dcd..29def1ec 100644 --- a/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/CVVTextFieldTests.swift +++ b/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/CVVTextFieldTests.swift @@ -107,4 +107,29 @@ class CVVTextFieldTests: VGSCollectBaseTestCase { cardNumberTextField.focusOn() XCTAssert(cvvTextField.textField.formatPattern == "####", "Default format is wrong. Should be ####") } + + /// Test accessibility properties + func testAccessibilityAttributes() { + // Hint + let accHint = "accessibility hint" + cvvTextField.textFieldAccessibilityHint = accHint + XCTAssertNotNil(cvvTextField.textFieldAccessibilityHint) + XCTAssertEqual(cvvTextField.textFieldAccessibilityHint, accHint) + + // Label + let accLabel = "accessibility label" + cvvTextField.textFieldAccessibilityLabel = accLabel + XCTAssertNotNil(cvvTextField.textFieldAccessibilityLabel) + XCTAssertEqual(cvvTextField.textFieldAccessibilityLabel, accLabel) + + // Element + cvvTextField.textFieldIsAccessibilityElement = true + XCTAssertTrue(cvvTextField.textFieldIsAccessibilityElement) + + // Value + let accValue = "accessibility value" + cvvTextField.textField.secureText = accValue + XCTAssertTrue(cvvTextField.textField.secureText!.isEmpty) + XCTAssertNil(cvvTextField.textField.accessibilityValue) + } } diff --git a/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/CardHolderNameFieldTests.swift b/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/CardHolderNameFieldTests.swift index 834648d6..6d064e05 100644 --- a/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/CardHolderNameFieldTests.swift +++ b/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/CardHolderNameFieldTests.swift @@ -100,4 +100,29 @@ class CardHolderNameFieldTests: VGSCollectBaseTestCase { XCTAssertFalse(cardHolderTextField.state.isValid) XCTAssertFalse(cardHolderTextField.state.isEmpty) } + + /// Test accessibility properties + func testAccessibilityAttributes() { + // Hint + let accHint = "accessibility hint" + cardHolderTextField.textFieldAccessibilityHint = accHint + XCTAssertNotNil(cardHolderTextField.textFieldAccessibilityHint) + XCTAssertEqual(cardHolderTextField.textFieldAccessibilityHint, accHint) + + // Label + let accLabel = "accessibility label" + cardHolderTextField.textFieldAccessibilityLabel = accLabel + XCTAssertNotNil(cardHolderTextField.textFieldAccessibilityLabel) + XCTAssertEqual(cardHolderTextField.textFieldAccessibilityLabel, accLabel) + + // Element + cardHolderTextField.textFieldIsAccessibilityElement = true + XCTAssertTrue(cardHolderTextField.textFieldIsAccessibilityElement) + + // Value + let accValue = "accessibility value" + cardHolderTextField.textField.secureText = accValue + XCTAssertFalse(cardHolderTextField.textField.secureText!.isEmpty) + XCTAssertNil(cardHolderTextField.textField.accessibilityValue) + } } diff --git a/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/CardNumerTextFieldTests.swift b/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/CardNumerTextFieldTests.swift index 2e25d180..fcab9ee9 100644 --- a/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/CardNumerTextFieldTests.swift +++ b/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/CardNumerTextFieldTests.swift @@ -308,4 +308,29 @@ class CardNumerTextFieldTests: VGSCollectBaseTestCase { } } } + + /// Test accessibility properties + func testAccessibilityAttributes() { + // Hint + let accHint = "accessibility hint" + cardNumerTextField.textFieldAccessibilityHint = accHint + XCTAssertNotNil(cardNumerTextField.textFieldAccessibilityHint) + XCTAssertEqual(cardNumerTextField.textFieldAccessibilityHint, accHint) + + // Label + let accLabel = "accessibility label" + cardNumerTextField.textFieldAccessibilityLabel = accLabel + XCTAssertNotNil(cardNumerTextField.textFieldAccessibilityLabel) + XCTAssertEqual(cardNumerTextField.textFieldAccessibilityLabel, accLabel) + + // Element + cardNumerTextField.textFieldIsAccessibilityElement = true + XCTAssertTrue(cardNumerTextField.textFieldIsAccessibilityElement) + + // Value + let accValue = "accessibility value" + cardNumerTextField.textField.secureText = accValue + XCTAssertTrue(cardNumerTextField.textField.secureText!.isEmpty) + XCTAssertNil(cardNumerTextField.textField.accessibilityValue) + } } diff --git a/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/DateTextFieldTest.swift b/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/DateTextFieldTest.swift index 8b48fb37..fe86aa04 100644 --- a/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/DateTextFieldTest.swift +++ b/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/DateTextFieldTest.swift @@ -222,4 +222,29 @@ class DateTextFieldTest: VGSCollectBaseTestCase { XCTAssertTrue(textField.textField.inputView != nil, "Date picker not set!") XCTAssertTrue(textField.textField.inputView is UIPickerView, "Wrong date picker view!") } + + /// Test accessibility properties + func testAccessibilityAttributes() { + // Hint + let accHint = "accessibility hint" + textField.textFieldAccessibilityHint = accHint + XCTAssertNotNil(textField.textFieldAccessibilityHint) + XCTAssertEqual(textField.textFieldAccessibilityHint, accHint) + + // Label + let accLabel = "accessibility label" + textField.textFieldAccessibilityLabel = accLabel + XCTAssertNotNil(textField.textFieldAccessibilityLabel) + XCTAssertEqual(textField.textFieldAccessibilityLabel, accLabel) + + // Element + textField.textFieldIsAccessibilityElement = true + XCTAssertTrue(textField.textFieldIsAccessibilityElement) + + // Value + let accValue = "accessibility value" + textField.textField.secureText = accValue + XCTAssertTrue(textField.textField.secureText!.isEmpty) + XCTAssertNil(textField.textField.accessibilityValue) + } } diff --git a/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/ExpDateTextField.swift b/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/ExpDateTextField.swift index 12674c8c..732cf69c 100644 --- a/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/ExpDateTextField.swift +++ b/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/ExpDateTextField.swift @@ -102,4 +102,29 @@ class ExpDateTextField: VGSCollectBaseTestCase { XCTAssertTrue(textField.textField.inputView != nil, "Date picker not set!") XCTAssertTrue(textField.textField.inputView is UIPickerView, "Wrong date picker view!") } + + /// Test accessibility properties + func testAccessibilityAttributes() { + // Hint + let accHint = "accessibility hint" + textField.textFieldAccessibilityHint = accHint + XCTAssertNotNil(textField.textFieldAccessibilityHint) + XCTAssertEqual(textField.textFieldAccessibilityHint, accHint) + + // Label + let accLabel = "accessibility label" + textField.textFieldAccessibilityLabel = accLabel + XCTAssertNotNil(textField.textFieldAccessibilityLabel) + XCTAssertEqual(textField.textFieldAccessibilityLabel, accLabel) + + // Element + textField.textFieldIsAccessibilityElement = true + XCTAssertTrue(textField.textFieldIsAccessibilityElement) + + // Value + let accValue = "accessibility value" + textField.textField.secureText = accValue + XCTAssertTrue(textField.textField.secureText!.isEmpty) + XCTAssertNil(textField.textField.accessibilityValue) + } } diff --git a/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/SSNTextFieldTests.swift b/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/SSNTextFieldTests.swift index 2863188f..a62b79b3 100644 --- a/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/SSNTextFieldTests.swift +++ b/Tests/FrameworkTests/Satellite Tests/Text Fields Tests/SSNTextFieldTests.swift @@ -102,4 +102,29 @@ class SSNTextFieldTests: VGSCollectBaseTestCase { } } } + + /// Test accessibility properties + func testAccessibilityAttributes() { + // Hint + let accHint = "accessibility hint" + ssnTextField.textFieldAccessibilityHint = accHint + XCTAssertNotNil(ssnTextField.textFieldAccessibilityHint) + XCTAssertEqual(ssnTextField.textFieldAccessibilityHint, accHint) + + // Label + let accLabel = "accessibility label" + ssnTextField.textFieldAccessibilityLabel = accLabel + XCTAssertNotNil(ssnTextField.textFieldAccessibilityLabel) + XCTAssertEqual(ssnTextField.textFieldAccessibilityLabel, accLabel) + + // Element + ssnTextField.textFieldIsAccessibilityElement = true + XCTAssertTrue(ssnTextField.textFieldIsAccessibilityElement) + + // Value + let accValue = "accessibility value" + ssnTextField.textField.secureText = accValue + XCTAssertTrue(ssnTextField.textField.secureText!.isEmpty) + XCTAssertNil(ssnTextField.textField.accessibilityValue) + } } diff --git a/demoapp/demoapp.xcodeproj/project.pbxproj b/demoapp/demoapp.xcodeproj/project.pbxproj index 3a5c6e16..5b87f370 100644 --- a/demoapp/demoapp.xcodeproj/project.pbxproj +++ b/demoapp/demoapp.xcodeproj/project.pbxproj @@ -132,6 +132,7 @@ 971F95F0CD23156BC2F071A3 /* Pods-demoappUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-demoappUITests.release.xcconfig"; path = "Target Support Files/Pods-demoappUITests/Pods-demoappUITests.release.xcconfig"; sourceTree = ""; }; 9E14BE9AC3107988B3A45EBF /* Pods-demoapp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-demoapp.release.xcconfig"; path = "Target Support Files/Pods-demoapp/Pods-demoapp.release.xcconfig"; sourceTree = ""; }; A01CE3F429E5C50D0059700F /* DateValidationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateValidationViewController.swift; sourceTree = ""; }; + A06681532A58BB6500B93FC6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/LaunchScreen.strings; sourceTree = ""; }; B96EAC87AAF5BF889451003A /* Pods-demoapp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-demoapp.debug.xcconfig"; path = "Target Support Files/Pods-demoapp/Pods-demoapp.debug.xcconfig"; sourceTree = ""; }; C0DAC2D9D525DA573788F57B /* Pods_demoapp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_demoapp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; FD12B9742304616C00B670DD /* demoapp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = demoapp.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -145,7 +146,6 @@ FD12B9992304616E00B670DD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; FDD398EF247D7A7100B55057 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; FDD398F2247D7A7C00B55057 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - FDD398F4247D877800B55057 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/LaunchScreen.strings; sourceTree = ""; }; FDD398F6247D877900B55057 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/LaunchScreen.strings; sourceTree = ""; }; /* End PBXFileReference section */ @@ -779,8 +779,8 @@ isa = PBXVariantGroup; children = ( FDD398F2247D7A7C00B55057 /* Base */, - FDD398F4247D877800B55057 /* en */, FDD398F6247D877900B55057 /* ar */, + A06681532A58BB6500B93FC6 /* en */, ); name = LaunchScreen.storyboard; sourceTree = ""; diff --git a/demoapp/demoapp/UseCases/CardsDataCollectingViewController.swift b/demoapp/demoapp/UseCases/CardsDataCollectingViewController.swift index fee3cfcb..9f59f3ef 100644 --- a/demoapp/demoapp/UseCases/CardsDataCollectingViewController.swift +++ b/demoapp/demoapp/UseCases/CardsDataCollectingViewController.swift @@ -149,7 +149,6 @@ class CardsDataCollectingViewController: UIViewController { vgsCollect.textFields.forEach { textField in textField.textColor = UIColor.inputBlackTextColor - textField.font = .systemFont(ofSize: 22) textField.padding = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8) textField.tintColor = .lightGray /// Implement VGSTextFieldDelegate methods diff --git a/demoapp/demoapp/UseCases/CardsDataTokenizationViewController.swift b/demoapp/demoapp/UseCases/CardsDataTokenizationViewController.swift index 1d0e9b64..2c0107df 100644 --- a/demoapp/demoapp/UseCases/CardsDataTokenizationViewController.swift +++ b/demoapp/demoapp/UseCases/CardsDataTokenizationViewController.swift @@ -118,7 +118,6 @@ class CardsDataTokenizationViewController: UIViewController { vgsCollect.textFields.forEach { textField in textField.textColor = UIColor.inputBlackTextColor - textField.font = .systemFont(ofSize: 22) textField.padding = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8) textField.tintColor = .lightGray /// Implement VGSTextFieldDelegate methods diff --git a/demoapp/demoapp/UseCases/CombineExamplesViewController.swift b/demoapp/demoapp/UseCases/CombineExamplesViewController.swift index 27099d00..32e85777 100644 --- a/demoapp/demoapp/UseCases/CombineExamplesViewController.swift +++ b/demoapp/demoapp/UseCases/CombineExamplesViewController.swift @@ -170,7 +170,6 @@ class CombineExamplesViewController: UIViewController { vgsCollect.textFields.forEach { textField in textField.textColor = UIColor.inputBlackTextColor - textField.font = .systemFont(ofSize: 22) textField.padding = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8) textField.tintColor = .lightGray } diff --git a/demoapp/demoapp/UseCases/CustomDataCollectingViewController.swift b/demoapp/demoapp/UseCases/CustomDataCollectingViewController.swift index 7e672d45..fb48dae2 100644 --- a/demoapp/demoapp/UseCases/CustomDataCollectingViewController.swift +++ b/demoapp/demoapp/UseCases/CustomDataCollectingViewController.swift @@ -91,7 +91,6 @@ class CustomDataCollectingViewController: UIViewController { customDataField.textAlignment = .center customDataField.textColor = UIColor.inputBlackTextColor - customDataField.font = .systemFont(ofSize: 22) customDataField.padding = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8) customDataField.tintColor = .lightGray customDataField.delegate = self diff --git a/demoapp/demoapp/UseCases/CustomPaymentCardsViewController.swift b/demoapp/demoapp/UseCases/CustomPaymentCardsViewController.swift index 02b7dfcb..ad0dc851 100644 --- a/demoapp/demoapp/UseCases/CustomPaymentCardsViewController.swift +++ b/demoapp/demoapp/UseCases/CustomPaymentCardsViewController.swift @@ -173,7 +173,6 @@ class CustomPaymentCardsViewController: UIViewController { vgsCollect.textFields.forEach { textField in textField.textColor = UIColor.inputBlackTextColor - textField.font = .systemFont(ofSize: 22) textField.padding = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8) textField.tintColor = .lightGray textField.delegate = self diff --git a/demoapp/demoapp/UseCases/DateValidationViewController.swift b/demoapp/demoapp/UseCases/DateValidationViewController.swift index 11f20738..fe089112 100644 --- a/demoapp/demoapp/UseCases/DateValidationViewController.swift +++ b/demoapp/demoapp/UseCases/DateValidationViewController.swift @@ -114,10 +114,12 @@ private extension DateValidationViewController { dateField.placeholder = "MM-DD-YYYY" dateField.monthPickerFormat = .longSymbols + // Setup accessibility + dateField.textFieldAccessibilityLabel = "expiration date input" + /// Add logging vgsCollect.textFields.forEach { textField in textField.textColor = UIColor.inputBlackTextColor - textField.font = .systemFont(ofSize: 22) textField.padding = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8) textField.tintColor = .lightGray /// Implement VGSTextFieldDelegate methods diff --git a/demoapp/demoapp/UseCases/SSNCollectingViewController.swift b/demoapp/demoapp/UseCases/SSNCollectingViewController.swift index df21e91b..077cdb5d 100644 --- a/demoapp/demoapp/UseCases/SSNCollectingViewController.swift +++ b/demoapp/demoapp/UseCases/SSNCollectingViewController.swift @@ -86,7 +86,6 @@ class SSNCollectingViewController: UIViewController { ssnField.textAlignment = .center ssnField.textColor = UIColor.inputBlackTextColor - ssnField.font = .systemFont(ofSize: 22) ssnField.padding = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8) ssnField.tintColor = .lightGray ssnField.delegate = self From 4a71e61752bcba0bd72a256c02963285a14d34e4 Mon Sep 17 00:00:00 2001 From: Donald Rodriguez Gutierrez <129230521+DonaldRG@users.noreply.github.com> Date: Wed, 19 Jul 2023 09:41:25 -0600 Subject: [PATCH 4/4] Bump SDK version and update internal docs (#355) --- .../Utils/Extensions/Utils.swift | 2 +- VGSCollectSDK.podspec | 2 +- VGSCollectSDK.xcodeproj/project.pbxproj | 4 +- docs/Classes/CardState.html | 2 +- docs/Classes/SSNState.html | 2 +- docs/Classes/State.html | 2 +- docs/Classes/VGSCVCTextField.html | 2 +- .../VGSCVCTextField/CVCIconLocation.html | 2 +- .../VGSCVCTokenizationConfiguration.html | 2 +- ...rdHolderNameTokenizationConfiguration.html | 2 +- ...GSCardNumberTokenizationConfiguration.html | 2 +- docs/Classes/VGSCardTextField.html | 2 +- .../VGSCardTextField/CardIconLocation.html | 2 +- docs/Classes/VGSCollect.html | 2 +- docs/Classes/VGSCollectLogger.html | 2 +- docs/Classes/VGSConfiguration.html | 2 +- docs/Classes/VGSDateConfiguration.html | 2 +- docs/Classes/VGSDateTextField.html | 2 +- .../Classes/VGSDateTextField/MonthFormat.html | 2 +- .../VGSDateTokenizationConfiguration.html | 2 +- docs/Classes/VGSError.html | 2 +- docs/Classes/VGSExpDateConfiguration.html | 2 +- docs/Classes/VGSExpDateTextField.html | 10 +-- .../VGSExpDateTextField/MonthFormat.html | 2 +- .../VGSExpDateTextField/YearFormat.html | 2 +- .../VGSExpDateTokenizationConfiguration.html | 2 +- docs/Classes/VGSFileInfo.html | 2 +- docs/Classes/VGSFilePickerConfiguration.html | 2 +- docs/Classes/VGSFilePickerController.html | 2 +- docs/Classes/VGSPaymentCards.html | 2 +- docs/Classes/VGSPaymentCards/CardBrand.html | 2 +- .../VGSSSNTokenizationConfiguration.html | 2 +- docs/Classes/VGSTextField.html | 70 ++++++++++++++---- .../Classes/VGSTokenizationConfiguration.html | 2 +- docs/Debugging.html | 2 +- docs/Enumerations.html | 2 +- docs/Enums/CheckSumAlgorithmType.html | 2 +- docs/Enums/Environment.html | 2 +- docs/Enums/FieldType.html | 2 +- docs/Enums/VGSCardExpDateFormat.html | 2 +- .../VGSCollectFieldNameMappingPolicy.html | 2 +- docs/Enums/VGSCollectHTTPMethod.html | 2 +- docs/Enums/VGSDateFormat.html | 8 +- docs/Enums/VGSErrorType.html | 2 +- docs/Enums/VGSFileSource.html | 2 +- docs/Enums/VGSLogLevel.html | 2 +- docs/Enums/VGSResponse.html | 2 +- docs/Enums/VGSTextFieldInputSource.html | 2 +- docs/Enums/VGSTokenizationResponse.html | 2 +- docs/Enums/VGSValidationErrorType.html | 2 +- docs/Enums/VGSVaultAliasFormat.html | 2 +- docs/Enums/VGSVaultStorageType.html | 2 +- docs/Error Keys.html | 2 +- docs/Errors.html | 2 +- docs/File Picker.html | 2 +- docs/Observe State and Send Data.html | 2 +- docs/Payment Cards.html | 2 +- .../VGSDateConfigurationProtocol.html | 2 +- .../VGSExpDateConfigurationProtocol.html | 2 +- .../VGSFilePickerControllerDelegate.html | 2 +- docs/Protocols/VGSTextFieldDelegate.html | 2 +- .../VGSTokenizationParametersProtocol.html | 2 +- .../Structs/VGSCVCTokenizationParameters.html | 2 +- ...SCardHolderNameTokenizationParameters.html | 2 +- .../VGSCardNumberTokenizationParameters.html | 2 +- .../VGSCollectLoggingConfiguration.html | 2 +- docs/Structs/VGSCollectRequestOptions.html | 2 +- docs/Structs/VGSCustomPaymentCardModel.html | 2 +- docs/Structs/VGSDate.html | 2 +- .../VGSDateTokenizationParameters.html | 2 +- .../Structs/VGSExpDateSeparateSerializer.html | 2 +- .../VGSExpDateTokenizationParameters.html | 2 +- docs/Structs/VGSPaymentCardModel.html | 2 +- .../Structs/VGSSSNTokenizationParameters.html | 2 +- docs/Structs/VGSTextFieldStatePublisher.html | 2 +- docs/Structs/VGSTokenizationParameters.html | 2 +- docs/Structs/VGSUnknownPaymentCardModel.html | 2 +- .../VGSValidationRuleCardExpirationDate.html | 2 +- docs/Structs/VGSValidationRuleDateRange.html | 2 +- docs/Structs/VGSValidationRuleLength.html | 2 +- .../Structs/VGSValidationRuleLengthMatch.html | 2 +- docs/Structs/VGSValidationRuleLuhnCheck.html | 2 +- docs/Structs/VGSValidationRulePattern.html | 2 +- .../Structs/VGSValidationRulePaymentCard.html | 2 +- docs/Structs/VGSValidationRuleSet.html | 2 +- docs/Tokenization Parameters.html | 2 +- docs/UI Elements.html | 6 +- docs/VGSTextField Serializers.html | 2 +- docs/Validation Rules.html | 2 +- .../Documents/Classes/CardState.html | 2 +- .../Resources/Documents/Classes/SSNState.html | 2 +- .../Resources/Documents/Classes/State.html | 2 +- .../Documents/Classes/VGSCVCTextField.html | 2 +- .../VGSCVCTextField/CVCIconLocation.html | 2 +- .../VGSCVCTokenizationConfiguration.html | 2 +- ...rdHolderNameTokenizationConfiguration.html | 2 +- ...GSCardNumberTokenizationConfiguration.html | 2 +- .../Documents/Classes/VGSCardTextField.html | 2 +- .../VGSCardTextField/CardIconLocation.html | 2 +- .../Documents/Classes/VGSCollect.html | 2 +- .../Documents/Classes/VGSCollectLogger.html | 2 +- .../Documents/Classes/VGSConfiguration.html | 2 +- .../Classes/VGSDateConfiguration.html | 2 +- .../Documents/Classes/VGSDateTextField.html | 2 +- .../Classes/VGSDateTextField/MonthFormat.html | 2 +- .../VGSDateTokenizationConfiguration.html | 2 +- .../Resources/Documents/Classes/VGSError.html | 2 +- .../Classes/VGSExpDateConfiguration.html | 2 +- .../Classes/VGSExpDateTextField.html | 10 +-- .../VGSExpDateTextField/MonthFormat.html | 2 +- .../VGSExpDateTextField/YearFormat.html | 2 +- .../VGSExpDateTokenizationConfiguration.html | 2 +- .../Documents/Classes/VGSFileInfo.html | 2 +- .../Classes/VGSFilePickerConfiguration.html | 2 +- .../Classes/VGSFilePickerController.html | 2 +- .../Documents/Classes/VGSPaymentCards.html | 2 +- .../Classes/VGSPaymentCards/CardBrand.html | 2 +- .../VGSSSNTokenizationConfiguration.html | 2 +- .../Documents/Classes/VGSTextField.html | 70 ++++++++++++++---- .../Classes/VGSTokenizationConfiguration.html | 2 +- .../Resources/Documents/Debugging.html | 2 +- .../Resources/Documents/Enumerations.html | 2 +- .../Enums/CheckSumAlgorithmType.html | 2 +- .../Documents/Enums/Environment.html | 2 +- .../Resources/Documents/Enums/FieldType.html | 2 +- .../Documents/Enums/VGSCardExpDateFormat.html | 2 +- .../VGSCollectFieldNameMappingPolicy.html | 2 +- .../Documents/Enums/VGSCollectHTTPMethod.html | 2 +- .../Documents/Enums/VGSDateFormat.html | 8 +- .../Documents/Enums/VGSErrorType.html | 2 +- .../Documents/Enums/VGSFileSource.html | 2 +- .../Documents/Enums/VGSLogLevel.html | 2 +- .../Documents/Enums/VGSResponse.html | 2 +- .../Enums/VGSTextFieldInputSource.html | 2 +- .../Enums/VGSTokenizationResponse.html | 2 +- .../Enums/VGSValidationErrorType.html | 2 +- .../Documents/Enums/VGSVaultAliasFormat.html | 2 +- .../Documents/Enums/VGSVaultStorageType.html | 2 +- .../Resources/Documents/Error Keys.html | 2 +- .../Contents/Resources/Documents/Errors.html | 2 +- .../Resources/Documents/File Picker.html | 2 +- .../Observe State and Send Data.html | 2 +- .../Resources/Documents/Payment Cards.html | 2 +- .../VGSDateConfigurationProtocol.html | 2 +- .../VGSExpDateConfigurationProtocol.html | 2 +- .../VGSFilePickerControllerDelegate.html | 2 +- .../Protocols/VGSTextFieldDelegate.html | 2 +- .../VGSTokenizationParametersProtocol.html | 2 +- .../Structs/VGSCVCTokenizationParameters.html | 2 +- ...SCardHolderNameTokenizationParameters.html | 2 +- .../VGSCardNumberTokenizationParameters.html | 2 +- .../VGSCollectLoggingConfiguration.html | 2 +- .../Structs/VGSCollectRequestOptions.html | 2 +- .../Structs/VGSCustomPaymentCardModel.html | 2 +- .../Resources/Documents/Structs/VGSDate.html | 2 +- .../VGSDateTokenizationParameters.html | 2 +- .../Structs/VGSExpDateSeparateSerializer.html | 2 +- .../VGSExpDateTokenizationParameters.html | 2 +- .../Structs/VGSPaymentCardModel.html | 2 +- .../Structs/VGSSSNTokenizationParameters.html | 2 +- .../Structs/VGSTextFieldStatePublisher.html | 2 +- .../Structs/VGSTokenizationParameters.html | 2 +- .../Structs/VGSUnknownPaymentCardModel.html | 2 +- .../VGSValidationRuleCardExpirationDate.html | 2 +- .../Structs/VGSValidationRuleDateRange.html | 2 +- .../Structs/VGSValidationRuleLength.html | 2 +- .../Structs/VGSValidationRuleLengthMatch.html | 2 +- .../Structs/VGSValidationRuleLuhnCheck.html | 2 +- .../Structs/VGSValidationRulePattern.html | 2 +- .../Structs/VGSValidationRulePaymentCard.html | 2 +- .../Structs/VGSValidationRuleSet.html | 2 +- .../Documents/Tokenization Parameters.html | 2 +- .../Resources/Documents/UI Elements.html | 6 +- .../Documents/VGSTextField Serializers.html | 2 +- .../Resources/Documents/Validation Rules.html | 2 +- .../Contents/Resources/Documents/index.html | 6 +- .../Contents/Resources/Documents/search.json | 2 +- .../Contents/Resources/docSet.dsidx | Bin 131072 -> 131072 bytes docs/docsets/VGSCollectSDK.tgz | Bin 242816 -> 242980 bytes docs/index.html | 6 +- docs/search.json | 2 +- docs/undocumented.json | 6 +- 182 files changed, 315 insertions(+), 231 deletions(-) diff --git a/Sources/VGSCollectSDK/Utils/Extensions/Utils.swift b/Sources/VGSCollectSDK/Utils/Extensions/Utils.swift index defc0aef..42073477 100644 --- a/Sources/VGSCollectSDK/Utils/Extensions/Utils.swift +++ b/Sources/VGSCollectSDK/Utils/Extensions/Utils.swift @@ -46,7 +46,7 @@ internal class Utils { /// VGS Collect SDK Version. /// Necessary since SPM doesn't track info plist correctly: https://forums.swift.org/t/add-info-plist-on-spm-bundle/40274/5 - static let vgsCollectVersion: String = "1.14.0" + static let vgsCollectVersion: String = "1.15.0" } extension Dictionary { diff --git a/VGSCollectSDK.podspec b/VGSCollectSDK.podspec index 4528b3ec..3e1b594c 100644 --- a/VGSCollectSDK.podspec +++ b/VGSCollectSDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'VGSCollectSDK' - spec.version = '1.14.0' + spec.version = '1.15.0' spec.summary = 'VGS Collect - is a product suite that allows customers to collect information securely without possession of it.' spec.swift_version = '5.0' spec.description = <<-DESC diff --git a/VGSCollectSDK.xcodeproj/project.pbxproj b/VGSCollectSDK.xcodeproj/project.pbxproj index 28806752..c7f09a70 100644 --- a/VGSCollectSDK.xcodeproj/project.pbxproj +++ b/VGSCollectSDK.xcodeproj/project.pbxproj @@ -2045,7 +2045,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.12.0; + MARKETING_VERSION = 1.15.0; PRODUCT_BUNDLE_IDENTIFIER = com.vgs.framework; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2077,7 +2077,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.12.0; + MARKETING_VERSION = 1.15.0; PRODUCT_BUNDLE_IDENTIFIER = com.vgs.framework; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/docs/Classes/CardState.html b/docs/Classes/CardState.html index 7f3f558c..730ab5fd 100644 --- a/docs/Classes/CardState.html +++ b/docs/Classes/CardState.html @@ -523,7 +523,7 @@

Declaration

diff --git a/docs/Classes/SSNState.html b/docs/Classes/SSNState.html index 8f695bee..ebb68d25 100644 --- a/docs/Classes/SSNState.html +++ b/docs/Classes/SSNState.html @@ -463,7 +463,7 @@

Declaration

diff --git a/docs/Classes/State.html b/docs/Classes/State.html index b4761360..aa4703ea 100644 --- a/docs/Classes/State.html +++ b/docs/Classes/State.html @@ -673,7 +673,7 @@

Declaration

diff --git a/docs/Classes/VGSCVCTextField.html b/docs/Classes/VGSCVCTextField.html index be69d3bf..5097c085 100644 --- a/docs/Classes/VGSCVCTextField.html +++ b/docs/Classes/VGSCVCTextField.html @@ -559,7 +559,7 @@

Declaration

diff --git a/docs/Classes/VGSCVCTextField/CVCIconLocation.html b/docs/Classes/VGSCVCTextField/CVCIconLocation.html index f7357ce7..a6ef8bb4 100644 --- a/docs/Classes/VGSCVCTextField/CVCIconLocation.html +++ b/docs/Classes/VGSCVCTextField/CVCIconLocation.html @@ -463,7 +463,7 @@

Declaration

diff --git a/docs/Classes/VGSCVCTokenizationConfiguration.html b/docs/Classes/VGSCVCTokenizationConfiguration.html index 448faf60..91327dc4 100644 --- a/docs/Classes/VGSCVCTokenizationConfiguration.html +++ b/docs/Classes/VGSCVCTokenizationConfiguration.html @@ -463,7 +463,7 @@

Declaration

diff --git a/docs/Classes/VGSCardHolderNameTokenizationConfiguration.html b/docs/Classes/VGSCardHolderNameTokenizationConfiguration.html index a6eac2ba..921f28ad 100644 --- a/docs/Classes/VGSCardHolderNameTokenizationConfiguration.html +++ b/docs/Classes/VGSCardHolderNameTokenizationConfiguration.html @@ -463,7 +463,7 @@

Declaration

diff --git a/docs/Classes/VGSCardNumberTokenizationConfiguration.html b/docs/Classes/VGSCardNumberTokenizationConfiguration.html index f35f52d1..f2d58e61 100644 --- a/docs/Classes/VGSCardNumberTokenizationConfiguration.html +++ b/docs/Classes/VGSCardNumberTokenizationConfiguration.html @@ -463,7 +463,7 @@

Declaration

diff --git a/docs/Classes/VGSCardTextField.html b/docs/Classes/VGSCardTextField.html index ac1e17ce..340f3e8d 100644 --- a/docs/Classes/VGSCardTextField.html +++ b/docs/Classes/VGSCardTextField.html @@ -559,7 +559,7 @@

Declaration

diff --git a/docs/Classes/VGSCardTextField/CardIconLocation.html b/docs/Classes/VGSCardTextField/CardIconLocation.html index 3a7ca7be..d5895dcb 100644 --- a/docs/Classes/VGSCardTextField/CardIconLocation.html +++ b/docs/Classes/VGSCardTextField/CardIconLocation.html @@ -463,7 +463,7 @@

Declaration

diff --git a/docs/Classes/VGSCollect.html b/docs/Classes/VGSCollect.html index 81178585..9fabca01 100644 --- a/docs/Classes/VGSCollect.html +++ b/docs/Classes/VGSCollect.html @@ -1841,7 +1841,7 @@

Return Value

diff --git a/docs/Classes/VGSCollectLogger.html b/docs/Classes/VGSCollectLogger.html index ee15b418..fbaeb37a 100644 --- a/docs/Classes/VGSCollectLogger.html +++ b/docs/Classes/VGSCollectLogger.html @@ -516,7 +516,7 @@

Declaration

diff --git a/docs/Classes/VGSConfiguration.html b/docs/Classes/VGSConfiguration.html index 583dd239..da7d175f 100644 --- a/docs/Classes/VGSConfiguration.html +++ b/docs/Classes/VGSConfiguration.html @@ -846,7 +846,7 @@

Parameters

diff --git a/docs/Classes/VGSDateConfiguration.html b/docs/Classes/VGSDateConfiguration.html index 4c11627b..1d77db68 100644 --- a/docs/Classes/VGSDateConfiguration.html +++ b/docs/Classes/VGSDateConfiguration.html @@ -750,7 +750,7 @@

Declaration

diff --git a/docs/Classes/VGSDateTextField.html b/docs/Classes/VGSDateTextField.html index b5c0f2c5..c80623d9 100644 --- a/docs/Classes/VGSDateTextField.html +++ b/docs/Classes/VGSDateTextField.html @@ -529,7 +529,7 @@

Declaration

diff --git a/docs/Classes/VGSDateTextField/MonthFormat.html b/docs/Classes/VGSDateTextField/MonthFormat.html index 3709f8c8..c1a86151 100644 --- a/docs/Classes/VGSDateTextField/MonthFormat.html +++ b/docs/Classes/VGSDateTextField/MonthFormat.html @@ -493,7 +493,7 @@

Declaration

diff --git a/docs/Classes/VGSDateTokenizationConfiguration.html b/docs/Classes/VGSDateTokenizationConfiguration.html index 50e491e7..c97572f8 100644 --- a/docs/Classes/VGSDateTokenizationConfiguration.html +++ b/docs/Classes/VGSDateTokenizationConfiguration.html @@ -648,7 +648,7 @@

Declaration

diff --git a/docs/Classes/VGSError.html b/docs/Classes/VGSError.html index a49b05dc..e7d0c9f8 100644 --- a/docs/Classes/VGSError.html +++ b/docs/Classes/VGSError.html @@ -493,7 +493,7 @@

Declaration

diff --git a/docs/Classes/VGSExpDateConfiguration.html b/docs/Classes/VGSExpDateConfiguration.html index 8939dcfd..981c1e7e 100644 --- a/docs/Classes/VGSExpDateConfiguration.html +++ b/docs/Classes/VGSExpDateConfiguration.html @@ -588,7 +588,7 @@

Declaration

diff --git a/docs/Classes/VGSExpDateTextField.html b/docs/Classes/VGSExpDateTextField.html index c61d6c83..1d655e0d 100644 --- a/docs/Classes/VGSExpDateTextField.html +++ b/docs/Classes/VGSExpDateTextField.html @@ -513,9 +513,9 @@

Declaration

  • @@ -530,7 +530,7 @@

    Declaration

    Declaration

    Swift

    -
    public var yearPickeFormat: YearFormat { get set }
    +
    public var yearPickerFormat: YearFormat { get set }
    @@ -548,7 +548,7 @@

    Declaration

    diff --git a/docs/Classes/VGSExpDateTextField/MonthFormat.html b/docs/Classes/VGSExpDateTextField/MonthFormat.html index 99480171..89008db4 100644 --- a/docs/Classes/VGSExpDateTextField/MonthFormat.html +++ b/docs/Classes/VGSExpDateTextField/MonthFormat.html @@ -493,7 +493,7 @@

    Declaration

    diff --git a/docs/Classes/VGSExpDateTextField/YearFormat.html b/docs/Classes/VGSExpDateTextField/YearFormat.html index 796dd565..2accfc02 100644 --- a/docs/Classes/VGSExpDateTextField/YearFormat.html +++ b/docs/Classes/VGSExpDateTextField/YearFormat.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/Classes/VGSExpDateTokenizationConfiguration.html b/docs/Classes/VGSExpDateTokenizationConfiguration.html index d4690f3d..2fcf10f5 100644 --- a/docs/Classes/VGSExpDateTokenizationConfiguration.html +++ b/docs/Classes/VGSExpDateTokenizationConfiguration.html @@ -631,7 +631,7 @@

    Declaration

    diff --git a/docs/Classes/VGSFileInfo.html b/docs/Classes/VGSFileInfo.html index a8563c52..79ebe753 100644 --- a/docs/Classes/VGSFileInfo.html +++ b/docs/Classes/VGSFileInfo.html @@ -498,7 +498,7 @@

    Declaration

    diff --git a/docs/Classes/VGSFilePickerConfiguration.html b/docs/Classes/VGSFilePickerConfiguration.html index fc82cfb7..d5ab7396 100644 --- a/docs/Classes/VGSFilePickerConfiguration.html +++ b/docs/Classes/VGSFilePickerConfiguration.html @@ -528,7 +528,7 @@

    Parameters

    diff --git a/docs/Classes/VGSFilePickerController.html b/docs/Classes/VGSFilePickerController.html index 778c1ce4..8d7b7bcb 100644 --- a/docs/Classes/VGSFilePickerController.html +++ b/docs/Classes/VGSFilePickerController.html @@ -651,7 +651,7 @@

    Parameters

    diff --git a/docs/Classes/VGSPaymentCards.html b/docs/Classes/VGSPaymentCards.html index 2eb7c665..a3afb6bf 100644 --- a/docs/Classes/VGSPaymentCards.html +++ b/docs/Classes/VGSPaymentCards.html @@ -1051,7 +1051,7 @@

    Declaration

    diff --git a/docs/Classes/VGSPaymentCards/CardBrand.html b/docs/Classes/VGSPaymentCards/CardBrand.html index 8314c190..8038edd6 100644 --- a/docs/Classes/VGSPaymentCards/CardBrand.html +++ b/docs/Classes/VGSPaymentCards/CardBrand.html @@ -1016,7 +1016,7 @@

    Declaration

    diff --git a/docs/Classes/VGSSSNTokenizationConfiguration.html b/docs/Classes/VGSSSNTokenizationConfiguration.html index e3009be0..b2e2b207 100644 --- a/docs/Classes/VGSSSNTokenizationConfiguration.html +++ b/docs/Classes/VGSSSNTokenizationConfiguration.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/Classes/VGSTextField.html b/docs/Classes/VGSTextField.html index bb07559e..3e603e9b 100644 --- a/docs/Classes/VGSTextField.html +++ b/docs/Classes/VGSTextField.html @@ -387,7 +387,7 @@

    VGSTextField

    An object that displays an editable text area in user interface.

    @@ -735,6 +735,19 @@

    Declaration

  • + + +
    +
    + + +
    + +

    Accessibility Attributes +

    +
    +
    +
    • @@ -760,7 +773,7 @@

      Declaration

    @@ -778,7 +791,8 @@

    Declaration

    -

    A localized string that contains a brief description of the result of performing an action on the accessibility text field.

    +

    A localized string that contains a brief description of the result of +performing an action on the accessibility text field.

    @@ -790,7 +804,37 @@

    Declaration

    +
    + + +
  • + +
    +
    +
    +
    +
    +

    Boolean value that determinates if the text field should be exposed as an accesibility element.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var textFieldIsAccessibilityElement: Bool { get set }
    + +
    +
    +
    @@ -833,7 +877,7 @@

    Declaration

    @@ -863,7 +907,7 @@

    Declaration

    @@ -913,7 +957,7 @@

    Declaration

    @@ -943,7 +987,7 @@

    Declaration

    @@ -991,7 +1035,7 @@

    Declaration

    @@ -1245,7 +1289,7 @@

    Declaration

    @@ -1276,7 +1320,7 @@

    Declaration

    @@ -1306,7 +1350,7 @@

    Declaration

    @@ -1319,7 +1363,7 @@

    Declaration

    diff --git a/docs/Classes/VGSTokenizationConfiguration.html b/docs/Classes/VGSTokenizationConfiguration.html index 18a2a57d..19a6bba2 100644 --- a/docs/Classes/VGSTokenizationConfiguration.html +++ b/docs/Classes/VGSTokenizationConfiguration.html @@ -433,7 +433,7 @@

    Declaration

    diff --git a/docs/Debugging.html b/docs/Debugging.html index df867e6e..df4f5b15 100644 --- a/docs/Debugging.html +++ b/docs/Debugging.html @@ -486,7 +486,7 @@

    Declaration

    diff --git a/docs/Enumerations.html b/docs/Enumerations.html index 80f007a4..5642de01 100644 --- a/docs/Enumerations.html +++ b/docs/Enumerations.html @@ -454,7 +454,7 @@

    Declaration

    diff --git a/docs/Enums/CheckSumAlgorithmType.html b/docs/Enums/CheckSumAlgorithmType.html index 6cfd7bb5..a1b1f05d 100644 --- a/docs/Enums/CheckSumAlgorithmType.html +++ b/docs/Enums/CheckSumAlgorithmType.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/Enums/Environment.html b/docs/Enums/Environment.html index d290ae67..56826e1c 100644 --- a/docs/Enums/Environment.html +++ b/docs/Enums/Environment.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/Enums/FieldType.html b/docs/Enums/FieldType.html index d9b4f112..7ba21eec 100644 --- a/docs/Enums/FieldType.html +++ b/docs/Enums/FieldType.html @@ -613,7 +613,7 @@

    Declaration

    diff --git a/docs/Enums/VGSCardExpDateFormat.html b/docs/Enums/VGSCardExpDateFormat.html index 76f4ff1b..6b7a6d86 100644 --- a/docs/Enums/VGSCardExpDateFormat.html +++ b/docs/Enums/VGSCardExpDateFormat.html @@ -523,7 +523,7 @@

    Declaration

    diff --git a/docs/Enums/VGSCollectFieldNameMappingPolicy.html b/docs/Enums/VGSCollectFieldNameMappingPolicy.html index 7684b5e1..de418de6 100644 --- a/docs/Enums/VGSCollectFieldNameMappingPolicy.html +++ b/docs/Enums/VGSCollectFieldNameMappingPolicy.html @@ -601,7 +601,7 @@

    Declaration

    diff --git a/docs/Enums/VGSCollectHTTPMethod.html b/docs/Enums/VGSCollectHTTPMethod.html index e2a37d05..43ed6f4d 100644 --- a/docs/Enums/VGSCollectHTTPMethod.html +++ b/docs/Enums/VGSCollectHTTPMethod.html @@ -553,7 +553,7 @@

    Declaration

    diff --git a/docs/Enums/VGSDateFormat.html b/docs/Enums/VGSDateFormat.html index 51c97f75..00b1bfc6 100644 --- a/docs/Enums/VGSDateFormat.html +++ b/docs/Enums/VGSDateFormat.html @@ -386,7 +386,7 @@

    VGSDateFormat

    Format used to validate a VGS date text input

    @@ -420,7 +420,7 @@

    Declaration

    @@ -463,7 +463,7 @@

    Declaration

    @@ -476,7 +476,7 @@

    Declaration

    diff --git a/docs/Enums/VGSErrorType.html b/docs/Enums/VGSErrorType.html index abbde3d0..b8de703a 100644 --- a/docs/Enums/VGSErrorType.html +++ b/docs/Enums/VGSErrorType.html @@ -678,7 +678,7 @@

    Declaration

    diff --git a/docs/Enums/VGSFileSource.html b/docs/Enums/VGSFileSource.html index 42ac711e..4a0068ee 100644 --- a/docs/Enums/VGSFileSource.html +++ b/docs/Enums/VGSFileSource.html @@ -493,7 +493,7 @@

    Declaration

    diff --git a/docs/Enums/VGSLogLevel.html b/docs/Enums/VGSLogLevel.html index 72fb8657..308f28ef 100644 --- a/docs/Enums/VGSLogLevel.html +++ b/docs/Enums/VGSLogLevel.html @@ -493,7 +493,7 @@

    Declaration

    diff --git a/docs/Enums/VGSResponse.html b/docs/Enums/VGSResponse.html index 62b5171a..071b23ad 100644 --- a/docs/Enums/VGSResponse.html +++ b/docs/Enums/VGSResponse.html @@ -562,7 +562,7 @@

    Parameters

    diff --git a/docs/Enums/VGSTextFieldInputSource.html b/docs/Enums/VGSTextFieldInputSource.html index 875f0444..b84de93f 100644 --- a/docs/Enums/VGSTextFieldInputSource.html +++ b/docs/Enums/VGSTextFieldInputSource.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/Enums/VGSTokenizationResponse.html b/docs/Enums/VGSTokenizationResponse.html index 1bea722d..cff0f678 100644 --- a/docs/Enums/VGSTokenizationResponse.html +++ b/docs/Enums/VGSTokenizationResponse.html @@ -562,7 +562,7 @@

    Parameters

    diff --git a/docs/Enums/VGSValidationErrorType.html b/docs/Enums/VGSValidationErrorType.html index 5b8d6143..b1a5c9a0 100644 --- a/docs/Enums/VGSValidationErrorType.html +++ b/docs/Enums/VGSValidationErrorType.html @@ -613,7 +613,7 @@

    Declaration

    diff --git a/docs/Enums/VGSVaultAliasFormat.html b/docs/Enums/VGSVaultAliasFormat.html index 32beb7b5..2648e5b7 100644 --- a/docs/Enums/VGSVaultAliasFormat.html +++ b/docs/Enums/VGSVaultAliasFormat.html @@ -673,7 +673,7 @@

    Declaration

    diff --git a/docs/Enums/VGSVaultStorageType.html b/docs/Enums/VGSVaultStorageType.html index be51033c..e23a4e79 100644 --- a/docs/Enums/VGSVaultStorageType.html +++ b/docs/Enums/VGSVaultStorageType.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/Error Keys.html b/docs/Error Keys.html index 4ff7dd1f..dace0270 100644 --- a/docs/Error Keys.html +++ b/docs/Error Keys.html @@ -685,7 +685,7 @@

    Declaration

    diff --git a/docs/Errors.html b/docs/Errors.html index e49e3a5c..61722565 100644 --- a/docs/Errors.html +++ b/docs/Errors.html @@ -545,7 +545,7 @@

    Declaration

    diff --git a/docs/File Picker.html b/docs/File Picker.html index 60e9539c..df1f676e 100644 --- a/docs/File Picker.html +++ b/docs/File Picker.html @@ -548,7 +548,7 @@

    Declaration

    diff --git a/docs/Observe State and Send Data.html b/docs/Observe State and Send Data.html index fb390174..b813fea9 100644 --- a/docs/Observe State and Send Data.html +++ b/docs/Observe State and Send Data.html @@ -765,7 +765,7 @@

    Declaration

    diff --git a/docs/Payment Cards.html b/docs/Payment Cards.html index 5a70d9cc..85c3057a 100644 --- a/docs/Payment Cards.html +++ b/docs/Payment Cards.html @@ -522,7 +522,7 @@

    Declaration

    diff --git a/docs/Protocols/VGSDateConfigurationProtocol.html b/docs/Protocols/VGSDateConfigurationProtocol.html index 60e86959..07203603 100644 --- a/docs/Protocols/VGSDateConfigurationProtocol.html +++ b/docs/Protocols/VGSDateConfigurationProtocol.html @@ -493,7 +493,7 @@

    Declaration

    diff --git a/docs/Protocols/VGSExpDateConfigurationProtocol.html b/docs/Protocols/VGSExpDateConfigurationProtocol.html index 72e4aeae..80cefbaf 100644 --- a/docs/Protocols/VGSExpDateConfigurationProtocol.html +++ b/docs/Protocols/VGSExpDateConfigurationProtocol.html @@ -493,7 +493,7 @@

    Declaration

    diff --git a/docs/Protocols/VGSFilePickerControllerDelegate.html b/docs/Protocols/VGSFilePickerControllerDelegate.html index 4ea61309..21dd5a48 100644 --- a/docs/Protocols/VGSFilePickerControllerDelegate.html +++ b/docs/Protocols/VGSFilePickerControllerDelegate.html @@ -503,7 +503,7 @@

    Declaration

    diff --git a/docs/Protocols/VGSTextFieldDelegate.html b/docs/Protocols/VGSTextFieldDelegate.html index 51f2a1c2..1fb092fb 100644 --- a/docs/Protocols/VGSTextFieldDelegate.html +++ b/docs/Protocols/VGSTextFieldDelegate.html @@ -537,7 +537,7 @@

    Declaration

    diff --git a/docs/Protocols/VGSTokenizationParametersProtocol.html b/docs/Protocols/VGSTokenizationParametersProtocol.html index a1c04ed7..9899acfc 100644 --- a/docs/Protocols/VGSTokenizationParametersProtocol.html +++ b/docs/Protocols/VGSTokenizationParametersProtocol.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/Structs/VGSCVCTokenizationParameters.html b/docs/Structs/VGSCVCTokenizationParameters.html index 1e6f2e5b..dedf4c9f 100644 --- a/docs/Structs/VGSCVCTokenizationParameters.html +++ b/docs/Structs/VGSCVCTokenizationParameters.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/Structs/VGSCardHolderNameTokenizationParameters.html b/docs/Structs/VGSCardHolderNameTokenizationParameters.html index 8db7af15..95825085 100644 --- a/docs/Structs/VGSCardHolderNameTokenizationParameters.html +++ b/docs/Structs/VGSCardHolderNameTokenizationParameters.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/Structs/VGSCardNumberTokenizationParameters.html b/docs/Structs/VGSCardNumberTokenizationParameters.html index c34a8669..27fd4c06 100644 --- a/docs/Structs/VGSCardNumberTokenizationParameters.html +++ b/docs/Structs/VGSCardNumberTokenizationParameters.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/Structs/VGSCollectLoggingConfiguration.html b/docs/Structs/VGSCollectLoggingConfiguration.html index 04ad1045..1fc63adf 100644 --- a/docs/Structs/VGSCollectLoggingConfiguration.html +++ b/docs/Structs/VGSCollectLoggingConfiguration.html @@ -493,7 +493,7 @@

    Declaration

    diff --git a/docs/Structs/VGSCollectRequestOptions.html b/docs/Structs/VGSCollectRequestOptions.html index a08bb8e7..6fcdeb86 100644 --- a/docs/Structs/VGSCollectRequestOptions.html +++ b/docs/Structs/VGSCollectRequestOptions.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/Structs/VGSCustomPaymentCardModel.html b/docs/Structs/VGSCustomPaymentCardModel.html index e4549362..e4d76330 100644 --- a/docs/Structs/VGSCustomPaymentCardModel.html +++ b/docs/Structs/VGSCustomPaymentCardModel.html @@ -812,7 +812,7 @@

    Parameters

    diff --git a/docs/Structs/VGSDate.html b/docs/Structs/VGSDate.html index df8c2856..2b3718ae 100644 --- a/docs/Structs/VGSDate.html +++ b/docs/Structs/VGSDate.html @@ -563,7 +563,7 @@

    Return Value

    diff --git a/docs/Structs/VGSDateTokenizationParameters.html b/docs/Structs/VGSDateTokenizationParameters.html index 56d4f728..c38a6f03 100644 --- a/docs/Structs/VGSDateTokenizationParameters.html +++ b/docs/Structs/VGSDateTokenizationParameters.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/Structs/VGSExpDateSeparateSerializer.html b/docs/Structs/VGSExpDateSeparateSerializer.html index ee67b387..41087852 100644 --- a/docs/Structs/VGSExpDateSeparateSerializer.html +++ b/docs/Structs/VGSExpDateSeparateSerializer.html @@ -537,7 +537,7 @@

    Parameters

    diff --git a/docs/Structs/VGSExpDateTokenizationParameters.html b/docs/Structs/VGSExpDateTokenizationParameters.html index 672659cb..26f4e11a 100644 --- a/docs/Structs/VGSExpDateTokenizationParameters.html +++ b/docs/Structs/VGSExpDateTokenizationParameters.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/Structs/VGSPaymentCardModel.html b/docs/Structs/VGSPaymentCardModel.html index 9d1a7551..db65257d 100644 --- a/docs/Structs/VGSPaymentCardModel.html +++ b/docs/Structs/VGSPaymentCardModel.html @@ -678,7 +678,7 @@

    Declaration

    diff --git a/docs/Structs/VGSSSNTokenizationParameters.html b/docs/Structs/VGSSSNTokenizationParameters.html index 9a6a6b28..68c26226 100644 --- a/docs/Structs/VGSSSNTokenizationParameters.html +++ b/docs/Structs/VGSSSNTokenizationParameters.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/Structs/VGSTextFieldStatePublisher.html b/docs/Structs/VGSTextFieldStatePublisher.html index 3a1fd72d..7cce9cbc 100644 --- a/docs/Structs/VGSTextFieldStatePublisher.html +++ b/docs/Structs/VGSTextFieldStatePublisher.html @@ -511,7 +511,7 @@

    Parameters

    diff --git a/docs/Structs/VGSTokenizationParameters.html b/docs/Structs/VGSTokenizationParameters.html index dc3eeb5e..71b688de 100644 --- a/docs/Structs/VGSTokenizationParameters.html +++ b/docs/Structs/VGSTokenizationParameters.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/Structs/VGSUnknownPaymentCardModel.html b/docs/Structs/VGSUnknownPaymentCardModel.html index 24f1804b..1332ac09 100644 --- a/docs/Structs/VGSUnknownPaymentCardModel.html +++ b/docs/Structs/VGSUnknownPaymentCardModel.html @@ -613,7 +613,7 @@

    Declaration

    diff --git a/docs/Structs/VGSValidationRuleCardExpirationDate.html b/docs/Structs/VGSValidationRuleCardExpirationDate.html index 0fa6b5ed..76091caa 100644 --- a/docs/Structs/VGSValidationRuleCardExpirationDate.html +++ b/docs/Structs/VGSValidationRuleCardExpirationDate.html @@ -524,7 +524,7 @@

    Parameters

    diff --git a/docs/Structs/VGSValidationRuleDateRange.html b/docs/Structs/VGSValidationRuleDateRange.html index cb4498c4..e69908dd 100644 --- a/docs/Structs/VGSValidationRuleDateRange.html +++ b/docs/Structs/VGSValidationRuleDateRange.html @@ -574,7 +574,7 @@

    Parameters

    diff --git a/docs/Structs/VGSValidationRuleLength.html b/docs/Structs/VGSValidationRuleLength.html index ecf7ccb0..44df4691 100644 --- a/docs/Structs/VGSValidationRuleLength.html +++ b/docs/Structs/VGSValidationRuleLength.html @@ -566,7 +566,7 @@

    Parameters

    diff --git a/docs/Structs/VGSValidationRuleLengthMatch.html b/docs/Structs/VGSValidationRuleLengthMatch.html index 23dae294..969d7093 100644 --- a/docs/Structs/VGSValidationRuleLengthMatch.html +++ b/docs/Structs/VGSValidationRuleLengthMatch.html @@ -524,7 +524,7 @@

    Parameters

    diff --git a/docs/Structs/VGSValidationRuleLuhnCheck.html b/docs/Structs/VGSValidationRuleLuhnCheck.html index 8b17ac3b..bbc3c216 100644 --- a/docs/Structs/VGSValidationRuleLuhnCheck.html +++ b/docs/Structs/VGSValidationRuleLuhnCheck.html @@ -482,7 +482,7 @@

    Parameters

    diff --git a/docs/Structs/VGSValidationRulePattern.html b/docs/Structs/VGSValidationRulePattern.html index b5375946..5ff244f9 100644 --- a/docs/Structs/VGSValidationRulePattern.html +++ b/docs/Structs/VGSValidationRulePattern.html @@ -524,7 +524,7 @@

    Parameters

    diff --git a/docs/Structs/VGSValidationRulePaymentCard.html b/docs/Structs/VGSValidationRulePaymentCard.html index 76caa9d0..030b9e50 100644 --- a/docs/Structs/VGSValidationRulePaymentCard.html +++ b/docs/Structs/VGSValidationRulePaymentCard.html @@ -575,7 +575,7 @@

    Parameters

    diff --git a/docs/Structs/VGSValidationRuleSet.html b/docs/Structs/VGSValidationRuleSet.html index ca4adc58..a6264ec7 100644 --- a/docs/Structs/VGSValidationRuleSet.html +++ b/docs/Structs/VGSValidationRuleSet.html @@ -512,7 +512,7 @@

    Declaration

    diff --git a/docs/Tokenization Parameters.html b/docs/Tokenization Parameters.html index 686a5149..2fde8918 100644 --- a/docs/Tokenization Parameters.html +++ b/docs/Tokenization Parameters.html @@ -702,7 +702,7 @@

    Declaration

    diff --git a/docs/UI Elements.html b/docs/UI Elements.html index 5c57cebe..4241e015 100644 --- a/docs/UI Elements.html +++ b/docs/UI Elements.html @@ -411,7 +411,7 @@

    Declaration

    @@ -1004,7 +1004,7 @@

    Declaration

    @@ -1080,7 +1080,7 @@

    Declaration

    diff --git a/docs/VGSTextField Serializers.html b/docs/VGSTextField Serializers.html index 2f191f73..6594052e 100644 --- a/docs/VGSTextField Serializers.html +++ b/docs/VGSTextField Serializers.html @@ -453,7 +453,7 @@

    Declaration

    diff --git a/docs/Validation Rules.html b/docs/Validation Rules.html index 79a6c768..45bb1022 100644 --- a/docs/Validation Rules.html +++ b/docs/Validation Rules.html @@ -674,7 +674,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/CardState.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/CardState.html index 7f3f558c..730ab5fd 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/CardState.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/CardState.html @@ -523,7 +523,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/SSNState.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/SSNState.html index 8f695bee..ebb68d25 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/SSNState.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/SSNState.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/State.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/State.html index b4761360..aa4703ea 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/State.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/State.html @@ -673,7 +673,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCVCTextField.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCVCTextField.html index be69d3bf..5097c085 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCVCTextField.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCVCTextField.html @@ -559,7 +559,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCVCTextField/CVCIconLocation.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCVCTextField/CVCIconLocation.html index f7357ce7..a6ef8bb4 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCVCTextField/CVCIconLocation.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCVCTextField/CVCIconLocation.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCVCTokenizationConfiguration.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCVCTokenizationConfiguration.html index 448faf60..91327dc4 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCVCTokenizationConfiguration.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCVCTokenizationConfiguration.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCardHolderNameTokenizationConfiguration.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCardHolderNameTokenizationConfiguration.html index a6eac2ba..921f28ad 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCardHolderNameTokenizationConfiguration.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCardHolderNameTokenizationConfiguration.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCardNumberTokenizationConfiguration.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCardNumberTokenizationConfiguration.html index f35f52d1..f2d58e61 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCardNumberTokenizationConfiguration.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCardNumberTokenizationConfiguration.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCardTextField.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCardTextField.html index ac1e17ce..340f3e8d 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCardTextField.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCardTextField.html @@ -559,7 +559,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCardTextField/CardIconLocation.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCardTextField/CardIconLocation.html index 3a7ca7be..d5895dcb 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCardTextField/CardIconLocation.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCardTextField/CardIconLocation.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCollect.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCollect.html index 81178585..9fabca01 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCollect.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCollect.html @@ -1841,7 +1841,7 @@

    Return Value

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCollectLogger.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCollectLogger.html index ee15b418..fbaeb37a 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCollectLogger.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSCollectLogger.html @@ -516,7 +516,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSConfiguration.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSConfiguration.html index 583dd239..da7d175f 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSConfiguration.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSConfiguration.html @@ -846,7 +846,7 @@

    Parameters

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSDateConfiguration.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSDateConfiguration.html index 4c11627b..1d77db68 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSDateConfiguration.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSDateConfiguration.html @@ -750,7 +750,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSDateTextField.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSDateTextField.html index b5c0f2c5..c80623d9 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSDateTextField.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSDateTextField.html @@ -529,7 +529,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSDateTextField/MonthFormat.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSDateTextField/MonthFormat.html index 3709f8c8..c1a86151 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSDateTextField/MonthFormat.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSDateTextField/MonthFormat.html @@ -493,7 +493,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSDateTokenizationConfiguration.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSDateTokenizationConfiguration.html index 50e491e7..c97572f8 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSDateTokenizationConfiguration.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSDateTokenizationConfiguration.html @@ -648,7 +648,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSError.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSError.html index a49b05dc..e7d0c9f8 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSError.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSError.html @@ -493,7 +493,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateConfiguration.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateConfiguration.html index 8939dcfd..981c1e7e 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateConfiguration.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateConfiguration.html @@ -588,7 +588,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateTextField.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateTextField.html index c61d6c83..1d655e0d 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateTextField.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateTextField.html @@ -513,9 +513,9 @@

    Declaration

  • @@ -530,7 +530,7 @@

    Declaration

    Declaration

    Swift

    -
    public var yearPickeFormat: YearFormat { get set }
    +
    public var yearPickerFormat: YearFormat { get set }
    @@ -548,7 +548,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateTextField/MonthFormat.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateTextField/MonthFormat.html index 99480171..89008db4 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateTextField/MonthFormat.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateTextField/MonthFormat.html @@ -493,7 +493,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateTextField/YearFormat.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateTextField/YearFormat.html index 796dd565..2accfc02 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateTextField/YearFormat.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateTextField/YearFormat.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateTokenizationConfiguration.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateTokenizationConfiguration.html index d4690f3d..2fcf10f5 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateTokenizationConfiguration.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSExpDateTokenizationConfiguration.html @@ -631,7 +631,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSFileInfo.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSFileInfo.html index a8563c52..79ebe753 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSFileInfo.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSFileInfo.html @@ -498,7 +498,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSFilePickerConfiguration.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSFilePickerConfiguration.html index fc82cfb7..d5ab7396 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSFilePickerConfiguration.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSFilePickerConfiguration.html @@ -528,7 +528,7 @@

    Parameters

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSFilePickerController.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSFilePickerController.html index 778c1ce4..8d7b7bcb 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSFilePickerController.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSFilePickerController.html @@ -651,7 +651,7 @@

    Parameters

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSPaymentCards.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSPaymentCards.html index 2eb7c665..a3afb6bf 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSPaymentCards.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSPaymentCards.html @@ -1051,7 +1051,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSPaymentCards/CardBrand.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSPaymentCards/CardBrand.html index 8314c190..8038edd6 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSPaymentCards/CardBrand.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSPaymentCards/CardBrand.html @@ -1016,7 +1016,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSSSNTokenizationConfiguration.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSSSNTokenizationConfiguration.html index e3009be0..b2e2b207 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSSSNTokenizationConfiguration.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSSSNTokenizationConfiguration.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSTextField.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSTextField.html index bb07559e..3e603e9b 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSTextField.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSTextField.html @@ -387,7 +387,7 @@

    VGSTextField

    An object that displays an editable text area in user interface.

    @@ -735,6 +735,19 @@

    Declaration

  • + + +
    +
    + + +
    + +

    Accessibility Attributes +

    +
    +
    +
    • @@ -760,7 +773,7 @@

      Declaration

    @@ -778,7 +791,8 @@

    Declaration

    -

    A localized string that contains a brief description of the result of performing an action on the accessibility text field.

    +

    A localized string that contains a brief description of the result of +performing an action on the accessibility text field.

    @@ -790,7 +804,37 @@

    Declaration

    +
    + + +
  • + +
    +
    +
    +
    +
    +

    Boolean value that determinates if the text field should be exposed as an accesibility element.

    + +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public var textFieldIsAccessibilityElement: Bool { get set }
    + +
    +
    +
    @@ -833,7 +877,7 @@

    Declaration

    @@ -863,7 +907,7 @@

    Declaration

    @@ -913,7 +957,7 @@

    Declaration

    @@ -943,7 +987,7 @@

    Declaration

    @@ -991,7 +1035,7 @@

    Declaration

    @@ -1245,7 +1289,7 @@

    Declaration

    @@ -1276,7 +1320,7 @@

    Declaration

    @@ -1306,7 +1350,7 @@

    Declaration

    @@ -1319,7 +1363,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSTokenizationConfiguration.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSTokenizationConfiguration.html index 18a2a57d..19a6bba2 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSTokenizationConfiguration.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Classes/VGSTokenizationConfiguration.html @@ -433,7 +433,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Debugging.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Debugging.html index df867e6e..df4f5b15 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Debugging.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Debugging.html @@ -486,7 +486,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enumerations.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enumerations.html index 80f007a4..5642de01 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enumerations.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enumerations.html @@ -454,7 +454,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/CheckSumAlgorithmType.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/CheckSumAlgorithmType.html index 6cfd7bb5..a1b1f05d 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/CheckSumAlgorithmType.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/CheckSumAlgorithmType.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/Environment.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/Environment.html index d290ae67..56826e1c 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/Environment.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/Environment.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/FieldType.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/FieldType.html index d9b4f112..7ba21eec 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/FieldType.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/FieldType.html @@ -613,7 +613,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSCardExpDateFormat.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSCardExpDateFormat.html index 76f4ff1b..6b7a6d86 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSCardExpDateFormat.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSCardExpDateFormat.html @@ -523,7 +523,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSCollectFieldNameMappingPolicy.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSCollectFieldNameMappingPolicy.html index 7684b5e1..de418de6 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSCollectFieldNameMappingPolicy.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSCollectFieldNameMappingPolicy.html @@ -601,7 +601,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSCollectHTTPMethod.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSCollectHTTPMethod.html index e2a37d05..43ed6f4d 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSCollectHTTPMethod.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSCollectHTTPMethod.html @@ -553,7 +553,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSDateFormat.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSDateFormat.html index 51c97f75..00b1bfc6 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSDateFormat.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSDateFormat.html @@ -386,7 +386,7 @@

    VGSDateFormat

    Format used to validate a VGS date text input

    @@ -420,7 +420,7 @@

    Declaration

    @@ -463,7 +463,7 @@

    Declaration

    @@ -476,7 +476,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSErrorType.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSErrorType.html index abbde3d0..b8de703a 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSErrorType.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSErrorType.html @@ -678,7 +678,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSFileSource.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSFileSource.html index 42ac711e..4a0068ee 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSFileSource.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSFileSource.html @@ -493,7 +493,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSLogLevel.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSLogLevel.html index 72fb8657..308f28ef 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSLogLevel.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSLogLevel.html @@ -493,7 +493,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSResponse.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSResponse.html index 62b5171a..071b23ad 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSResponse.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSResponse.html @@ -562,7 +562,7 @@

    Parameters

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSTextFieldInputSource.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSTextFieldInputSource.html index 875f0444..b84de93f 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSTextFieldInputSource.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSTextFieldInputSource.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSTokenizationResponse.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSTokenizationResponse.html index 1bea722d..cff0f678 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSTokenizationResponse.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSTokenizationResponse.html @@ -562,7 +562,7 @@

    Parameters

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSValidationErrorType.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSValidationErrorType.html index 5b8d6143..b1a5c9a0 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSValidationErrorType.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSValidationErrorType.html @@ -613,7 +613,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSVaultAliasFormat.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSVaultAliasFormat.html index 32beb7b5..2648e5b7 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSVaultAliasFormat.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSVaultAliasFormat.html @@ -673,7 +673,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSVaultStorageType.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSVaultStorageType.html index be51033c..e23a4e79 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSVaultStorageType.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Enums/VGSVaultStorageType.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Error Keys.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Error Keys.html index 4ff7dd1f..dace0270 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Error Keys.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Error Keys.html @@ -685,7 +685,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Errors.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Errors.html index e49e3a5c..61722565 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Errors.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Errors.html @@ -545,7 +545,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/File Picker.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/File Picker.html index 60e9539c..df1f676e 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/File Picker.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/File Picker.html @@ -548,7 +548,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Observe State and Send Data.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Observe State and Send Data.html index fb390174..b813fea9 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Observe State and Send Data.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Observe State and Send Data.html @@ -765,7 +765,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Payment Cards.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Payment Cards.html index 5a70d9cc..85c3057a 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Payment Cards.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Payment Cards.html @@ -522,7 +522,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSDateConfigurationProtocol.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSDateConfigurationProtocol.html index 60e86959..07203603 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSDateConfigurationProtocol.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSDateConfigurationProtocol.html @@ -493,7 +493,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSExpDateConfigurationProtocol.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSExpDateConfigurationProtocol.html index 72e4aeae..80cefbaf 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSExpDateConfigurationProtocol.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSExpDateConfigurationProtocol.html @@ -493,7 +493,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSFilePickerControllerDelegate.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSFilePickerControllerDelegate.html index 4ea61309..21dd5a48 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSFilePickerControllerDelegate.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSFilePickerControllerDelegate.html @@ -503,7 +503,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSTextFieldDelegate.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSTextFieldDelegate.html index 51f2a1c2..1fb092fb 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSTextFieldDelegate.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSTextFieldDelegate.html @@ -537,7 +537,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSTokenizationParametersProtocol.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSTokenizationParametersProtocol.html index a1c04ed7..9899acfc 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSTokenizationParametersProtocol.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Protocols/VGSTokenizationParametersProtocol.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCVCTokenizationParameters.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCVCTokenizationParameters.html index 1e6f2e5b..dedf4c9f 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCVCTokenizationParameters.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCVCTokenizationParameters.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCardHolderNameTokenizationParameters.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCardHolderNameTokenizationParameters.html index 8db7af15..95825085 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCardHolderNameTokenizationParameters.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCardHolderNameTokenizationParameters.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCardNumberTokenizationParameters.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCardNumberTokenizationParameters.html index c34a8669..27fd4c06 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCardNumberTokenizationParameters.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCardNumberTokenizationParameters.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCollectLoggingConfiguration.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCollectLoggingConfiguration.html index 04ad1045..1fc63adf 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCollectLoggingConfiguration.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCollectLoggingConfiguration.html @@ -493,7 +493,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCollectRequestOptions.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCollectRequestOptions.html index a08bb8e7..6fcdeb86 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCollectRequestOptions.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCollectRequestOptions.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCustomPaymentCardModel.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCustomPaymentCardModel.html index e4549362..e4d76330 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCustomPaymentCardModel.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSCustomPaymentCardModel.html @@ -812,7 +812,7 @@

    Parameters

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSDate.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSDate.html index df8c2856..2b3718ae 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSDate.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSDate.html @@ -563,7 +563,7 @@

    Return Value

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSDateTokenizationParameters.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSDateTokenizationParameters.html index 56d4f728..c38a6f03 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSDateTokenizationParameters.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSDateTokenizationParameters.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSExpDateSeparateSerializer.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSExpDateSeparateSerializer.html index ee67b387..41087852 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSExpDateSeparateSerializer.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSExpDateSeparateSerializer.html @@ -537,7 +537,7 @@

    Parameters

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSExpDateTokenizationParameters.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSExpDateTokenizationParameters.html index 672659cb..26f4e11a 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSExpDateTokenizationParameters.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSExpDateTokenizationParameters.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSPaymentCardModel.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSPaymentCardModel.html index 9d1a7551..db65257d 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSPaymentCardModel.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSPaymentCardModel.html @@ -678,7 +678,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSSSNTokenizationParameters.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSSSNTokenizationParameters.html index 9a6a6b28..68c26226 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSSSNTokenizationParameters.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSSSNTokenizationParameters.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSTextFieldStatePublisher.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSTextFieldStatePublisher.html index 3a1fd72d..7cce9cbc 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSTextFieldStatePublisher.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSTextFieldStatePublisher.html @@ -511,7 +511,7 @@

    Parameters

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSTokenizationParameters.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSTokenizationParameters.html index dc3eeb5e..71b688de 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSTokenizationParameters.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSTokenizationParameters.html @@ -463,7 +463,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSUnknownPaymentCardModel.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSUnknownPaymentCardModel.html index 24f1804b..1332ac09 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSUnknownPaymentCardModel.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSUnknownPaymentCardModel.html @@ -613,7 +613,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleCardExpirationDate.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleCardExpirationDate.html index 0fa6b5ed..76091caa 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleCardExpirationDate.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleCardExpirationDate.html @@ -524,7 +524,7 @@

    Parameters

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleDateRange.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleDateRange.html index cb4498c4..e69908dd 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleDateRange.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleDateRange.html @@ -574,7 +574,7 @@

    Parameters

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleLength.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleLength.html index ecf7ccb0..44df4691 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleLength.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleLength.html @@ -566,7 +566,7 @@

    Parameters

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleLengthMatch.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleLengthMatch.html index 23dae294..969d7093 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleLengthMatch.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleLengthMatch.html @@ -524,7 +524,7 @@

    Parameters

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleLuhnCheck.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleLuhnCheck.html index 8b17ac3b..bbc3c216 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleLuhnCheck.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleLuhnCheck.html @@ -482,7 +482,7 @@

    Parameters

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRulePattern.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRulePattern.html index b5375946..5ff244f9 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRulePattern.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRulePattern.html @@ -524,7 +524,7 @@

    Parameters

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRulePaymentCard.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRulePaymentCard.html index 76caa9d0..030b9e50 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRulePaymentCard.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRulePaymentCard.html @@ -575,7 +575,7 @@

    Parameters

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleSet.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleSet.html index ca4adc58..a6264ec7 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleSet.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Structs/VGSValidationRuleSet.html @@ -512,7 +512,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Tokenization Parameters.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Tokenization Parameters.html index 686a5149..2fde8918 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Tokenization Parameters.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Tokenization Parameters.html @@ -702,7 +702,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/UI Elements.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/UI Elements.html index 5c57cebe..4241e015 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/UI Elements.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/UI Elements.html @@ -411,7 +411,7 @@

    Declaration

    @@ -1004,7 +1004,7 @@

    Declaration

    @@ -1080,7 +1080,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/VGSTextField Serializers.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/VGSTextField Serializers.html index 2f191f73..6594052e 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/VGSTextField Serializers.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/VGSTextField Serializers.html @@ -453,7 +453,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Validation Rules.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Validation Rules.html index 79a6c768..45bb1022 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Validation Rules.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/Validation Rules.html @@ -674,7 +674,7 @@

    Declaration

    diff --git a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/index.html b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/index.html index d0943368..d225dfbf 100644 --- a/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/index.html +++ b/docs/docsets/VGSCollectSDK.docset/Contents/Resources/Documents/index.html @@ -801,8 +801,6 @@

    Code Example

    Demo Application

    Demo application for collecting card data on iOS is here.

    - -

    Also you can check our payment optimization demo with Payment Orchestration integration.

    Documentation