diff --git a/.gitignore b/.gitignore index 02c08753..40714785 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ .DS_Store +ModelVersions.md + /.build /Packages /*.xcodeproj diff --git a/Package.resolved b/Package.resolved index 7076e693..5c9d175d 100644 --- a/Package.resolved +++ b/Package.resolved @@ -15,8 +15,8 @@ "repositoryURL": "https://github.com/vapor/console.git", "state": { "branch": null, - "revision": "d6cf07af59ae63cd95c4b5f98cf1f25627750fd1", - "version": "3.1.0" + "revision": "74cfbea629d4aac34a97cead2447a6870af1950b", + "version": "3.1.1" } }, { @@ -24,8 +24,8 @@ "repositoryURL": "https://github.com/vapor/core.git", "state": { "branch": null, - "revision": "1794ff138bd669175a2528d27695028d7cb30471", - "version": "3.5.0" + "revision": "727ae2905ebdca162c5da5bfe187c406555859e2", + "version": "3.7.3" } }, { @@ -33,8 +33,8 @@ "repositoryURL": "https://github.com/skelpo/Countries.git", "state": { "branch": null, - "revision": "95962a77438b5c949f9d812a700cbabbefcf15da", - "version": "0.9.1" + "revision": "b240c113f6035426bf04332119cf98d825e1b0a6", + "version": "1.0.0" } }, { @@ -42,8 +42,8 @@ "repositoryURL": "https://github.com/vapor/crypto.git", "state": { "branch": null, - "revision": "bce9ac891c9b33fc045deda713e0d976d13b749a", - "version": "3.3.1" + "revision": "45bb12d13cdec80dbd1cc0685ea002e51ab83439", + "version": "3.3.2" } }, { @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/vapor/database-kit.git", "state": { "branch": null, - "revision": "3557894af50914e134803a684b42a9ea6eefaea2", - "version": "1.3.2" + "revision": "8f352c8e66dab301ab9bfef912a01ce1361ba1e4", + "version": "1.3.3" } }, { @@ -60,8 +60,8 @@ "repositoryURL": "https://github.com/skelpo/Failable.git", "state": { "branch": null, - "revision": "34dde6d29991ddfc583d71d81e6ad90aac3fe2e5", - "version": "0.3.0" + "revision": "b488d50046d35243a67860bd8499bfc7fe1b8428", + "version": "0.4.0" } }, { @@ -69,8 +69,8 @@ "repositoryURL": "https://github.com/vapor/http.git", "state": { "branch": null, - "revision": "6973bf50dab8dd00e4daf8cb82ca72b33f5db016", - "version": "3.1.6" + "revision": "8da7d475a1a060714766d9ad4b24eb0dae243aab", + "version": "3.1.11" } }, { @@ -78,8 +78,8 @@ "repositoryURL": "https://github.com/skelpo/JSON.git", "state": { "branch": null, - "revision": "59167bee35bfeb588d76f54b6fd50d797d3be980", - "version": "0.13.1" + "revision": "521263ef8c57f41cbbd75a7bc2c1a49916af4054", + "version": "1.0.0" } }, { @@ -87,8 +87,8 @@ "repositoryURL": "https://github.com/vapor/multipart.git", "state": { "branch": null, - "revision": "e57007c23a52b68e44ebdfc70cbe882a7c4f1ec3", - "version": "3.0.2" + "revision": "bd7736c5f28e48ed8b683dcc9df3dcd346064c2b", + "version": "3.0.3" } }, { @@ -96,8 +96,8 @@ "repositoryURL": "https://github.com/vapor/routing.git", "state": { "branch": null, - "revision": "3219e328491b0853b8554c5a694add344d2c6cfb", - "version": "3.0.1" + "revision": "626190ddd2bd9f967743b60ba6adaf90bbd2651c", + "version": "3.0.2" } }, { @@ -105,8 +105,8 @@ "repositoryURL": "https://github.com/vapor/service.git", "state": { "branch": null, - "revision": "281a70b69783891900be31a9e70051b6fe19e146", - "version": "1.0.0" + "revision": "fa5b5de62bd68bcde9a69933f31319e46c7275fb", + "version": "1.0.2" } }, { @@ -114,8 +114,8 @@ "repositoryURL": "https://github.com/apple/swift-nio.git", "state": { "branch": null, - "revision": "03c541a24dd0558c942b15d8464eb75d70a921c4", - "version": "1.12.1" + "revision": "29a9f2aca71c8afb07e291336f1789337ce235dd", + "version": "1.13.2" } }, { @@ -159,8 +159,8 @@ "repositoryURL": "https://github.com/vapor/template-kit.git", "state": { "branch": null, - "revision": "aff2d6fc65bfd04579b0201b31a8d6720239c1cf", - "version": "1.1.1" + "revision": "4b1073d74be9f5c6a5bc63a07a84e83efec26229", + "version": "1.1.2" } }, { @@ -168,8 +168,8 @@ "repositoryURL": "https://github.com/vapor/url-encoded-form.git", "state": { "branch": null, - "revision": "932024f363ee5ff59059cf7d67194a1c271d3d0c", - "version": "1.0.5" + "revision": "82d8d63bdb76b6dd8febe916c639ab8608dbbaed", + "version": "1.0.6" } }, { @@ -186,8 +186,8 @@ "repositoryURL": "https://github.com/vapor/vapor.git", "state": { "branch": null, - "revision": "54cbf396147aba77ecb32e7fc75a3d13251551b1", - "version": "3.1.1" + "revision": "c86ada59b31c69f08a6abd4f776537cba48d5df6", + "version": "3.3.0" } }, { @@ -195,8 +195,8 @@ "repositoryURL": "https://github.com/vapor/websocket.git", "state": { "branch": null, - "revision": "21eb4773e25a8ff96fe347a31fe106900a69fa6a", - "version": "1.1.1" + "revision": "d85e5b6dce4d04065865f77385fc3324f98178f6", + "version": "1.1.2" } } ] diff --git a/Package.swift b/Package.swift index 9db414e5..1ac542cb 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:4.2 +// swift-tools-version:5.0 import PackageDescription @@ -8,19 +8,21 @@ let package = Package( .library(name: "PayPal", targets: ["PayPal"]), ], dependencies: [ - .package(url: "https://github.com/skelpo/Countries.git", from: "0.9.1"), - .package(url: "https://github.com/skelpo/Failable.git", from: "0.2.0"), - .package(url: "https://github.com/vapor/vapor.git", from: "3.1.0"), - .package(url: "https://github.com/skelpo/JSON.git", from: "0.13.1"), + .package(url: "https://github.com/skelpo/Countries.git", from: "1.0.0"), + .package(url: "https://github.com/skelpo/Failable.git", from: "0.4.0"), + .package(url: "https://github.com/vapor/vapor.git", from: "3.3.0"), + .package(url: "https://github.com/skelpo/JSON.git", from: "1.0.0"), .package(url: "https://github.com/twostraws/SwiftGD.git", from: "2.2.0") ], targets: [ .target(name: "PayPal", dependencies: ["Vapor", "JSON", "Failable", "Countries"]), + .target(name: "PayPalV1", dependencies: ["Vapor", "PayPal"], path: "Sources/V1"), + .target(name: "PayPalV2", dependencies: ["Vapor", "PayPal"], path: "Sources/V2"), .target(name: "TestUtilities", dependencies: ["PayPal", "Vapor"]), .testTarget(name: "ConfigTests", dependencies: ["PayPal", "TestUtilities"]), .testTarget(name: "ControllerTests", dependencies: ["PayPal", "SwiftGD", "TestUtilities"]), .testTarget(name: "ModelTests", dependencies: ["PayPal", "TestUtilities"]), - .testTarget(name: "PayPalTests", dependencies: ["PayPal", "Vapor", "JSON"]), + .testTarget(name: "PayPalTests", dependencies: ["PayPal", "Vapor", "JSON", "ConfigTests", "ControllerTests", "ModelTests"]), ] ) diff --git a/Sources/PayPal/API/API.swift b/Sources/PayPal/API/API.swift new file mode 100644 index 00000000..ba7172cd --- /dev/null +++ b/Sources/PayPal/API/API.swift @@ -0,0 +1,24 @@ +import Vapor + +/// The wrapper for the whole PayPal REST API. +public final class API { + + /// The client used to send requests to PayPal. + public let client: PayPalClient + + /// Creates a new `API` instance with the dependencies for the `PayPalClient` instance. + /// + /// - Parameters: + /// - client: The `Client` instance that the `PayPalClient` instance uses to send requests. + /// - environment: The PayPal environment to send requests to. + public init(client: Client, version: Version, environment: Environment) { + self.client = PayPalClient(client: client, version: version, env: environment) + } + + /// Creates a new `API` instance with the `PayPalClient` instance to use. + /// + /// - Parameter client: The `PayPalClient` instance that will be used to send requests to the PayPal API. + public init(client: PayPalClient) { + self.client = client + } +} diff --git a/Sources/PayPal/API/Authentication.swift b/Sources/PayPal/API/Authentication.swift index 377f1f16..0ae53923 100644 --- a/Sources/PayPal/API/Authentication.swift +++ b/Sources/PayPal/API/Authentication.swift @@ -55,15 +55,15 @@ extension PayPalClient { /// /// - Returns: A void future that can be used to get notified when the auth information has been fetched and stored. public func authenticate() -> Future { - return Future.flatMap(on: self.container) { () -> Future in - let config = try self.container.make(Configuration.self) + return Future.flatMap(on: self.client.container) { () -> Future in + let config = try self.client.container.make(Configuration.self) let credentials = "\(config.id):\(config.secret)" let encoded = Data(credentials.utf8).base64EncodedString() let headers: HTTPHeaders = ["Accept": "application/json", "Accept-Language": "en_US", "Authorization": "Basic \(encoded)"] - let request = try self.container.paypal(.POST, "v1/oauth2/token", headers: headers, auth: false, body: ["grant_type": "client_credentials"]) - return try self.container.client().send(request) + let request = try self.request(.POST, "v1/oauth2/token", headers: headers, auth: false, body: ["grant_type": "client_credentials"]) + return self.client.send(request) }.flatMap(to: AuthResponse.self) { response in if !(200...299).contains(response.http.status.code) { return try response.content.decode(PayPalAPIIdentityError.self).map { error in throw error } @@ -72,8 +72,7 @@ extension PayPalClient { return try response.content.decode(AuthResponse.self) }.map(to: Void.self) { data in - let auth = try self.container.make(AuthInfo.self) - data.populate(auth) + data.populate(self.auth) } } } diff --git a/Sources/PayPal/API/Controller.swift b/Sources/PayPal/API/Controller.swift index eae80394..0066cc3e 100644 --- a/Sources/PayPal/API/Controller.swift +++ b/Sources/PayPal/API/Controller.swift @@ -50,3 +50,28 @@ extension PayPalController { } } } + +// TODO: - Renamed protocol to PayPalController. + +/// A controller that handles a versioned resource of the PayPal API. +public protocol VersionedController { + + /// The `PayPalClient` instance used to send requests to the PayPal API. + var client: PayPalClient { get } + + /// The path components for the API resource that the controller interacts with. + var resource: [String] { get } + + /// Creates a new instance of `Self` with the `PayPalClient` instance that will be used by it. + /// + /// - Parameter client: The `PayPalClient` instance to send requests with. + init(client: PayPalClient) +} + +extension VersionedController { + + /// The resource elements joined togeather as a URL path. + public var path: String { + return self.resource.joined(separator: "/") + "/" + } +} diff --git a/Sources/PayPal/API/Controllers/CustomerDisputes.swift b/Sources/PayPal/API/Controllers/CustomerDisputes.swift index b7627b41..beecdbf4 100644 --- a/Sources/PayPal/API/Controllers/CustomerDisputes.swift +++ b/Sources/PayPal/API/Controllers/CustomerDisputes.swift @@ -213,7 +213,7 @@ public final class CustomerDisputes: PayPalController { /// - Returns: An array of request-related [HATEOAS links](https://developer.paypal.com/docs/api/overview/#hateoas-links). /// If an error response was sent back instead, it gets converted to a Swift error and the future wraps that instead. public func evidence(for disputeID: String, file: File, evidences: [Evidence]) -> Future<[LinkDescription]> { - return Future.flatMap(on: self.container) { () -> Future<[LinkDescription]> in + return self.client { client -> Future<[LinkDescription]> in guard let ext = file.ext, ext == "jpg" || ext == "gif" || ext == "png" || ext == "pdf" else { throw PayPalError(status: .badRequest, identifier: "invalidExtension", reason: "File type must be JPG, GIF, PNG, or PDF") @@ -222,7 +222,7 @@ public final class CustomerDisputes: PayPalController { let json = try MultipartPart(data: JSONEncoder().encode(evidences), headers: ["Content-Type": "application/json"]) let body: [String: MultipartPartConvertible] = ["input": json, "file1": file] - let request: Request = try self.container.paypal(.POST, self.path + disputeID + "/provide-evidence", body: nil as [Int]?) + let request: Request = try client.request(.POST, self.path + disputeID + "/provide-evidence", body: nil as [Int]?) try request.content.encode(body.parts(), as: .related) let response = try self.container.client().send(request) diff --git a/Sources/PayPal/API/Controllers/ManagedAccounts.swift b/Sources/PayPal/API/Controllers/ManagedAccounts.swift index c787af67..5e2917ca 100644 --- a/Sources/PayPal/API/Controllers/ManagedAccounts.swift +++ b/Sources/PayPal/API/Controllers/ManagedAccounts.swift @@ -33,7 +33,7 @@ public final class ManagedAccounts: PayPalController { /// See `PayPalController.init(container:)`. public init(container: Container) { self.container = container - self.resource = "partners/merchant-accounts" + self.resource = "customer/partners/merchant-accounts" self.version = try container.make(Configuration.self).version || .v1 } diff --git a/Sources/PayPal/API/PayPalClient.swift b/Sources/PayPal/API/PayPalClient.swift index 6781019d..4e899a88 100644 --- a/Sources/PayPal/API/PayPalClient.swift +++ b/Sources/PayPal/API/PayPalClient.swift @@ -3,22 +3,85 @@ import Vapor /// An interface for the PayPal REST API. public final class PayPalClient: ServiceType { - /// The current container that the service instance is connected to. - public let container: Container + /// The client object used to send requests to the PayPal API. + internal let client: Client + + /// The root URL (domain and API version) of all API calls. + internal let root: String + + /// The PayPal API version that the client will be used on. + public let version: Version + + /// The PayPal environment to send the requests to. + public let environment: Environment + + /// The data used to authenticate with the PayPal API. + public internal(set) var auth: AuthInfo /// Creates a new PayPal client with a given container. /// /// - Note: Instead of calling this initializer, you should register the /// provider and call `container.make(PayPalClient.self)`. - public init(container: Container) { - self.container = container + public init(client: Client, version: Version, env: Environment) { + self.client = client + self.version = version + self.environment = env + self.auth = AuthInfo() + + self.root = self.environment.domain + "/v" + self.version.rawValue + "/" } /// Creates a new instance of the service for the supplied `Container`. /// /// See `ServiceFactory` for more information. public static func makeService(for worker: Container) throws -> Self { - return self.init(container: worker) + let config = try worker.make(Configuration.self) + return try self.init(client: worker.make(), version: config.version, env: config.environment) + } + + /// A helper to create requests that will be sent to the PayPal REST API. + /// + /// Besides creating a `Request` instance with the data passed in, this method will also add + /// the authentication header if authorization in desired. + /// + /// - Parameters: + /// - method: The HTTP of the request. + /// - path: The resource path for the request. The domain for the client's environment is appended to + /// the front of this string the create the full URL. + /// - headers: Any headers to send in the request, besides the any that are automatically added. + /// - auth: A boolean flag indicating whether the request should have an authorization header or not. + /// - body: The body of the request. + public func request( + _ method: HTTPMethod, + _ path: String, + parameters: QueryParamaters = QueryParamaters(), + headers: HTTPHeaders = [:], + auth: Bool = true, + body: Body? + )throws -> Request where Body: Encodable { + let querystring = parameters.encode() + let path = self.root + path + (querystring == "" ? "" : "?" + querystring) + + let http = HTTPRequest(method: method, url: path, headers: headers) + let request = Request(http: http, using: self.client.container) + + if auth { + guard let type = self.auth.type, let token = self.auth.token else { + throw Abort( + .internalServerError, + reason: "Attempted to make a PayPal request that requires auth before authenticating." + ) + } + + request.http.headers.replaceOrAdd(name: .authorization, value: type + " " + token) + } + + if let body = body { + let contentType: MediaType = auth ? .json : .urlEncodedForm + try request.content.encode(body, as: contentType) + } + + return request } /// Sends a request to the PayPal REST API, using the configured environment. @@ -39,8 +102,37 @@ public final class PayPalClient: ServiceType { headers: HTTPHeaders = [:], body: Body?, as response: Result.Type = Result.self - ) -> Future where Body: Content, Result: Content { - return self.container.paypal(method, path, parameters: parameters, headers: headers, body: body, as: Result.self) + ) -> Future where Body: Encodable, Result: Decodable { + let authentication: EventLoopFuture + if self.auth.tokenExpired { + authentication = self.authenticate() + } else { + authentication = self.client.container.future() + } + + return authentication.flatMap { () -> EventLoopFuture in + let request = try self.request(method, path, parameters: parameters, headers: headers, auth: true, body: body) + return self.client.send(request) + }.flatMap { response -> EventLoopFuture in + if !(200...299).contains(response.http.status.code) { + guard response.http.headers.firstValue(name: .contentType) == "application/json" else { + let body = response.http.body.data ?? Data() + let error = String(data: body, encoding: .utf8) + throw Abort(response.http.status, reason: error) + } + + return try response.content.decode(PayPalAPIError.self).catchFlatMap { _ in + return try response.content.decode(PayPalAPIIdentityError.self).map { error in throw error } + }.map { error in + throw error + } + } + + if Result.self is HTTPStatus.Type { + return self.client.container.future(response.http.status as! Result) + } + return try response.content.decode(Result.self) + } } /// Sends a request to the PayPal REST API, using the configured environment. @@ -58,8 +150,8 @@ public final class PayPalClient: ServiceType { parameters: QueryParamaters = QueryParamaters(), headers: HTTPHeaders = [:], as response: Result.Type = Result.self - ) -> Future where Result: Content { - return self.container.paypal(method, path, parameters: parameters, headers: headers, as: Result.self) + ) -> Future where Result: Decodable { + return self.send(method, path, parameters: parameters, headers: headers, body: nil as [String: String]?, as: Result.self) } /// Sends a `GET` request to the PayPal REST API, using the configured environment. @@ -74,7 +166,7 @@ public final class PayPalClient: ServiceType { /// - Returns: The endpoint's response, encoded to the `Result` type. public func get( _ path: String, parameters: QueryParamaters = QueryParamaters(), headers: HTTPHeaders = [:], body: Body?, as response: Result.Type = Result.self - ) -> Future where Body: Content, Result: Content { + ) -> Future where Body: Encodable, Result: Decodable { return self.send(.GET, path, parameters: parameters, headers: headers, body: body, as: Result.self) } @@ -88,7 +180,7 @@ public final class PayPalClient: ServiceType { /// - Returns: The endpoint's response, encoded to the `Result` type. public func get( _ path: String, parameters: QueryParamaters = QueryParamaters(), headers: HTTPHeaders = [:], as response: Result.Type = Result.self - ) -> Future where Result: Content { + ) -> Future where Result: Decodable { return self.send(.GET, path, parameters: parameters, headers: headers, as: Result.self) } @@ -104,7 +196,7 @@ public final class PayPalClient: ServiceType { /// - Returns: The endpoint's response, encoded to the `Result` type. public func post( _ path: String, parameters: QueryParamaters = QueryParamaters(), headers: HTTPHeaders = [:], body: Body?, as response: Result.Type = Result.self - ) -> Future where Body: Content, Result: Content { + ) -> Future where Body: Encodable, Result: Decodable { return self.send(.POST, path, parameters: parameters, headers: headers, body: body, as: Result.self) } @@ -118,7 +210,7 @@ public final class PayPalClient: ServiceType { /// - Returns: The endpoint's response, encoded to the `Result` type. public func post( _ path: String, parameters: QueryParamaters = QueryParamaters(), headers: HTTPHeaders = [:], as response: Result.Type = Result.self - ) -> Future where Result: Content { + ) -> Future where Result: Decodable { return self.send(.POST, path, parameters: parameters, headers: headers, as: Result.self) } @@ -134,7 +226,7 @@ public final class PayPalClient: ServiceType { /// - Returns: The endpoint's response, encoded to the `Result` type. public func put( _ path: String, parameters: QueryParamaters = QueryParamaters(), headers: HTTPHeaders = [:], body: Body?, as response: Result.Type = Result.self - ) -> Future where Body: Content, Result: Content { + ) -> Future where Body: Encodable, Result: Decodable { return self.send(.PUT, path, parameters: parameters, headers: headers, body: body, as: Result.self) } @@ -148,7 +240,7 @@ public final class PayPalClient: ServiceType { /// - Returns: The endpoint's response, encoded to the `Result` type. public func put( _ path: String, parameters: QueryParamaters = QueryParamaters(), headers: HTTPHeaders = [:], as response: Result.Type = Result.self - ) -> Future where Result: Content { + ) -> Future where Result: Decodable { return self.send(.PUT, path, parameters: parameters, headers: headers, as: Result.self) } @@ -164,7 +256,7 @@ public final class PayPalClient: ServiceType { /// - Returns: The endpoint's response, encoded to the `Result` type. public func patch( _ path: String, parameters: QueryParamaters = QueryParamaters(), headers: HTTPHeaders = [:], body: Body?, as response: Result.Type = Result.self - ) -> Future where Body: Content, Result: Content { + ) -> Future where Body: Encodable, Result: Decodable { return self.send(.PATCH, path, parameters: parameters, headers: headers, body: body, as: Result.self) } @@ -178,7 +270,7 @@ public final class PayPalClient: ServiceType { /// - Returns: The endpoint's response, encoded to the `Result` type. public func patch( _ path: String, parameters: QueryParamaters = QueryParamaters(), headers: HTTPHeaders = [:], as response: Result.Type = Result.self - ) -> Future where Result: Content { + ) -> Future where Result: Decodable { return self.send(.PATCH, path, parameters: parameters, headers: headers, as: Result.self) } @@ -194,7 +286,7 @@ public final class PayPalClient: ServiceType { /// - Returns: The endpoint's response, encoded to the `Result` type. public func delete( _ path: String, parameters: QueryParamaters = QueryParamaters(), headers: HTTPHeaders = [:], body: Body?, as response: Result.Type = Result.self - ) -> Future where Body: Content, Result: Content { + ) -> Future where Body: Encodable, Result: Decodable { return self.send(.DELETE, path, parameters: parameters, headers: headers, body: body, as: Result.self) } @@ -208,7 +300,7 @@ public final class PayPalClient: ServiceType { /// - Returns: The endpoint's response, encoded to the `Result` type. public func delete( _ path: String, parameters: QueryParamaters = QueryParamaters(), headers: HTTPHeaders = [:], as response: Result.Type = Result.self - ) -> Future where Result: Content { + ) -> Future where Result: Decodable { return self.send(.DELETE, path, parameters: parameters, headers: headers, as: Result.self) } } diff --git a/Sources/PayPal/Config/Versions.swift b/Sources/PayPal/Config/Versions.swift index 0abdb22a..1130c5e5 100644 --- a/Sources/PayPal/Config/Versions.swift +++ b/Sources/PayPal/Config/Versions.swift @@ -3,4 +3,7 @@ public enum Version: String, Hashable, CaseIterable, Codable { /// Version 1. case v1 = "1" + + /// Version 2. + case v2 = "2" } diff --git a/Sources/PayPal/Models/Business/Business.swift b/Sources/PayPal/Models/Business/Business.swift index f9ff7841..17b6ff2a 100644 --- a/Sources/PayPal/Models/Business/Business.swift +++ b/Sources/PayPal/Models/Business/Business.swift @@ -52,7 +52,7 @@ public struct Business: Content, Equatable { /// The email address to which to send disputes, in [Simple Mail Transfer Protocol](https://www.ietf.org/rfc/rfc5321.txt) as defined in RFC 5321 /// or in [Internet Message Format](https://www.ietf.org/rfc/rfc5322.txt) as defined in RFC 5322. Does not support Unicode email addresses. - public var disputeEmail: EmailAddress? + public var disputeEmail: Failable> /// The details of business sales. public var sales: Sales? @@ -112,7 +112,7 @@ public struct Business: Content, Equatable { merchantCategory: Failable>>, establishedDate: TimelessDate?, registrationDate: TimelessDate?, - disputeEmail: EmailAddress?, + disputeEmail: Failable>, sales: Sales?, customerService: CustomerService?, addresses: [Address], diff --git a/Sources/PayPal/Models/Business/BusinessOwner/BusinessOwner.swift b/Sources/PayPal/Models/Business/BusinessOwner/BusinessOwner.swift index 0ea317db..24024a47 100644 --- a/Sources/PayPal/Models/Business/BusinessOwner/BusinessOwner.swift +++ b/Sources/PayPal/Models/Business/BusinessOwner/BusinessOwner.swift @@ -27,7 +27,7 @@ public struct BusinessOwner: Content, Equatable { /// The account holder's date of birth, in [Internet date and time `full-date` format](https://tools.ietf.org/html/rfc3339#section-5.6). /// Supports `YYYY-MM-dd`. Not required for all countries. - public var birthdate: Date? + public var birthdate: TimelessDate? /// The [language code](https://developer.paypal.com/docs/integration/direct/rest/locale-codes/) for the account holder's preferred language. public var language: Language? @@ -77,25 +77,14 @@ public struct BusinessOwner: Content, Equatable { self.phones = phones self.ids = ids self.occupation = occupation - - if let date = birthdate { - self.birthdate = TimelessDate.formatter.date(from: TimelessDate.formatter.string(from: date)) - } else { - self.birthdate = nil - } + self.birthdate = birthdate.map(TimelessDate.init) } /// See [`Decodable.init(from:)`](https://developer.apple.com/documentation/swift/decodable/2894081-init). public init(from decoder: Decoder)throws { let container = try decoder.container(keyedBy: CodingKeys.self) - if - let birthdate = try container.decodeIfPresent(String.self, forKey: .birthdate), - let date = TimelessDate.formatter.date(from: birthdate) - { - self.birthdate = date - } - + self.birthdate = try container.decodeIfPresent(TimelessDate.self, forKey: .birthdate) self.email = try container.decode(Failable.self, forKey: .email) self.country = try container.decode(Country.self, forKey: .country) self.name = try container.decode(Name.self, forKey: .name) @@ -111,14 +100,11 @@ public struct BusinessOwner: Content, Equatable { public func encode(to encoder: Encoder)throws { var container = encoder.container(keyedBy: CodingKeys.self) - if let date = self.birthdate { - try container.encode(TimelessDate.formatter.string(from: date), forKey: .birthdate) - } - try container.encode(self.email, forKey: .email) try container.encode(self.country, forKey: .country) try container.encode(self.name, forKey: .name) try container.encode(self.addresses, forKey: .addresses) + try container.encodeIfPresent(self.birthdate, forKey: .birthdate) try container.encodeIfPresent(self.relationships, forKey: .relationships) try container.encodeIfPresent(self.language, forKey: .language) try container.encodeIfPresent(self.phones, forKey: .phones) diff --git a/Sources/PayPal/Models/Business/BusinessSales.swift b/Sources/PayPal/Models/Business/BusinessSales.swift index 864d9730..e89c0c2a 100644 --- a/Sources/PayPal/Models/Business/BusinessSales.swift +++ b/Sources/PayPal/Models/Business/BusinessSales.swift @@ -6,10 +6,10 @@ extension Business { public struct Sales: Content, Equatable { /// The average transaction price. - public var price: MoneyRange? + public var price: MoneyRange? /// The average volume of monthly sales. - public var volume: MoneyRange? + public var volume: MoneyRange? /// An array of sales venues for the business. public var venues: [SalesVenue]? @@ -32,8 +32,8 @@ extension Business { /// - website: The primary URL of the business. /// - online: The percentage of revenue attributable to online sales. public init( - price: MoneyRange?, - volume: MoneyRange?, + price: MoneyRange?, + volume: MoneyRange?, venues: [SalesVenue]?, website: Failable>, online: PercentRange? diff --git a/Sources/PayPal/Models/Charge/CounterParty.swift b/Sources/PayPal/Models/Charge/CounterParty.swift index 15241588..8923f677 100644 --- a/Sources/PayPal/Models/Charge/CounterParty.swift +++ b/Sources/PayPal/Models/Charge/CounterParty.swift @@ -9,20 +9,41 @@ public struct CounterParty: Content, Equatable { /// The other party's mobile phone number. public var phoneNumber: String? - /// The other party's name, which is usually the first and last name or the merchant's store name + /// The first name of the counter party. + public var firstName: String? + + /// The last name of the counter part. + public var lastName: String? + + /// The other party's name, which is usually the first and last name or the merchant's store name. public var name: String? - /// Create a new `CounterPart` instance. + /// The ID of the payment that the counter-party's activity is connected to. + public var payment: String? + + /// Create a new `CounterParty` instance. /// - /// CounterParty(email: "once.again@exmaple.com", phoneNumber: "314-159-2653", name: "Hallidy") - public init(email: String?, phoneNumber: String?, name: String?) { + /// - Parameters: + /// - email: The other party's email address. For unregistered users only. + /// - phoneNumber: The other party's mobile phone number. + /// - firstName: The first name of the counter party. + /// - lastName: The last name of the counter part. + /// - name: The other party's name, which is usually the first and last name or the merchant's store name. + /// - payment: The ID of the payment that the counter-party's activity is connected to. + public init(email: String?, phoneNumber: String?, firstName: String?, lastName: String?, name: String?, payment: String?) { self.email = email self.phoneNumber = phoneNumber + self.firstName = firstName + self.lastName = lastName self.name = name + self.payment = payment } enum CodingKeys: String, CodingKey { case email, name case phoneNumber = "phone_number" + case firstName = "first_name" + case lastName = "last_name" + case payment = "payment_id" } } diff --git a/Sources/PayPal/Models/GovernmentBody.swift b/Sources/PayPal/Models/GovernmentBody.swift index 2c9cddd1..0f8c80e5 100644 --- a/Sources/PayPal/Models/GovernmentBody.swift +++ b/Sources/PayPal/Models/GovernmentBody.swift @@ -8,7 +8,7 @@ public struct GovernmentBody: Content, Equatable { /// Creates a new `GovernmentBody` instance. /// - /// GovernmentBody(name: "") + /// - parameter name: The name of enabling legislation. public init(name: String?) { self.name = name } diff --git a/Sources/PayPal/Models/Merchant/MerchantInfo.swift b/Sources/PayPal/Models/Merchant/MerchantInfo.swift index 73208d66..6be73410 100644 --- a/Sources/PayPal/Models/Merchant/MerchantInfo.swift +++ b/Sources/PayPal/Models/Merchant/MerchantInfo.swift @@ -8,22 +8,22 @@ public struct MerchantInfo: Content, Equatable { /// If you omit this value, notifications are sent from and to the primary email address but do not appear on the invoice. /// /// Maximum length: 260. - public var email: String? + public var email: Failable> /// The merchant's business name. /// /// Maximum length: 100. - public var business: String? + public var business: Failable> /// The merchant's first name. /// /// Maximum length: 256. - public var firstName: String? + public var firstName: Failable> /// The merchant's last name. /// /// Maximum length: 256. - public var lastName: String? + public var lastName: Failable> /// The merchant's address. public var address: Address? @@ -37,53 +37,43 @@ public struct MerchantInfo: Content, Equatable { /// The merchant's website. /// /// Maximum length: 2048. - public var website: String? + public var website: Failable> /// The merchant's tax ID. /// /// Maximum length: 100. - public var taxID: String? + public var taxID: Failable> /// Any additional information, such as business hours. /// /// Maximum length: 40. - public var info: String? + public var info: Failable> /// Creates a new `MerchantInfo` instance. /// - /// MerchantInfo( - /// email: "basil@baker.com", - /// business: "Basil Cases and Mystery", - /// firstName: "Basil", - /// lastName: "Mouse", - /// address: Address( - /// recipientName: nil, - /// defaultAddress: true, - /// line1: "221B Baker Street", - /// line2: nil, - /// city: "London", - /// state: nil, - /// countryCode: "UK", - /// postalCode: "42" - /// ), - /// phone: PhoneNumber(country: "1", number: "9963191901"), - /// fax: PhoneNumber(country: "1", number: "9963191901"), - /// website: nil, - /// taxID: "934-00-2376", - /// info: "He sells cheese. Rich cheese." - /// ) + /// - Parameters: + /// - email: The merchant email address. This email must be listed in the merchant's PayPal profile. + /// - business: The merchant's business name. + /// - firstName: The merchant's first name. + /// - lastName: The merchant's last name. + /// - address: The merchant's address. + /// - phone: The merchant's phone number. + /// - fax: The merchant's fax number. + /// - website: The merchant's website. + /// - taxID: The merchant's tax ID. + /// - info: Any additional information, such as business hours. public init( - email: String?, - business: String?, - firstName: String?, - lastName: String?, + email: Failable>, + business: Failable>, + firstName: Failable>, + lastName: Failable>, address: Address?, phone: PhoneNumber?, fax: PhoneNumber?, - website: String?, - taxID: String?, - info: String? + website: Failable>, + taxID: Failable>, + info: Failable> )throws { self.email = email self.business = business diff --git a/Sources/PayPal/Models/Money/Amount.swift b/Sources/PayPal/Models/Money/Amount.swift index 4dfa5cf7..dcfa46bf 100644 --- a/Sources/PayPal/Models/Money/Amount.swift +++ b/Sources/PayPal/Models/Money/Amount.swift @@ -120,6 +120,6 @@ public struct AmountType: Content, Amount, Equatable where Key: AmountCodin } try container.encode(self.currency, forKey: .currency) - try container.encode(self.currency.string(for: self.value), forKey: .value) + try container.encode(rounded.description, forKey: .value) } } diff --git a/Sources/PayPal/Models/Payer/PaymentPayerInfo.swift b/Sources/PayPal/Models/Payer/PaymentPayerInfo.swift index 00b55418..1493565e 100644 --- a/Sources/PayPal/Models/Payer/PaymentPayerInfo.swift +++ b/Sources/PayPal/Models/Payer/PaymentPayerInfo.swift @@ -29,7 +29,7 @@ extension Order.Payer { public var email: Optional127String /// The birth date of the payer, in [Internet date format](https://tools.ietf.org/html/rfc3339#section-5.6). - public var birthdate: Date? + public var birthdate: TimelessDate? /// The payer's tax ID. Supported for the PayPal payment method only. /// @@ -71,7 +71,7 @@ extension Order.Payer { self.payer = nil self.email = email - self.birthdate = birthdate + self.birthdate = birthdate.map(TimelessDate.init) self.tax = tax self.taxType = taxType self.country = country @@ -82,15 +82,7 @@ extension Order.Payer { public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) - if - let string = try container.decodeIfPresent(String.self, forKey: .birthdate), - let date = TimelessDate.formatter.date(from: string) - { - self.birthdate = date - } else { - self.birthdate = nil - } - + self.birthdate = try container.decodeIfPresent(TimelessDate.self, forKey: .birthdate) self.salutation = try container.decodeIfPresent(String.self, forKey: .salutation) self.firstname = try container.decodeIfPresent(String.self, forKey: .firstname) self.middlename = try container.decodeIfPresent(String.self, forKey: .middlename) @@ -108,10 +100,7 @@ extension Order.Payer { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) - if let date = self.birthdate { - try container.encode(TimelessDate.formatter.string(from: date), forKey: .birthdate) - } - + try container.encodeIfPresent(self.birthdate, forKey: .birthdate) try container.encodeIfPresent(self.salutation, forKey: .salutation) try container.encodeIfPresent(self.firstname, forKey: .firstname) try container.encodeIfPresent(self.middlename, forKey: .middlename) diff --git a/Sources/PayPal/Models/Payment/Details/PaymentTerm.swift b/Sources/PayPal/Models/Payment/Details/PaymentTerm.swift index 7cdb56b6..ec7d72dd 100644 --- a/Sources/PayPal/Models/Payment/Details/PaymentTerm.swift +++ b/Sources/PayPal/Models/Payment/Details/PaymentTerm.swift @@ -8,7 +8,7 @@ public struct PaymentTerm: Content, Equatable { /// The date when the invoice payment is due, in [Internet date and time format](https://tools.ietf.org/html/rfc3339#section-5.6). /// For example, _yyyy-MM-dd z_. - public var due: Date? + public var due: TimelessDate? /// Creates a new `PaymentType` instance. /// @@ -17,20 +17,15 @@ public struct PaymentTerm: Content, Equatable { /// - due: The date when the invoice payment is due, in Internet date and time format. public init(type: TermType?, due: Date?) { self.type = type - self.due = due + self.due = due.map(TimelessDate.init) } /// See [`Decodable.init(from:)`](https://developer.apple.com/documentation/swift/decodable/2894081-init). public init(from decoder: Decoder)throws { let container = try decoder.container(keyedBy: CodingKeys.self) - let dueStr = try container.decode(String.self, forKey: .due) - guard let due = TimelessDate.formatter.date(from: dueStr) else { - throw DecodingError.dataCorruptedError(forKey: .due, in: container, debugDescription: "Date format must be `yyyy-MM-dd`") - } - - self.due = due - self.type = try container.decode(TermType.self, forKey: .type) + self.due = try container.decodeIfPresent(TimelessDate.self, forKey: .due) + self.type = try container.decodeIfPresent(TermType.self, forKey: .type) } /// See [`Encodable.encode(to:)`](https://developer.apple.com/documentation/swift/encodable/2893603-encode). @@ -38,10 +33,7 @@ public struct PaymentTerm: Content, Equatable { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(self.type, forKey: .type) - - if let due = self.due { - try container.encode(TimelessDate.formatter.string(from: due), forKey: .due) - } + try container.encodeIfPresent(self.due, forKey: .due) } enum CodingKeys: String, CodingKey { diff --git a/Sources/PayPal/Models/Template/TemplateList.swift b/Sources/PayPal/Models/Template/TemplateList.swift index be20e2c4..eeb702d9 100644 --- a/Sources/PayPal/Models/Template/TemplateList.swift +++ b/Sources/PayPal/Models/Template/TemplateList.swift @@ -13,7 +13,7 @@ extension Template { public var addresses: [Address]? /// An array of email addresses in the user's PayPal profile. - public var emails: [Email]? + public var emails: Failable<[String]?, NotNilValidate>> /// An array of phone numbers in the user's PayPal profile. public var phones: [PhoneNumber]? @@ -26,7 +26,18 @@ extension Template { /// /// Instead of creating a `TemplateList` with this initializer, you will most likely want to create it /// be decoding it from a JSON response from the PayPal API. - public init(addresses: [Address]?, emails: [Email]?, phones: [PhoneNumber]?, templates: [Template]?) { + /// + /// - Parameters: + /// - addresses: An array of postal addresses in the user's PayPal profile. + /// - emails: An array of email addresses in the user's PayPal profile. + /// - phones: An array of phone numbers in the user's PayPal profile. + /// - temapltes: The details for each template. + public init( + addresses: [Address]?, + emails: Failable<[String]?, NotNilValidate>>, + phones: [PhoneNumber]?, + templates: [Template]? + ) { self.links = nil self.addresses = addresses self.emails = emails diff --git a/Sources/PayPal/Models/TimelessDate.swift b/Sources/PayPal/Models/TimelessDate.swift index 001e4c3f..2a87a890 100644 --- a/Sources/PayPal/Models/TimelessDate.swift +++ b/Sources/PayPal/Models/TimelessDate.swift @@ -3,33 +3,35 @@ import Vapor /// The stand-alone date, in [Internet date and time format](https://tools.ietf.org/html/rfc3339#section-5.6). To represent special legal values, /// such as a date of birth, you should use dates with no associated time or time-zone data. Whenever possible, use the standard `date_time` type. public struct TimelessDate: Content, Equatable, ExpressibleByFloatLiteral { - internal static let formatter: DateFormatter = { + internal static let threadSafeFormatter: ThreadSpecificVariable = { let formatter = DateFormatter() formatter.calendar = Calendar(identifier: .iso8601) formatter.locale = Locale(identifier: "en_US_POSIX") formatter.timeZone = TimeZone(secondsFromGMT: 0) formatter.dateFormat = "yyyy-MM-dd" - return formatter + return ThreadSpecificVariable(value: formatter) }() - /// The UNIX timestamp for the date being represented. - /// - /// This timestamp is converted to a date and then formated for encoding and decoding. - public var timestamp: TimeInterval? + internal static var formatter: DateFormatter? { + return self.threadSafeFormatter.currentValue + } + + /// The underlying data for the date. + public var date: Date /// Creates a new `TimelessDate` instance from a `Date`. /// - /// - Parameter date: The `Date` instance to get the timestamp from. - public init(_ date: Date?) { - self.timestamp = date?.timeIntervalSince1970 + /// - Parameter date: The `Date` instance. + public init(_ date: Date) { + self.date = Calendar(identifier: .iso8601).date(bySettingHour: 0, minute: 0, second: 0, of: date) ?? date } /// Creates a new `TimelessDate` instance from a `String`. /// /// - Parameter date: The date representation, formatted as `yyyy-mm-dd`. - public init?(date: String?) { - guard let string = date, let date = TimelessDate.formatter.date(from: string) else { return nil } - self.timestamp = date.timeIntervalSince1970 + public init?(string: String) { + guard let date = TimelessDate.formatter?.date(from: string) else { return nil } + self.date = date } /// Creates a new `TimelessDate` instance from a `TimeInterval` (`Double`) instance. @@ -41,32 +43,29 @@ public struct TimelessDate: Content, Equatable, ExpressibleByFloatLiteral { /// /// - Parameter floatLiteral: The timestamp to use for the date. public init(floatLiteral value: TimeInterval) { - self.timestamp = value + self.date = Date(timeIntervalSince1970: value) } /// See [`Decodable.init(from:)`](https://developer.apple.com/documentation/swift/decodable/2894081-init). public init(from decoder: Decoder)throws { - if let raw = try decoder.container(keyedBy: CodingKeys.self).decodeIfPresent(String.self, forKey: .date) { - guard let date = TimelessDate.formatter.date(from: raw) else { - throw PayPalError(status: .badRequest, identifier: "dateFormat", reason: "Expected date to be formatted as `yyyy-mm-dd`") - } - self.timestamp = date.timeIntervalSince1970 - } else { - self.timestamp = nil + let container = try decoder.singleValueContainer() + let raw = try container.decode(String.self) + + guard let date = TimelessDate.formatter?.date(from: raw) else { + throw PayPalError( + status: .badRequest, + identifier: "dateFormat", + reason: "Expected date to be formatted as `yyyy-mm-dd`" + ) } + self.date = date } /// See [`Encodable.encode(to:)`](https://developer.apple.com/documentation/swift/encodable/2893603-encode). public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - if let timestamp = self.timestamp { - let date = Date(timeIntervalSince1970: timestamp) - let raw = TimelessDate.formatter.string(from: date) - try container.encode(raw, forKey: .date) - } - } - - enum CodingKeys: String, CodingKey { - case date = "date_no_time" + var container = encoder.singleValueContainer() + + let raw = TimelessDate.formatter?.string(from: self.date) + try container.encode(raw) } } diff --git a/Sources/PayPal/Utilities/ISO8601.swift b/Sources/PayPal/Utilities/ISO8601.swift index 17cc2c24..7a9154bc 100644 --- a/Sources/PayPal/Utilities/ISO8601.swift +++ b/Sources/PayPal/Utilities/ISO8601.swift @@ -5,17 +5,18 @@ import Foundation extension DateFormatter { /// A formatter for ISO 8601 dates. - public static let iso8601: Formatter = { - if #available(OSX 10.12, *) { - return ISO8601DateFormatter() - } else { - let formatter = DateFormatter() - formatter.calendar = Calendar(identifier: .iso8601) - formatter.locale = Locale(identifier: "en_US_POSIX") - formatter.timeZone = TimeZone(secondsFromGMT: 0) - formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX" - return formatter - } + /// + /// The date format pattern is `yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX`, so a `Date` instance + /// converted to a string will look something like this: + /// + /// "2019-03-04T11:28:36.000Z" + public static let iso8601: DateFormatter = { + let formatter = DateFormatter() + formatter.calendar = Calendar(identifier: .iso8601) + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX" + return formatter }() } @@ -30,26 +31,34 @@ extension Date { /// /// - Parameter iso8601: The string that has the date. public init?(iso8601: String) { - let converter: ((String) -> Date?)? - if #available(OSX 10.12, *) { - converter = (DateFormatter.iso8601 as? ISO8601DateFormatter)?.date - } else { - converter = (DateFormatter.iso8601 as? DateFormatter)?.date - } - guard let date = converter?(iso8601) else { return nil } + guard let date = DateFormatter.iso8601.date(from: iso8601) else { return nil } self = date } } +/// A `Date` container that encodes/decodes the instance as an ISO8601 string. public struct ISO8601Date: Codable, Hashable { + + /// The `Date` instance that the `ISO8601Date` instance wraps. public let date: Date + + /// The string that the `date` property was decoded from. public let raw: String? + /// Creates a new `ISO8601Date` instance from a `Date`. + /// + /// - Parameter date: The `Date` instance to wrap. public init(_ date: Date) { self.date = date self.raw = nil } + /// Creates a new `ISOL8601Date` instance from a formatted date string. + /// + /// If a `Date` instance cannnot be created from the string passed in, `nil` will be returned from the initializer. + /// + /// - Parameter string: The string to decode the `Date` from. + /// This is also the value that the `raw` property will be set to. public init?(string: String) { guard let date = Date(iso8601: string) else { return nil @@ -59,6 +68,7 @@ public struct ISO8601Date: Codable, Hashable { self.raw = string } + /// See [`Decodable.init(from:)`](https://developer.apple.com/documentation/swift/decodable/2894081-init). public init(from decoder: Decoder)throws { let decoder = try decoder.singleValueContainer() let raw = try decoder.decode(String.self) @@ -70,11 +80,13 @@ public struct ISO8601Date: Codable, Hashable { self.date = date } + /// See [`Encodable.encode(to:)`](https://developer.apple.com/documentation/swift/encodable/2893603-encode). public func encode(to encoder: Encoder)throws { var container = encoder.singleValueContainer() try container.encode(self.date.iso8601) } + /// See [`Equatable.==(lhs:rhs:)`](https://developer.apple.com/documentation/swift/equatable/1539854). public static func ==(lhs: ISO8601Date, rhs: ISO8601Date) -> Bool { let lRaw = lhs.raw ?? lhs.date.iso8601 let rRaw = rhs.raw ?? rhs.date.iso8601 @@ -83,6 +95,13 @@ public struct ISO8601Date: Codable, Hashable { } } +/// Compares the ISO8601 string of the date wrapped by a `ISO8601Date` instance and another `Date` instance. +/// +/// - Parameters: +/// - lhs: The `ISO8601Date` instance check against the `Date` on the right. +/// - rhs: The `Date` instance to check against the instance wrapped by the `ISO8601Date`. +/// +/// - Returns: A boolean indicating whether the ISO8601 strings of the `Date` instances match or not. public func ==(lhs: ISO8601Date, rhs: Date) -> Bool { return lhs.date.iso8601 == rhs.iso8601 } diff --git a/Sources/PayPal/Utilities/MultipartRelatedCoding.swift b/Sources/PayPal/Utilities/MultipartRelatedCoding.swift index d201b9ee..efbed3ef 100644 --- a/Sources/PayPal/Utilities/MultipartRelatedCoding.swift +++ b/Sources/PayPal/Utilities/MultipartRelatedCoding.swift @@ -23,14 +23,6 @@ extension MultipartPart { } } -extension MultipartPart: MultipartPartConvertible { - /// /// Converts `self` to `MultipartPart`. In other words, we return `self`. - public func convertToMultipartPart() throws -> MultipartPart { return self } - - /// Converts a `MultipartPart` to `Self`. In other words, we return what is passed in. - public static func convertFromMultipartPart(_ part: MultipartPart) throws -> MultipartPart { return part } -} - extension Dictionary where Key: LosslessStringConvertible, Value == MultipartPartConvertible { /// Converts an dictionary of `String: MultipartPartConvertible` objects to keyed `MultipartPart`s diff --git a/Sources/PayPal/Utilities/PayPalRequest.swift b/Sources/PayPal/Utilities/PayPalRequest.swift deleted file mode 100644 index 51b1ed5a..00000000 --- a/Sources/PayPal/Utilities/PayPalRequest.swift +++ /dev/null @@ -1,95 +0,0 @@ -import Vapor - -extension Container { - func paypal( - _ method: HTTPMethod, - _ path: String, - parameters: QueryParamaters = QueryParamaters(), - headers: HTTPHeaders = [:], - auth: Bool = true, - body: Body? = nil - )throws -> Request where Body: Content { - let config = try self.make(Configuration.self) - let querystring = parameters.encode() - let path = config.environment.domain + "/" + path + (querystring == "" ? "" : "?" + querystring) - - var http = HTTPRequest(method: method, url: path, headers: headers) - if auth { - let auth = try self.make(AuthInfo.self) - guard let type = auth.type, let token = auth.token else { - throw Abort(.internalServerError, reason: "Attempted to make a PayPal request that requires auth before authenticating.") - } - - http.headers.replaceOrAdd(name: .authorization, value: type + " " + token) - } - - let request = Request(http: http, using: self) - if let body = body { - let contentType: MediaType = auth ? .json : .urlEncodedForm - try request.content.encode(body, as: contentType) - } - return request - } - - func paypal( - _ method: HTTPMethod, - _ path: String, - parameters: QueryParamaters = QueryParamaters(), - headers: HTTPHeaders = [:], - body: Body?, - as response: Result.Type = Result.self - ) -> Future where Body: Content, Result: Content { - #if DEBUG - var req: Request? - #endif - - return Future.flatMap(on: self) { () -> Future in - if try self.make(AuthInfo.self).tokenExpired == true { - return try self.make(PayPalClient.self).authenticate() - } else { - return self.future() - } - }.flatMap(to: Response.self) { - let request = try self.paypal(method, path, parameters: parameters, headers: headers, auth: true, body: body) - - #if DEBUG - if Env.get("PAYPAL_LOG_API_ERROR") == "TRUE" { req = request } - #endif - - return try self.client().send(request) - }.flatMap(to: Result.self) { response in - if !(200...299).contains(response.http.status.code) { - #if DEBUG - if Env.get("PAYPAL_LOG_API_ERROR") == "TRUE" { print(req!, "\n\n", response) } - #endif - - guard response.http.headers.firstValue(name: .contentType) == "application/json" else { - let body = response.http.body.data ?? Data() - let error = String(data: body, encoding: .utf8) - throw Abort(response.http.status, reason: error) - } - - return try response.content.decode(PayPalAPIError.self).catchFlatMap { _ in - return try response.content.decode(PayPalAPIIdentityError.self).map { error in throw error } - }.map { error in - throw error - } - } - - if Result.self is HTTPStatus.Type { - return self.future(response.http.status as! Result) - } - return try response.content.decode(Result.self) - } - } - - func paypal( - _ method: HTTPMethod, - _ path: String, - parameters: QueryParamaters = QueryParamaters(), - headers: HTTPHeaders = [:], - as response: Result.Type = Result.self - ) -> Future where Result: Content { - return self.paypal(method, path, parameters: parameters, headers: headers, body: nil as [String: String]?, as: Result.self) - } -} diff --git a/Sources/V1/Controllers/Vault/Vault.swift b/Sources/V1/Controllers/Vault/Vault.swift new file mode 100644 index 00000000..b212d326 --- /dev/null +++ b/Sources/V1/Controllers/Vault/Vault.swift @@ -0,0 +1,130 @@ +import PayPal +import Vapor + +/// As a merchant, you can use the Vault API to securely store customer credit cards in the PayPal vault rather +/// than on your server. When you use the API to store a customer credit card, the API returns the ID of the vaulted card. +/// To make a payment with the vaulted card, you specify this ID instead of credit card details. +/// For information, see the [Vault Integration Guide](https://developer.paypal.com/docs/integration/direct/vault/). +/// +/// - Note: PayPal does not validate credit card information that you store in the vault. +/// +/// - Warning: The use of the PayPal REST /vault APIs to accept credit card payments is restricted because the +/// merchant must enable but can no longer get approved for the REST direct credit cards (DCC) feature. Instead, +/// you can accept credit card payments with [Braintree Direct](https://www.braintreepayments.com/products/braintree-direct). +/// +/// # Credit Cards +/// +/// Use the `/credit-cards` resource to store a credit card in the vault, delete, show details for, list, +/// and update vaulted cards. +public final class Valut: VersionedController { + + /// See `VersionedController.client`. + public var client: PayPalClient + + /// See `VersionedController.resource` + public var resource: [String] + + /// The controller for the `/vault/credit-cards` resource. + public var creditCards: CreditCards { + return CreditCards(client: self.client) + } + + /// See `VersionedController.init(client:)`. + public init(client: PayPalClient) { + self.client = client + self.resource = ["vault"] + } +} + +extension Valut { + + /// The controller for the `/credit-cards` resource of the Vault API. + public final class CreditCards: VersionedController { + + /// See `VersionedController.client`. + public var client: PayPalClient + + /// See `VersionedController.resource` + public var resource: [String] + + /// See `VersionedController.init(client:)`. + public init(client: PayPalClient) { + self.client = client + self.resource = ["vault", "credit-cards"] + } + + /// Stores credit card details in the PayPal vault. To use the vaulted card to make a payment, specify this ID as the + /// `credit_card_id` in a + /// [`credit_card_token`](https://developer.paypal.com/docs/api/payments/#definition-credit_card_token) object. + /// If you include a payer_id when you store the credit card, you must also include that ID as the + /// `external_customer_id` in the `credit_card_token` object. To show details for, update, or delete the vaulted card, + /// use the ID of the vaulted credit card. + /// + /// A successful request returns the HTTP 201 Created status code and a JSON response body that shows credit card + /// details, including the ID of the vaulted card. + /// + /// - Parameter card: The credit card information to store in the customer's vault. + /// - Returns: The stored credit cardm wrapped in an `EventLoopFuture`. + public func store(_ card: CreditCard) -> EventLoopFuture { + return self.client.post(self.path, body: card, as: CreditCard.self) + } + + /// Lists vaulted credit cards. To filter the cards in the response, specify one or more optional query parameters. + /// + /// A successful request returns the HTTP 200 OK status code and a JSON response body that includes an array of + /// vaulted cards. Each item in the array shows card details. + /// + /// - Parameter parameters: The query parameters that will be sent with the request to the PayPal API. + /// The supported query keys are: + /// - `page_size` + /// - `page` + /// - `start_time` + /// - `end_time` + /// - `sort_order` + /// - `sort_by` + /// - `merchant_id` + /// - `external_card_id` + /// - `external_customer_id` + /// - `total_required` + /// + /// - Returns: A paginated list of the credit cards in the customer's vault. + public func list(parameters: QueryParamaters = QueryParamaters()) -> EventLoopFuture { + return self.client.get(self.path, parameters: parameters, as: CreditCard.List.self) + } + + /// Updates information for a vaulted credit card, by ID. In the JSON request body, specify the values to update. + /// + /// A successful request returns the HTTP 200 OK status code and a JSON response body that shows card details. + /// + /// - Parameters: + /// - id: The ID of the vaulted credit card to update. + /// - patches: An array of JSON patch objects to apply partial updates to resources. + /// + /// - Returns: The updated credit card information, wrapped in an `EventLoopFuture`. + public func update(card id: String, with patches: [Patch]) -> EventLoopFuture { + return self.client.patch(self.path + id, body: patches, as: CreditCard.self) + } + + /// Deletes a vaulted credit card, by ID. + /// + /// A successful request returns the HTTP 204 No Content status code with no JSON response body. + /// + /// - Parameter id: The ID of the vaulted credit card to delete. + /// - Returns: An empty `EventLoopFuture` that succeeds when the deletion completes. + public func delete(card id: String) -> EventLoopFuture { + return self.client.delete(self.path + id, as: HTTPStatus.self).transform(to: ()) + } + + /// Shows details for a vaulted credit card, by ID. + /// + /// A successful request returns the HTTP 200 OK status code and a JSON response body with card details. + /// + /// - Parameter id: The ID of the vaulted credit card for which to show details. + /// This ID is returned when you store the credit card in the PayPal vault. + /// + /// - Returns: The credit card information for the ID passed in, wrapped in an `EventLoopFuture`. + public func get(card id: String) -> EventLoopFuture { + return self.client.get(self.path + id, as: CreditCard.self) + } + } +} diff --git a/Sources/V1/Controllers/Webhooks/EventTypes.swift b/Sources/V1/Controllers/Webhooks/EventTypes.swift new file mode 100644 index 00000000..617f62b3 --- /dev/null +++ b/Sources/V1/Controllers/Webhooks/EventTypes.swift @@ -0,0 +1,32 @@ +import PayPal +import Vapor + +extension Webhooks { + + /// The controller for the `/webhooks-event-types` resource of the Webhooks PayPal API. + public final class EventTypes: VersionedController { + + /// See `VersionedController.client` + public let client: PayPalClient + + /// See `VersionedController.resource`. + public let resource: [String] + + /// See `VersionedController.init(client:)`. + public init(client: PayPalClient) { + self.client = client + self.resource = ["notifications", "webhooks-event-types"] + } + + /// Lists available events to which any webhook can subscribe. For a list of supported events, + /// see [Webhook event names](https://developer.paypal.com/docs/integration/direct/webhooks/event-names/). + /// + /// A successful request returns the HTTP 200 OK status code and a JSON response body that + /// lists available events to which any webhook can subscribe. + /// + /// - Returns: The list of `EventType` objects, wrapped in an `EventLoopFuture`. + public func list() -> EventLoopFuture<[EventType]> { + return self.client.get(self.path, as: [EventType].self) + } + } +} diff --git a/Sources/V1/Controllers/Webhooks/Events.swift b/Sources/V1/Controllers/Webhooks/Events.swift new file mode 100644 index 00000000..ed1cd024 --- /dev/null +++ b/Sources/V1/Controllers/Webhooks/Events.swift @@ -0,0 +1,74 @@ +import PayPal +import Vapor + +extension Webhooks { + + /// The controller for the `/webhooks-events` resource of the Webhooks PayPal API. + public final class Events: VersionedController { + + /// See `VersionedController.client` + public let client: PayPalClient + + /// See `VersionedController.resource`. + public let resource: [String] + + /// See `VersionedController.init(client:)`. + public init(client: PayPalClient) { + self.client = client + self.resource = ["notifications", "webhooks-events"] + } + + /// Lists webhook event notifications. Use query parameters to filter the response. + /// + /// A successful request returns the HTTP 200 OK status code and a JSON response body that + /// lists webhook event notifications. + /// + /// - Parameters: + /// - parameters: + /// - transaction: Filters the response to a single transaction, by ID. + /// - type: Filters the response to a single event. + /// + /// - Returns: The list of `Event` objects, along with count and related links. + public func list( + parameters: QueryParamaters = QueryParamaters(), + transaction: String? = nil, + type: String? = nil + ) -> EventLoopFuture { + var parameters = parameters + if let transaction = transaction { + parameters.custom?["transaction_id"] = transaction + } + if let eventType = type { + parameters.custom?["event_type"] = eventType + } + + return self.client.get(self.path, parameters: parameters, as: Event.List.self) + } + + /// Shows details for a webhook event notification, by ID. + /// + /// A successful request returns the HTTP 200 OK status code and a JSON response body that + /// shows webhook event notification details + /// + /// - Parameter event: The ID of the webhook event notification for which to show details. + /// - Returns: The `Event` object for the given ID, wrapped in an `EventLoopFuture`. + public func get(event: String) -> EventLoopFuture { + return self.client.get(self.path + event, as: Event.self) + } + + /// Resends a webhook event notification, by ID. Any pending notifications are not resent. + /// + /// A successful request returns the HTTP 202 Accepted status code and a JSON response body + /// that shows webhook event notification details. + /// + /// - Parameters: + /// - event: The ID of the webhook event notification to resend. + /// - ids: An array of webhook account IDs. + /// + /// - Returns: The `Event` object for the event that was resent, wrapped in an `EventLoopFuture`. + public func resend(event: String, ids: [String]) -> EventLoopFuture { + return self.client.post(self.path + event, body: ["webhook_ids": ids], as: Event.self) + } + } +} + diff --git a/Sources/V1/Controllers/Webhooks/SimulateEvent.swift b/Sources/V1/Controllers/Webhooks/SimulateEvent.swift new file mode 100644 index 00000000..57120352 --- /dev/null +++ b/Sources/V1/Controllers/Webhooks/SimulateEvent.swift @@ -0,0 +1,32 @@ +import PayPal +import Vapor + +extension Webhooks { + + /// The controller for the `/simulate-event` resource of the Webhooks PayPal API. + public final class SimulateEvents: VersionedController { + + /// See `VersionedController.client` + public let client: PayPalClient + + /// See `VersionedController.resource`. + public let resource: [String] + + /// See `VersionedController.init(client:)`. + public init(client: PayPalClient) { + self.client = client + self.resource = ["notifications", "simulate-event"] + } + + /// Simulates a webhook event. In the JSON request body, specify a sample payload. + /// + /// A successful request returns the HTTP 202 Accepted status code and a JSON response body that + /// shows details for the mock event. + /// + /// - Parameter event: The webhook event to simulate. This is the body of the request to PayPal. + /// - Returns: The mocked `Event` object, wrapped in an `EventLoopFuture`. + public func simulate(event: Event.Simulated) -> EventLoopFuture { + return self.client.post(self.path, body: event, as: Event.self) + } + } +} diff --git a/Sources/V1/Controllers/Webhooks/Verification.swift b/Sources/V1/Controllers/Webhooks/Verification.swift new file mode 100644 index 00000000..42193c47 --- /dev/null +++ b/Sources/V1/Controllers/Webhooks/Verification.swift @@ -0,0 +1,32 @@ +import PayPal +import Vapor + +extension Webhooks { + + /// The controller for the `/verify-webhook-signature` resource of the Webhooks PayPal API. + public final class Verification: VersionedController { + + /// See `VersionedController.client` + public let client: PayPalClient + + /// See `VersionedController.resource`. + public let resource: [String] + + /// See `VersionedController.init(client:)`. + public init(client: PayPalClient) { + self.client = client + self.resource = ["notifications", "verify-webhook-signature"] + } + + /// Verifies a webhook signature. + /// + /// A successful request returns the HTTP 200 OK status code and a JSON response + /// body that shows the verification status. + /// + /// - Parameter signature: The `Webhook` object signature that will be the request's body to be verified. + /// - Returns: The verification result, wrapped in an `EventLoopFuture`. + public func verify(signature: Webhook.Signature) -> EventLoopFuture { + return self.client.post(self.path, body: signature, as: Webhook.Signature.Result.self) + } + } +} diff --git a/Sources/V1/Controllers/Webhooks/Webhooks.swift b/Sources/V1/Controllers/Webhooks/Webhooks.swift new file mode 100644 index 00000000..5a89d9b1 --- /dev/null +++ b/Sources/V1/Controllers/Webhooks/Webhooks.swift @@ -0,0 +1,130 @@ +import PayPal +import Vapor + +/// The PayPal REST APIs use [webhooks](https://developer.paypal.com/docs/integration/direct/webhooks) for event notification. +/// Webhooks are HTTP callbacks that receive notification messages for events. After you configure a webhook listener for your +/// app, you can [create a webhook](https://developer.paypal.com/docs/api/webhooks/v1/#webhooks_create), which subscribes +/// the webhook listener for your app to events. The `notifications` namespace contains resource collections for webhooks. +/// +/// # Webhooks +/// +/// Use the `/webhooks` resource to create, show details for, list all, update, and delete webhooks. +/// +/// # Verify Webhook Signature +/// +/// Use the `/verify-webhook-signature` resource to verify a webhook signature. +/// +/// # Event Type +/// +/// Use the `/webhooks-event-types` resource to list events to which webhooks can subscribe and the +/// `/webhooks//event-types` resource to list event subscriptions for a webhook. +/// +/// # Simulate Event +/// +/// Use the `/simulate-event` resource to use a sample payload to simulate a webhook event. The events that this call +/// generates only serve to validate the connection to the listener URL and to show how webhook events look. +/// +/// - Note: You can also use the [Webhooks simulator](https://developer.paypal.com/docs/integration/direct/webhooks/simulator/) +/// to simulate webhook events. +public final class Webhooks: VersionedController { + + /// See `VersionedController.client` + public let client: PayPalClient + + /// See `VersionedController.resource`. + public let resource: [String] + + /// The controller for the `/notifications/verify-webhook-signature` resource. + public var verification: Verification { + return Verification(client: self.client) + } + + /// The controller for the `/notifications/webhooks-event-types` resource. + public var eventTypes: EventTypes { + return EventTypes(client: self.client) + } + + /// The controller for the `/notifications/webhooks-events` resource. + public var events: Events { + return Events(client: self.client) + } + + /// The controller for the `/notifications/simulate-event` resource. + public var simulateEvents: SimulateEvents { + return SimulateEvents(client: self.client) + } + + /// See `VersionedController.init(client:)`. + public init(client: PayPalClient) { + self.client = client + self.resource = ["notifications", "webhooks"] + } + + /// Subscribes your webhook listener to events. + /// + /// A successful request returns the HTTP 201 Created status code and a JSON response body with a + /// `Webhook` object that includes the webhook ID for later use. + /// + /// - Parameter webhook: The `Webhook` instance to create + public func create(webhook: Webhook) -> EventLoopFuture { + return self.client.post(self.path, body: webhook, as: Webhook.self) + } + + /// Lists all webhooks for an app. + /// + /// A successful request returns the HTTP 200 OK status code and a JSON response body that lists + /// webhooks with webhook details. + /// + /// - Parameter anchor: Filters the webhooks in the response by the `anchor_id` entity type. + /// - Returns: The webhooks that match the given `anchor` value, wrapped in an `EventLoopFuture`. + public func get(by anchor: Webhook.AnchorType = .application) -> EventLoopFuture<[Webhook]> { + let parameters = QueryParamaters(custom: ["anchor_type": anchor.rawValue]) + return self.client.get(self.path, parameters: parameters, as: [Webhook].self) + } + + /// Deletes a webhook, by ID. + /// + /// A successful request returns the HTTP 204 No Content status code with no JSON response body. + /// + /// - Parameter webhook: The ID of the webhook to delete. + /// - Returns: A void `EventLoopFuture` that succeedes when the delete completes. + public func delete(webhook: String) -> EventLoopFuture { + return self.client.delete(self.path + webhook, as: HTTPStatus.self).transform(to: ()) + } + + /// Replaces webhook fields with new values. Supports only the `replace` operation. Pass a `json_patch` object with + /// `replace` operation and `path`, which is `/url` for a URL or `/event_types` for events. The `value` is either + /// the URL or a list of events. + /// + /// A successful request returns the HTTP 200 OK status code and a JSON response body that shows webhook details. + /// + /// - Parameters: + /// - webhook: The ID of the webhook to update. + /// - patches: An array of JSON patch objects to apply partial updates to resources. + /// + /// - Returns: The updated `Webhook` object, wrapped in an `EventLoopFuture`. + public func update(webhook: String, with patches: [Patch]) -> EventLoopFuture { + return self.client.patch(self.path + webhook, body: patches, as: Webhook.self) + } + + /// Shows details for a webhook, by ID. + /// + /// A successful request returns the HTTP 200 OK status code and a JSON response body that shows webhook details + /// + /// - Parameter webhook: The ID of the webhook for which to show details. + /// - Returns: The `Webhook` object for the given ID, wrapped in an `EventLoopFuture`. + public func get(webhook: String) -> EventLoopFuture { + return self.client.get(self.path + webhook, as: Webhook.self) + } + + /// Lists event subscriptions for a webhook, by ID. + /// + /// A successful request returns the HTTP 200 OK status code and a JSON response body that lists event + /// subscriptions for a webhook. + /// + /// - Parameter webhook: The ID of the webhook for which to list subscriptions. + /// - Returns: The list of `EventType` objects for the webhook, wrapped in an `EventLoopFuture`. + public func eventTypes(for webhook: String) -> EventLoopFuture<[EventType]> { + return self.client.get(self.path + webhook + "/event-types", as: [EventType].self) + } +} diff --git a/Sources/V1/Models/Vault/CreditCard.swift b/Sources/V1/Models/Vault/CreditCard.swift new file mode 100644 index 00000000..0560d696 --- /dev/null +++ b/Sources/V1/Models/Vault/CreditCard.swift @@ -0,0 +1,219 @@ +import Foundation +import PayPal + +/// The credit card data sotred in PayPal Vault. +public struct CreditCard: Codable { + + /// The ID of the vaulted credit card, which you can use to fund a payment. + public let id: String? + + /// The credit card number. Value is a string of numeric characters with no spaces or punctuation. + /// Must conform to modulo and the required length for the credit card type. Redacted in responses. + public var number: Failable + + /// The credit card type. + public var type: CreditCardType + + /// A date in the month and year that the card expires. + public var expiry: Date + + /// The first name of the credit card holder. + public var firstName: Failable> + + /// The last name of the credit card holder. + public var lastName: String? + + /// The billing address for this card. Supports only the `address_line_1`, `address_line_2`, `admin_area_1`, + /// `admin_area_2`, `postal_code`, and `country_code` properties. + public var billing: Address? + + /// The externally-provided ID of the customer. + public var externalCustomer: Failable> + + /// The ID of the merchant. + public var merchant: Failable> + + /// The externally-provided ID of the credit card. + public var externalCard: Failable> + + /// The state of the credit card funding instrument. + public let state: State? + + /// The date and time when the vaulted credit card was created. + public let created: ISO8601Date? + + /// The date and time when the vaulted credit card was updated. + public let updated: ISO8601Date? + + /// The date and time when the credit card becomes unusable from the vault. The `valid_until` parameter is not the same + /// as the expiration month and year. The expiration month and year might be later than the `valid_until` date. + /// For example, the card expires in November 2019 but the `valid_until` date is October 17th, 2019. + public let valueTo: ISO8601Date? + + /// An array of request-related + /// [HATEOAS links](https://developer.paypal.com/docs/api/reference/api-responses/#hateoas-links). + public let links: [LinkDescription]? + + /// Creates a new `CreditCard` instance. + /// + /// - Parameters: + /// - number: The credit card number. + /// - type: The credit card type. + /// - expiry: A date in the month and year that the card expires. + /// - firstName: The first name of the credit card holder. + /// - lastName: The last name of the credit card holder. + /// - billing: The billing address for this card. + /// - externalCustomer: The externally-provided ID of the customer. + /// - merchant: The ID of the merchant. + /// - externalCard: The externally-provided ID of the credit card. + public init( + number: Failable, + type: CreditCardType, + expiry: Date, + firstName: Failable>, + lastName: String?, + billing: Address?, + externalCustomer: Failable>, + merchant: Failable>, + externalCard: Failable> + ) { + var calendar = Calendar(identifier: .iso8601) + calendar.timeZone = TimeZone(secondsFromGMT: 0) ?? calendar.timeZone + + self.id = nil + self.state = nil + self.created = nil + self.updated = nil + self.valueTo = nil + self.links = nil + + self.number = number + self.type = type + self.expiry = calendar.date(from: calendar.dateComponents([.year, .month], from: expiry)) ?? expiry + self.firstName = firstName + self.lastName = lastName + self.billing = billing + self.externalCustomer = externalCustomer + self.merchant = merchant + self.externalCard = externalCard + } + + /// See [`Decodable.init(from:)`](https://developer.apple.com/documentation/swift/decodable/2894081-init). + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + let expireMonth = try Int(container.decode(String.self, forKey: .expiryMonth)) + let expireYear = try Int(container.decode(String.self, forKey: .expiryYear)) + guard + let expiry = Calendar(identifier: .iso8601).date(from: DateComponents( + timeZone: TimeZone(secondsFromGMT: 0), + year: expireYear, + month: expireMonth + )) + else { + throw DecodingError.dataCorrupted(DecodingError.Context( + codingPath: [CodingKeys.expiryYear, CodingKeys.expiryMonth], + debugDescription: "Cannot convert `expire_month` and `expire_year` values to a vlid date" + )) + } + + self.expiry = expiry + self.id = try container.decodeIfPresent(String.self, forKey: .id) + self.number = try container.decode(Failable.self, forKey: .number) + self.type = try container.decode(CreditCardType.self, forKey: .type) + self.firstName = try container.decode(Failable>.self, forKey: .firstName) + self.lastName = try container.decodeIfPresent(String.self, forKey: .lastName) + self.billing = try container.decodeIfPresent(Address.self, forKey: .billing) + self.externalCustomer = try container.decode(Failable>.self, forKey: .externalCustomer) + self.merchant = try container.decode(Failable>.self, forKey: .merchant) + self.externalCard = try container.decode(Failable>.self, forKey: .externalCard) + self.state = try container.decodeIfPresent(State.self, forKey: .state) + self.created = try container.decodeIfPresent(ISO8601Date.self, forKey: .created) + self.updated = try container.decodeIfPresent(ISO8601Date.self, forKey: .updated) + self.valueTo = try container.decodeIfPresent(ISO8601Date.self, forKey: .validTo) + self.links = try container.decodeIfPresent([LinkDescription].self, forKey: .links) + } + + /// See [`Encodable.encode(to:)`](https://developer.apple.com/documentation/swift/encodable/2893603-encode). + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + let calendar = Calendar(identifier: .iso8601) + let components = calendar.dateComponents([.year, .month], from: self.expiry) + try container.encodeIfPresent(components.year.map(String.init(describing:)), forKey: .expiryYear) + try container.encodeIfPresent(components.month.map(String.init(describing:)), forKey: .expiryMonth) + + try container.encodeIfPresent(self.id, forKey: .id) + try container.encode(self.number, forKey: .number) + try container.encode(self.type, forKey: .type) + try container.encode(self.firstName, forKey: .firstName) + try container.encodeIfPresent(self.lastName, forKey: .lastName) + try container.encodeIfPresent(self.billing, forKey: .billing) + try container.encode(self.externalCustomer, forKey: .externalCustomer) + try container.encode(self.merchant, forKey: .merchant) + try container.encode(self.externalCard, forKey: .externalCard) + try container.encodeIfPresent(self.state, forKey: .state) + try container.encodeIfPresent(self.created, forKey: .created) + try container.encodeIfPresent(self.updated, forKey: .updated) + try container.encodeIfPresent(self.valueTo, forKey: .validTo) + try container.encodeIfPresent(self.links, forKey: .links) + } + + /// The validator for the `CardCard.number` property value. + public struct Number: RegexValidation { + + /// See `RegexValidator.patter`. + public static let pattern: String = #"^\d{13,19}$"# + } + + /// The validator for the `CreditCard.firstName` property value. + public struct FirstName: StringLengthValidation { + + /// See `StringLengthValidation.maxLength`. + public static let maxLength: Int = 25 + } + + /// The states of a credit card funding instrument. + public enum State: String, Hashable, CaseIterable, Codable { + + /// The credit card is past it's expiration date. + case expired + + /// The creadit card has not expired yet. + case ok + } + + enum CodingKeys: String, CodingKey { + case id, number, type, state, links + case expiryMonth = "expire_month" + case expiryYear = "expire_year" + case firstName = "first_name" + case lastName = "last_name" + case billing = "billing_address" + case externalCustomer = "external_customer_id" + case merchant = "merchant_id" + case externalCard = "external_card_id" + case created = "create_time" + case updated = "update_time" + case validTo = "valid_until" + } +} + +/// The valid card brand or network options for a `CreditCard` instance. +public enum CreditCardType: String, Hashable, CaseIterable, Codable { + + /// `visa`. + case visa + + /// `mastercard`. + case mastercard + + /// `amex`. + case amex + + /// `discover`. + case discover + + /// `maestro`. + case maestro +} diff --git a/Sources/V1/Models/Vault/CreditCardList.swift b/Sources/V1/Models/Vault/CreditCardList.swift new file mode 100644 index 00000000..12494723 --- /dev/null +++ b/Sources/V1/Models/Vault/CreditCardList.swift @@ -0,0 +1,41 @@ +import PayPal + +extension CreditCard { + + /// A paginated list of credit cards from a user's vault. + public struct List: Codable { + + /// An array of credit card objects. + public var cards: [CreditCard]? + + /// The total number of items. + public var count: Int32? + + /// The total number of pages. + public var pages: Int32? + + /// An array of request-specific + /// [HATEOAS links](https://developer.paypal.com/docs/api/reference/api-responses/#hateoas-links). + public let links: [LinkDescription]? + + /// Creates a new `CreditCard.List` struct. + /// + /// - Parameters: + /// - cards: An array of credit card objects. + /// - count: The total number of items. + /// - pages: The total number of pages. + public init(cards: [CreditCard]?, count: Int32?, pages: Int32?) { + self.cards = cards + self.count = count + self.pages = pages + self.links = nil + } + + enum CodingKeys: String, CodingKey { + case links + case cards = "items" + case count = "total_items" + case pages = "total_pages" + } + } +} diff --git a/Sources/V1/Models/Webhook/Event.swift b/Sources/V1/Models/Webhook/Event.swift new file mode 100644 index 00000000..63c7c389 --- /dev/null +++ b/Sources/V1/Models/Webhook/Event.swift @@ -0,0 +1,108 @@ +import PayPal + +public struct Event: Codable { + + /// The ID of the webhook event notification. + public let id: String? + + /// The date and time when the webhook event notification was created. + public let created: ISO8601Date? + + /// The name of the resource related to the webhook notification event. + public let resourceType: String? + + /// The event version in the webhook notification. + public let version: EventType.Version? + + /// The event that triggered the webhook event notification. + public let type: EventType.Name? + + /// A summary description for the event notification. + public let summary: String? + + /// The resource version in the webhook notification. + public let resourceVersion: EventType.Version? + + /// The resource that triggered the webhook event notification. + public let resource: Resource? + + /// An array of request-related [HATEOAS links](https://developer.paypal.com/docs/api/hateoas-links). + public let links: [LinkDescription]? + + public struct Simulated: Codable { + + /// The ID of the webhook. If omitted, the URL is required. + public var webhook: String? + + /// The URL for the webhook endpoint. If omitted, the webhook ID is required. + public var url: String? + + /// The event name. Specify one of the subscribed events. For each request, provide only one event. + public var type: EventType.Name + + /// The identifier for event type ex: 1.0/2.0 etc. + public var version: EventType.Version? + + /// Creates a new `Event.Simulated` instance. + /// + /// - Parameters: + /// - webhook: The ID of the webhook. If omitted, the URL is required. + /// - url: The URL for the webhook endpoint. If omitted, the webhook ID is required. + /// - type: The event name. Specify one of the subscribed events. + /// - version: The identifier for event type ex: 1.0/2.0 etc. + public init(webhook: String?, url: String?, type: EventType.Name, version: EventType.Version?) { + self.webhook = webhook + self.url = url + self.type = type + self.version = version + } + + enum CodingKeys: String, CodingKey { + case webhook = "webhook_id" + case url + case type = "event_type" + case version = "resource_version" + } + } + + /// The response structure for a call to `Webhooks.Events.list( + public struct List: Codable { + + /// An array of webhooks events. + public var events: [Event]? + + /// The number of items in each range of results. Note that the response might have fewer items + /// than the requested `page_size` value. + public var count: Int? + + /// An array of request-related [HATEOAS links](https://developer.paypal.com/docs/api/overview/#hateoas-links). + public let links: [LinkDescription]? + } + + enum CodingKeys: String, CodingKey { + case id, summary, resource, links + case created = "create_time" + case resourceType = "resource_type" + case version = "event_version" + case type = "event_type" + case resourceVersion = "resource_version" + } +} + +public struct Resource: Codable { + public let id: String? + public let created: ISO8601Date? + public let updated: ISO8601Date? + public let state: String? + public let amount: DetailedAmount? + public let parent: String? + public let validTo: ISO8601Date? + + enum CodingKeys: String, CodingKey { + case id, state, amount + case created = "create_time" + case updated = "update_time" + case parent = "parent_payment" + case validTo = "valid_until" + } +} diff --git a/Sources/V1/Models/Webhook/EventType.swift b/Sources/V1/Models/Webhook/EventType.swift new file mode 100644 index 00000000..de5e5833 --- /dev/null +++ b/Sources/V1/Models/Webhook/EventType.swift @@ -0,0 +1,289 @@ +import Failable + +/// An event that will fire a registered webhook. +public struct EventType: Codable { + + /// The unique event name. + public var name: Name + + /// A human-readable description of the event. + public let description: String? + + /// The status of a webhook event. + public let status: String? + + /// The resource versions in the webhook notification. + public let versions: [Version]? + + /// Creates a new `EventType` instance. + /// + /// - Parameters: + /// - name: The unique event name. + /// - description: A human-readable description of the event. + /// - status: The status of a webhook event. + /// - versions: The resource versions in the webhook notification. + public init( + name: Name, + description: String?, + status: String?, + versions: [Version]? + ) { + self.name = name + self.description = description + self.status = status + self.versions = versions + } + + /// The validator for the `EventType.versions` property value. + public struct Version: Codable { + + /// The value which makes the major value of the version, i.e. `1.x`. + public var major: Int + + /// The value which makes the minor value of the version, i.e. `x.0`. + public var minor: Int + + /// Creates a new `EventType.Version` instance. + /// + /// - Parameters: + /// - major: The value which makes the major value of the version. + /// - minor: The value which makes the minor value of the version. + public init(major: Int, minor: Int) { + self.major = major + self.minor = minor + } + + /// Creates an `EventType` instance. + /// + /// - Parameter string: A string containing the version data, i.e. `1.0`. + public init?(_ string: String) { + + // FIXME: - We only convert to a `String` because otherwise we get a compiler crash. + // Remove that operation when the compiler gets fixed: https://bugs.swift.org/browse/SR-10305 + let components = string.split(separator: ".").map(String.init) + guard components.count == 2 else { return nil } + guard let major = components.first.flatMap(Int.init) else { return nil } + guard let minor = components.last.flatMap(Int.init) else { return nil } + + self.major = major + self.minor = minor + } + + /// See [`Decodable.init(from:)`](https://developer.apple.com/documentation/swift/decodable/2894081-init). + public init(from decoder: Decoder)throws { + let container = try decoder.singleValueContainer() + let version = try container.decode(String.self) + + guard let instance = Version(version) else { + throw DecodingError.dataCorruptedError( + in: container, + debugDescription: "Cannot get version components from string \(version)" + ) + } + + self = instance + } + + /// See [`Encodable.encode(to:)`](https://developer.apple.com/documentation/swift/encodable/2893603-encode). + public func encode(to encoder: Encoder)throws { + var container = encoder.singleValueContainer() + let version = "\(self.major).\(self.minor)" + + try container.encode(version) + } + } + + /// The webhook events that are supported by PayPal. + public enum Name: String, Hashable, CaseIterable, Codable { + + /// `PAYMENT.AUTHORIZATION.CREATED` + case authorizationCreated = "PAYMENT.AUTHORIZATION.CREATED" + + /// `PAYMENT.AUTHORIZATION.VOIDED` + case authorizationVoided = "PAYMENT.AUTHORIZATION.VOIDED" + + /// `PAYMENT.CAPTURE.COMPLETED` + case captureCompleted = "PAYMENT.CAPTURE.COMPLETED" + + /// `PAYMENT.CAPTURE.DENIED` + case captureDenied = "PAYMENT.CAPTURE.DENIED" + + /// `PAYMENT.CAPTURE.PENDING` + case capturePending = "PAYMENT.CAPTURE.PENDING" + + /// `PAYMENT.CAPTURE.REFUNDED` + case captureRefunded = "PAYMENT.CAPTURE.REFUNDED" + + /// `PAYMENT.CAPTURE.REVERSED` + case captureReversed = "PAYMENT.CAPTURE.REVERSED" + + + /// `PAYMENT.PAYOUTSBATCH.DENIED` + case payoutbatchDenied = "PAYMENT.PAYOUTSBATCH.DENIED" + + /// `PAYMENT.PAYOUTSBATCH.PROCESSING` + case payoutbatchProcessing = "PAYMENT.PAYOUTSBATCH.PROCESSING" + + /// `PAYMENT.PAYOUTSBATCH.SUCCESS` + case payoutbatchSuccess = "PAYMENT.PAYOUTSBATCH.SUCCESS" + + /// `PAYMENT.PAYOUTS-ITEM.BLOCKED` + case payoutItemBlocked = "PAYMENT.PAYOUTS-ITEM.BLOCKED" + + /// `PAYMENT.PAYOUTS-ITEM.CANCELED` + case payoutItemCanceled = "PAYMENT.PAYOUTS-ITEM.CANCELED" + + /// `PAYMENT.PAYOUTS-ITEM.DENIED` + case payoutItemDenied = "PAYMENT.PAYOUTS-ITEM.DENIED" + + /// `PAYMENT.PAYOUTS-ITEM.FAILED` + case payoutItemFailed = "PAYMENT.PAYOUTS-ITEM.FAILED" + + /// `PAYMENT.PAYOUTS-ITEM.HELD` + case payoutItemHeld = "PAYMENT.PAYOUTS-ITEM.HELD" + + /// `PAYMENT.PAYOUTS-ITEM.REFUNDED` + case payoutItemRefunded = "PAYMENT.PAYOUTS-ITEM.REFUNDED" + + /// `PAYMENT.PAYOUTS-ITEM.RETURNED` + case payoutItemReturned = "PAYMENT.PAYOUTS-ITEM.RETURNED" + + /// `PAYMENT.PAYOUTS-ITEM.SUCCEEDED` + case payoutItemSucceeded = "PAYMENT.PAYOUTS-ITEM.SUCCEEDED" + + /// `PAYMENT.PAYOUTS-ITEM.UNCLAIMED` + case payoutItemUnclaimed = "PAYMENT.PAYOUTS-ITEM.UNCLAIMED" + + + /// `BILLING_AGREEMENTS.AGREEMENT.CREATED` + case agreementCreated = "BILLING_AGREEMENTS.AGREEMENT.CREATED" + + /// `BILLING_AGREEMENTS.AGREEMENT.CANCELLED` + case agreementCancelled = "BILLING_AGREEMENTS.AGREEMENT.CANCELLED" + + /// `BILLING.PLAN.CREATED` + case planCreated = "BILLING.PLAN.CREATED" + + /// `BILLING.PLAN.UPDATED` + case planeUpdated = "BILLING.PLAN.UPDATED" + + /// `BILLING.SUBSCRIPTION.CANCELLED` + case subscriptionCancelled = "BILLING.SUBSCRIPTION.CANCELLED" + + /// `BILLING.SUBSCRIPTION.CREATED` + case subscriptionCreated = "BILLING.SUBSCRIPTION.CREATED" + + /// `BILLING.SUBSCRIPTION.RE-ACTIVATED` + case subscriptionReactivated = "BILLING.SUBSCRIPTION.RE-ACTIVATED" + + /// `BILLING.SUBSCRIPTION.SUSPENDED` + case subscriptionSuspended = "BILLING.SUBSCRIPTION.SUSPENDED" + + /// `BILLING.SUBSCRIPTION.UPDATED` + case subscriptionUpdated = "BILLING.SUBSCRIPTION.UPDATED" + + + /// `IDENTITY.AUTHORIZATION-CONSENT.REVOKED` + case authorizationConsentRevoked = "IDENTITY.AUTHORIZATION-CONSENT.REVOKED" + + + /// `CUSTOMER.DISPUTE.CREATED` + case disputeCreated = "CUSTOMER.DISPUTE.CREATED" + + /// `CUSTOMER.DISPUTE.RESOLVED` + case disputeResolved = "CUSTOMER.DISPUTE.RESOLVED" + + /// `CUSTOMER.DISPUTE.UPDATED` + case disputeUpdated = "CUSTOMER.DISPUTE.UPDATED" + + /// `RISK.DISPUTE.CREATED` + case riskDisputeCreated = "RISK.DISPUTE.CREATED" + + + /// `INVOICING.INVOICE.CANCELLED` + case invoiceCancelled = "INVOICING.INVOICE.CANCELLED" + + /// `INVOICING.INVOICE.CREATED` + case invoiceCreated = "INVOICING.INVOICE.CREATED" + + /// `INVOICING.INVOICE.PAID` + case invoicePaid = "INVOICING.INVOICE.PAID" + + /// `INVOICING.INVOICE.REFUNDED` + case invoiceRefunded = "INVOICING.INVOICE.REFUNDED" + + /// `INVOICING.INVOICE.SCHEDULED` + case invoiceScheduled = "INVOICING.INVOICE.SCHEDULED" + + /// `INVOICING.INVOICE.UPDATED` + case invoiceUpdtaed = "INVOICING.INVOICE.UPDATED" + + + /// `MERCHANT.ONBOARDING.COMPLETED` + case onboardingComplete = "MERCHANT.ONBOARDING.COMPLETED" + + /// `MERCHANT.PARTNER-CONSENT.REVOKED` + case partnerConsentRevoked = "MERCHANT.PARTNER-CONSENT.REVOKED" + + + /// `CHECKOUT.ORDER.PROCESSED` + case checkoutProcessed = "CHECKOUT.ORDER.PROCESSED" + + /// `CUSTOMER.ACCOUNT-LIMITATION.ADDED` + case accountLimitationAdded = "CUSTOMER.ACCOUNT-LIMITATION.ADDED" + + /// `CUSTOMER.ACCOUNT-LIMITATION.ESCALATED` + case accountLimitationEscalated = "CUSTOMER.ACCOUNT-LIMITATION.ESCALATED" + + /// `CUSTOMER.ACCOUNT-LIMITATION.LIFTED` + case accountLimitationLifted = "CUSTOMER.ACCOUNT-LIMITATION.LIFTED" + + /// `CUSTOMER.ACCOUNT-LIMITATION.UPDATED` + case accountLimitationUpdated = "CUSTOMER.ACCOUNT-LIMITATION.UPDATED" + + + /// `PAYMENT.ORDER.CANCELLED` + case orderCancelled = "PAYMENT.ORDER.CANCELLED" + + /// `PAYMENT.ORDER.CREATED` + case orderCreated = "PAYMENT.ORDER.CREATED" + + + /// `PAYMENT.REFERENCED-PAYOUT-ITEM.COMPLETED` + case referencedItemCompleted = "PAYMENT.REFERENCED-PAYOUT-ITEM.COMPLETED" + + /// `PAYMENT.REFERENCED-PAYOUT-ITEM.FAILED` + case referencedItemFailed = "PAYMENT.REFERENCED-PAYOUT-ITEM.FAILED" + + + /// `PAYMENT.SALE.COMPLETED` + case saleCompleted = "PAYMENT.SALE.COMPLETED" + + /// `PAYMENT.SALE.DENIED` + case saleDenied = "PAYMENT.SALE.DENIED" + + /// `PAYMENT.SALE.PENDING` + case salePending = "PAYMENT.SALE.PENDING" + + /// `PAYMENT.SALE.REFUNDED` + case saleRefunded = "PAYMENT.SALE.REFUNDED" + + /// `PAYMENT.SALE.REVERSED` + case saleReversed = "PAYMENT.SALE.REVERSED" + + + /// `VAULT.CREDIT-CARD.CREATED` + case creditCardCreated = "VAULT.CREDIT-CARD.CREATED" + + /// `VAULT.CREDIT-CARD.DELETED` + case creditCardDeleted = "VAULT.CREDIT-CARD.DELETED" + + /// `VAULT.CREDIT-CARD.UPDATED` + case creditCardUpdated = "VAULT.CREDIT-CARD.UPDATED" + } + + enum CodingKeys: String, CodingKey { + case name, description, status + case versions = "resource_versions" + } +} diff --git a/Sources/V1/Models/Webhook/Webhook.swift b/Sources/V1/Models/Webhook/Webhook.swift new file mode 100644 index 00000000..7dcd7008 --- /dev/null +++ b/Sources/V1/Models/Webhook/Webhook.swift @@ -0,0 +1,48 @@ +import PayPal + +/// The information for a webhook that will be fired by a PayPal action. +public struct Webhook: Codable { + + /// The ID of the webhook. + public let id: String? + + /// An array of request-related [HATEOAS links](https://developer.paypal.com/docs/api/hateoas-links/). + public let links: [LinkDescription]? + + /// The URL that is configured to listen on `localhost` for incoming `POST` notification messages + /// that contain event information. + public var url: String + + /// An array of events to which to subscribe your webhook. To subscribe to all events, including events as they are added, + /// specify the asterisk wild card. To replace the `event_types` array, specify the asterisk wild card. To list + /// all supported events, [list available events](https://developer.paypal.com/docs/api/webhooks/v1/#event-type_list). + public var events: [EventType] + + /// Creates a new `Webhook` instance. + /// + /// - Parameters: + /// - url: The URL that is configured to listen on `localhost` for incoming `POST` notification messages. + /// - events: An array of events to which to subscribe your webhook. + public init(url: String, events: [EventType]) { + self.id = nil + self.links = nil + + self.url = url + self.events = events + } + + /// The entity types that `Webhook` objects can be filtered by when fetched from the PayPal API. + public enum AnchorType: String, Hashable, CaseIterable, Codable { + + /// (Default) `APPLICATION`. + case application = "APPLICATION" + + /// `ACCOUNT`. + case account = "ACCOUNT" + } + + enum CodingKeys: String, CodingKey { + case id, links, url + case events = "event_types" + } +} diff --git a/Sources/V1/Models/Webhook/WebhookSignature.swift b/Sources/V1/Models/Webhook/WebhookSignature.swift new file mode 100644 index 00000000..8b7e041e --- /dev/null +++ b/Sources/V1/Models/Webhook/WebhookSignature.swift @@ -0,0 +1,126 @@ +import PayPal + +extension Webhook { + + /// The signature for a `Webhook` object that can be verified. + public struct Signature: Codable { + + /// The algorithm that PayPal uses to generate the signature and that you can use to verify the signature. + /// Extract this value from the PAYPAL-AUTH-ALGO response header, which is received with the webhook notification. + public var algorithm: String + + /// The X.509 public key certificate. Download the certificate from this URL and use it to verify the signature. + /// Extract this value from the PAYPAL-CERT-URL response header, which is received with the webhook notification. + public var cert: String + + /// The `transmission-x` properties for the JSON body. + public var transmission: Transmission + + /// The ID of the webhook as configured in your Developer Portal account. + public var webhook: String + + /// A webhook event notification. + public var event: Event + + /// Creates a new `Webhook.Verification` instance. + /// + /// - Parameters: + /// - algorithm: The algorithm that PayPal uses to generate the signature. + /// - cert: The X.509 public key certificate. + /// - webhook: The ID of the webhook as configured in your Developer Portal account. + /// - event: A webhook event notification. + public init( + algorithm: String, + cert: String, + transmission: Transmission, + webhook: String, + event: Event + ) { + self.algorithm = algorithm + self.cert = cert + self.transmission = transmission + self.webhook = webhook + self.event = event + } + + /// See [`Decodable.init(from:)`](https://developer.apple.com/documentation/swift/decodable/2894081-init). + public init(from decoder: Decoder)throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + self.algorithm = try container.decode(String.self, forKey: .algorithm) + self.webhook = try container.decode(String.self, forKey: .webhook) + self.event = try container.decode(Event.self, forKey: .event) + self.cert = try container.decode(String.self, forKey: .cert) + self.transmission = try Transmission(from: decoder) + } + + /// See [`Encodable.encode(to:)`](https://developer.apple.com/documentation/swift/encodable/2893603-encode). + public func encode(to encoder: Encoder)throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + try container.encode(self.algorithm, forKey: .algorithm) + try container.encode(self.webhook, forKey: .webhook) + try container.encode(self.event, forKey: .event) + try container.encode(self.cert, forKey: .cert) + try self.transmission.encode(to: encoder) + } + + /// The status options of a signature verification. + public enum Status: String, Hashable, CaseIterable, Codable { + + /// `SUCCESS`. + case success = "SUCCESS" + + /// `FAILURE`. + case failure = "FAILURE" + } + + /// The `transmission-x` properties for a `Webhok.Verification` instance. + public struct Transmission: Codable { + + /// The ID of the HTTP transmission. Contained in the `PAYPAL-TRANSMISSION-ID` header of the notification message. + public var id: String + + /// The PayPal-generated asymmetric signature. Appears in the `PAYPAL-TRANSMISSION-SIG` + /// header of the notification message. + public var signature: String + + /// The date and time of the HTTP transmission, in + /// [Internet date and time format](https://tools.ietf.org/html/rfc3339#section-5.6). + /// Appears in the `PAYPAL-TRANSMISSION-TIME` header of the notification message. + public var time: ISO8601Date + + /// Created a new `Webhook.Verification.Transmission` instance. + /// + /// - Parameters: + /// - id: The ID of the HTTP transmission. + /// - signature: The PayPal-generated asymmetric signature. + /// - time: The date and time of the HTTP transmission. + public init(id: String, signature: String, time: ISO8601Date) { + self.id = id + self.signature = signature + self.time = time + } + + enum CodingKeys: String, CodingKey { + case id = "transmission_id" + case signature = "transmission_sig" + case time = "transmission_time" + } + } + + /// The result of a `Webhooks.verify(signature:)` method call. + public struct Result: Codable { + + /// The status of a signature verification. + public var status: Status + } + + enum CodingKeys: String, CodingKey { + case algorithm = "auth_algo" + case cert = "cert_url" + case webhook = "webhook_id" + case event = "webhook_event" + } + } +} diff --git a/Sources/V1/V1.swift b/Sources/V1/V1.swift new file mode 100644 index 00000000..edfaac8f --- /dev/null +++ b/Sources/V1/V1.swift @@ -0,0 +1,22 @@ +@_exported import PayPal + +extension API { + + /// Version 1 of the PayPal API resources. + public var v1: V1 { + return V1(client: self.client) + } +} + +/// A container for the controllers for version 1 of the PayPal API resources. +public struct V1 { + + /// The client used to send requests to PayPal. + internal let client: PayPalClient + + /// Creates a new `V1` instance with the `PayPalClient` instance it will use. + internal init(client: PayPalClient) { + assert(client.version == .v1, "Make sure your PayPalClient instance is configured with the correct API version") + self.client = client + } +} diff --git a/Sources/V2/Controllers/Orders/Orders.swift b/Sources/V2/Controllers/Orders/Orders.swift new file mode 100644 index 00000000..e0b531a5 --- /dev/null +++ b/Sources/V2/Controllers/Orders/Orders.swift @@ -0,0 +1,165 @@ +import PayPal +import Vapor + +/// Use the Orders API to create, update, show details for, authorize and capture payments for, save, and void orders. +/// For more information, see the [PayPal Checkout Overview](https://developer.paypal.com/docs/checkout/). +/// +/// # Orders +/// +/// Use the `/orders` resource to create, update, show details for, and authorize and capture payments for orders. +public final class Orders: VersionedController { + + /// See `VersionedController.client` + public let client: PayPalClient + + /// See `VersionedController.resource`. + public let resource: [String] + + /// See `VersionedController.init(client:)`. + public init(client: PayPalClient) { + self.client = client + self.resource = ["checkout", "orders"] + } + + /// Creates an order. Supports orders with only one purchase unit. + /// + /// A successful request returns the HTTP 201 Created status code and a JSON response body that includes by default a + /// minimal response with the ID, status, and HATEOAS links. If you require the complete order resource representation, + /// you must pass the `.representation` value to the `prefer` parameter. This header value is not the default. + /// + /// - Parameters: + /// - order: The request body. This information is used to create an `Order` object. + /// - attribution: Identifies the caller as a PayPal partner. + /// - prefer: The value of the `Prefer` header. Defaults to `.minimal`. + /// + /// - Returns: The `Order` object created by PayPal, wrapped in an `EventLoopFuture`. + public func create( + order: Order.Request, attribution: String? = nil, prefer: PreferResponse = .minimal + ) -> EventLoopFuture { + var headers: HTTPHeaders = ["Content-Type": MediaType.json.serialize(), "Prefer": prefer.rawValue] + if let attribution = attribution { + headers.add(name: .paypalAttribution, value: attribution) + } + + return self.client.post(self.path, headers: headers, body: order, as: Order.self) + } + + /// Updates an order with the `CREATED` or `APPROVED` status. You cannot update an order with the `COMPLETED` status. + /// + /// To make an update, you must provide a `reference_id`. If you omit a `reference_id` for an order with one purchase unit, + /// PayPal defaults to a `reference_id` of `1`, which enables you to use a path: + /// + /// "path": "/purchase_units/@reference_id=='1'/{attribute-or-object}" + /// + /// You can patch these attributes and objects to complete these operations: + /// - `intent` — replace. + /// - `purchase_units` — replace, add. + /// - `purchase_units[].custom_id` — replace, add, remove. + /// - `purchase_units[].description` — replace, add, remove. + /// - `purchase_units[].payee.email` — replace, add. + /// - `purchase_units[].shipping` — replace, add, remove. + /// - `purchase_units[].soft_descriptor` — replace, add, remove. + /// - `purchase_units[].amount` — replace. + /// - `purchase_units[].invoice_id` — replace, add, remove. + /// - `purchase_units[].payment_instruction` — replace. + /// - `purchase_units[].payment_instruction.disbursement_mode` — replace. + /// - Note: By default, `disbursement_mode` is `INSTANT`. + /// - `purchase_units[].payment_instruction.platform_fees` — replace, add, remove. + /// + /// A successful request returns the HTTP 204 No Content status code with an empty object in the JSON response body. + /// + /// - Parameters: + /// - order: The ID of the order to update. + /// - patches: An array of JSON patch objects to apply partial updates to resources. + /// + /// - Returns: A void `EventLoopFuture` that succedes when the update completes. + public func update(order: String, with patches: [Patch]) -> EventLoopFuture { + return self.client.post(self.path + order, body: patches, as: HTTPStatus.self).transform(to: ()) + } + + /// Shows details for an order, by ID. + /// + /// A successful request returns the HTTP 200 OK status code and a JSON response body that shows order details. + /// + /// - Parameter order: The ID of the order for which to show details. + /// - Returns: The order object for the given ID, wrapped in an `EventLoopFuture`. + public func get(order: String) -> EventLoopFuture { + return self.client.get(self.path + order, as: Order.self) + } + + + /// Authorizes payment for an order. The response shows details of authorizations. + /// You can make this call only if you specified the `intent` property as `AUTHORIZE` in the create order call. + /// + /// A successful response to a non-idempotent request returns the HTTP 201 Created status code with a JSON response + /// body that shows authorized payment details. If a duplicate response is retried, returns the HTTP 200 OK status code. + /// By default, the response is minimal. If you need the complete resource representation, you must pass the + /// `.representation` value to the `prefer` parameter. + /// + /// - Parameters: + /// - order: The ID of the order for which to authorize. + /// - payment: The source of payment for the order, which can be a token or a card. Use this object only if + /// you have not redirected the user after order creation to approve the payment. In such cases, the + /// user-selected payment method in the PayPal flow is implicitly used. + /// - request: A unique user-generated ID that you can use to enforce idempotency. + /// - prefer: The preferred server response upon successful completion of the request. + /// - clientMetadata: Verifies that the payment originates from a valid, user-consented device and application. + /// - authAssertion: An API client-provided JSON Web Token (JWT) assertion that identifies the merchant. + public func authorize( + order: String, + payment: PaymentSource?, + request: String? = nil, + prefer: PreferResponse = .minimal, + clientMetadata: String? = nil, + authAssertion: String? = nil + ) -> EventLoopFuture { + var headers: HTTPHeaders = ["Content-Type": MediaType.json.serialize(), "Prefer": prefer.rawValue] + if let req = request { + headers.add(name: .paypalRequest, value: req) + } + if let metadata = clientMetadata { + headers.add(name: .paypalMetadata, value: metadata) + } + if let auth = authAssertion { + headers.add(name: .paypalAuth, value: auth) + } + + return self.client.post(self.path + order + "/authorize", headers: headers, body: payment, as: Order.self) + } + + /// Captures a payment for an order. + /// + /// A successful response to a non-idempotent request returns the HTTP 201 Created status code with a JSON response body + /// that shows captured payment details. If a duplicate response is retried, returns the HTTP 200 OK status code. + /// By default, the response is minimal. If you need the complete resource representation, pass the `.representation` + /// value to the `prefer` parameter. + /// + /// - Parameters: + /// - order: The ID of the order for which to capture a payment. + /// - payment: The payment source definition. + /// - request: A unique user-generated ID that you can use to enforce idempotency. + /// - prefer: The preferred server response upon successful completion of the request. + /// - clientMetadata: Verifies that the payment originates from a valid, user-consented device and application. + /// - authAssertion: An API client-provided JSON Web Token (JWT) assertion that identifies the merchant. + public func capture( + order: String, + payment: PaymentSource?, + request: String? = nil, + prefer: PreferResponse = .minimal, + clientMetadata: String? = nil, + authAssertion: String? = nil + ) -> EventLoopFuture { + var headers: HTTPHeaders = ["Content-Type": MediaType.json.serialize(), "Prefer": prefer.rawValue] + if let req = request { + headers.add(name: .paypalRequest, value: req) + } + if let metadata = clientMetadata { + headers.add(name: .paypalMetadata, value: metadata) + } + if let auth = authAssertion { + headers.add(name: .paypalAuth, value: auth) + } + + return self.client.post(self.path + order + "/capture", headers: headers, body: payment, as: Order.self) + } +} diff --git a/Sources/V2/Controllers/Payments/Authorizations.swift b/Sources/V2/Controllers/Payments/Authorizations.swift new file mode 100644 index 00000000..35077b45 --- /dev/null +++ b/Sources/V2/Controllers/Payments/Authorizations.swift @@ -0,0 +1,115 @@ +import PayPal +import Vapor + +extension Payments { + + /// The controller for the `/authorizations` resource of the Payments PayPal API. + public final class Authorizations: VersionedController { + + /// See `VersionedController.client` + public let client: PayPalClient + + /// See `VersionedController.resource`. + public let resource: [String] + + /// See `VersionedController.init(client:)`. + public init(client: PayPalClient) { + self.client = client + self.resource = ["payments", "authorizations"] + } + + /// Shows details for an authorized payment, by ID. + /// + /// A successful request returns the HTTP 200 OK status code and a JSON response body that shows authorization details. + /// + /// - Parameter authorization: The ID of the authorized payment for which to show details. + /// - Returns: The authorization details for the ID passed in, wrapped in an `EventLoopFuture`. + public func get(_ authorization: String) -> EventLoopFuture { + return self.client.get(self.path + authorization, as: Authorization.self) + } + + /// Captures an authorized payment, by ID. + /// + /// A successful request returns the HTTP 201 Created status code + /// and a JSON response body that shows captured payment details. + /// + /// - Parameters: + /// - authorization: The PayPal-generated ID for the authorized payment to capture. + /// - capture: The capture information for the payment, which will be the body for the request. + /// - prefer: The preferred server response upon successful completion of the request. + /// - requestID: A unique user-generated ID that the server stores for a period of time. + /// Use this header to enforce idempotency on REST API POST calls. + /// + /// - Returns: The captured payment, wrapped in an `EventLoopFuture`. + public func capture( + _ authorization: String, + capture: Authorization.Capture, + prefer: PreferResponse = .minimal, + requestID: String? = nil + ) -> EventLoopFuture { + var headers: HTTPHeaders = ["Prefer": prefer.rawValue] + if let request = requestID { + headers.add(name: "PayPal-Request-Id", value: request) + } + + return self.client.post(self.path + authorization + "/capture", headers: headers, body: capture, as: Capture.self) + } + + /// Reauthorizes an authorized PayPal account payment, by ID. To ensure that funds are still available, + /// reauthorize a payment after its initial three-day honor period expires. + /// You can reauthorize a payment only once from days four to 29. + /// + /// If 30 days have transpired since the date of the original authorization, + /// you must create an authorized payment instead of reauthorizing the original authorized payment. + /// + /// A reauthorized payment itself has a new honor period of three days. + /// + /// You can reauthorize an authorized payment once for up to 115% of the original authorized amount, + /// not to exceed an increase of $75 USD. + /// + /// Supports only the `amount` request parameter. + /// + /// - Note: This request is currently not supported for Partner use cases. + /// + /// A successful request returns the HTTP 201 Created status code and + /// a JSON response body that shows the reauthorized payment details. + /// + /// - Parameters: + /// - authorization: The PayPal-generated ID for the authorized payment to reauthorize. + /// - amount: The amount to reauthorize for an authorized payment. + /// - prefer: The preferred server response upon successful completion of the request. + /// - requestID: A unique user-generated ID that the server stores for a period of time. + /// Use this header to enforce idempotency on REST API POST calls. + /// + /// - Returns: The reauthorizaed payment, wrapped in an `EventLoopFuture`. + public func reauthorize( + _ authorization: String, + amount: CurrencyCodeAmount, + prefer: PreferResponse = .minimal, + requestID: String? = nil + ) -> EventLoopFuture { + var headers: HTTPHeaders = ["Prefer": prefer.rawValue] + if let request = requestID { + headers.add(name: "PayPal-Request-Id", value: request) + } + + return self.client.post( + self.path + authorization + "/reauthorize", + headers: headers, + body: amount, + as: Authorization.self + ) + } + + /// Voids, or cancels, an authorized payment, by ID. + /// You cannot void an authorized payment that has been fully captured. + /// + /// A successful request returns the HTTP 204 No Content status code with no JSON response body. + /// + /// - Parameter authorization: The PayPal-generated ID for the authorized payment to void. + /// - Returns: An empty `EventLoopFuture` that succeedes if the API response gives a success code. + public func void(_ authorization: String) -> EventLoopFuture { + return self.client.post(self.path + authorization + "/void", as: HTTPStatus.self).transform(to: ()) + } + } +} diff --git a/Sources/V2/Controllers/Payments/Captures.swift b/Sources/V2/Controllers/Payments/Captures.swift new file mode 100644 index 00000000..b2b79641 --- /dev/null +++ b/Sources/V2/Controllers/Payments/Captures.swift @@ -0,0 +1,58 @@ +import Vapor + +extension Payments { + + /// The controller for the `/captures` resource of the Payments PayPal API. + public final class Captures: VersionedController { + + /// See `VersionedController.client` + public let client: PayPalClient + + /// See `VersionedController.resource`. + public let resource: [String] + + /// See `VersionedController.init(client:)`. + public init(client: PayPalClient) { + self.client = client + self.resource = ["payments", "captures"] + } + + /// Shows details for a captured payment, by ID. + /// + /// A successful request returns the HTTP 200 OK status code and + /// a JSON response body that shows captured payment details. + /// + /// - Parameter capture: The PayPal-generated ID for the captured payment for which to show details. + /// - Returns: The captured payment for the ID, wrapped in an `EventLoopFuture`. + public func get(_ capture: String) -> EventLoopFuture { + return self.client.get(self.path + capture, as: Capture.self) + } + + /// Refunds a captured payment, by ID. For a full refund, include an empty payload in the JSON request body. + /// For a partial refund, include an `amount` object in the JSON request body. + /// + /// A successful request returns the HTTP 201 Created status code and a JSON response body that shows refund details. + /// + /// - Parameters: + /// - capture: The PayPal-generated ID for the captured payment to refund. + /// - refund: The refund data for the API. This will be the request body. + /// - prefer: The preferred server response upon successful completion of the request. + /// - requestID: A unique user-generated ID that the server stores for a period of time. + /// Use this header to enforce idempotency on REST API POST calls. + /// + /// - Returns: The refunded payment, wrapped in an `EventLoopFuture`. + public func refund( + _ capture: String, + refund: Capture.Refund? = nil, + prefer: PreferResponse = .minimal, + requestID: String? = nil + ) -> EventLoopFuture { + var headers: HTTPHeaders = ["Prefer": prefer.rawValue] + if let request = requestID { + headers.add(name: "PayPal-Request-Id", value: request) + } + + return self.client.post(self.path + capture + "/refund", headers: headers, body: refund, as: Refund.self) + } + } +} diff --git a/Sources/V2/Controllers/Payments/Payments.swift b/Sources/V2/Controllers/Payments/Payments.swift new file mode 100644 index 00000000..976583b4 --- /dev/null +++ b/Sources/V2/Controllers/Payments/Payments.swift @@ -0,0 +1,48 @@ +import PayPal +import NIO + +/// Call the Payments API to authorize payments, capture authorized payments, refund payments that have already been captured, +/// and show payment information. Use the Payments API in conjunction with the +/// [Orders API](https://developer.paypal.com/docs/api/orders/v2/). For more information, +/// see the [PayPal Checkout Overview](https://developer.paypal.com/docs/checkout/). +/// +/// # Authorizations +/// +/// Use the `/authorizations` resource to show details for, capture payment for, reauthorize, and void authorized payments. +/// +/// # Captures +/// +/// Use the `/captures` resource to show details for and refund a captured payment. +/// +/// # Refunds +/// +/// Use the `/refunds` resource to show refund details. +public final class Payments: VersionedController { + + /// See `VersionedController.client` + public let client: PayPalClient + + /// See `VersionedController.resource`. + public let resource: [String] + + /// See `VersionedController.init(client:)`. + public init(client: PayPalClient) { + self.client = client + self.resource = ["payments"] + } + + /// The controller for the `/payments/authorizations` resource. + public var authorizations: Authorizations { + return Authorizations(client: self.client) + } + + /// The controller for the `/payments/captures` resource. + public var captures: Captures { + return Captures(client: self.client) + } + + /// The controller for the `/payments/refunds` resource. + public var refunds: Refunds { + return Refunds(client: self.client) + } +} diff --git a/Sources/V2/Controllers/Payments/Refunds.swift b/Sources/V2/Controllers/Payments/Refunds.swift new file mode 100644 index 00000000..43f03b28 --- /dev/null +++ b/Sources/V2/Controllers/Payments/Refunds.swift @@ -0,0 +1,30 @@ +import Vapor + +extension Payments { + + /// The controller for the `/refunds` resource of the Payments PayPal API. + public final class Refunds: VersionedController { + + /// See `VersionedController.client` + public let client: PayPalClient + + /// See `VersionedController.resource`. + public let resource: [String] + + /// See `VersionedController.init(client:)`. + public init(client: PayPalClient) { + self.client = client + self.resource = ["payments", "refunds"] + } + + /// Shows details for a refund, by ID. + /// + /// A successful request returns the HTTP 200 OK status code and a JSON response body that shows refund details. + /// + /// - Parameter refund: The PayPal-generated ID for the refund for which to show details. + /// - Returns: The refund for the given ID, wrapped in an `EventLoopFuture`. + public func get(_ refund: String) -> EventLoopFuture { + return self.client.get(self.path + refund, as: Refund.self) + } + } +} diff --git a/Sources/V2/Models/Address.swift b/Sources/V2/Models/Address.swift new file mode 100644 index 00000000..7fa4b2c0 --- /dev/null +++ b/Sources/V2/Models/Address.swift @@ -0,0 +1,71 @@ +import Countries +import PayPal + +/// Address of the payer party in an order. +public struct Address: Codable { + + /// The first line of the address. For example, number or street. For example, `173 Drury Lane`. + /// Required for data entry and compliance and risk checks. Must contain the full address. + public var line1: Failable> + + /// The second line of the address. For example, suite or apartment number. + public var line2: Failable> + + /// The highest level sub-division in a country, which is usually a province, state, or ISO-3166-2 subdivision. + /// Format for postal delivery. For example, CA and not California. Value, by country, is: + /// - UK. A county. + /// - US. A state. + /// - Canada. A province. + /// - Japan. A prefecture. + /// - Switzerland. A kanton. + public var admin1: Failable> + + /// A city, town, or village. Smaller than admin_area_level_1. + public var admin2: Failable> + + /// The postal code, which is the zip code or equivalent. Typically required for countries with a + /// postal code or an equivalent. See [postal code](https://en.wikipedia.org/wiki/Postal_code). + public var postalCode: Failable> + + /// The [two-character ISO 3166-1 code](https://developer.paypal.com/docs/integration/direct/rest/country-codes/) + /// that identifies the country or region. + /// + /// - Note: The country code for Great Britain is GB and not UK as used in the top-level domain names for that country. + /// Use the C2 country code for China worldwide for comparable uncontrolled price (CUP) method, bank card, + /// and cross-border transactions. + public var country: Country + + /// Creates a new `Payer.Address` instance. + /// + /// - Parameters: + /// - line1: The first line of the address. + /// - line2: The second line of the address. + /// - admin1: The highest level sub-division in a country. + /// - admin2: A city, town, or village. + /// - postalCode: The postal code, which is the zip code or equivalent. + /// - country: The two-character ISO 3166-1 code that identifies the country or region. + public init( + line1: Failable>, + line2: Failable>, + admin1: Failable>, + admin2: Failable>, + postalCode: Failable>, + country: Country + ) { + self.line1 = line1 + self.line2 = line2 + self.admin1 = admin1 + self.admin2 = admin2 + self.postalCode = postalCode + self.country = country + } + + enum CodingKeys: String, CodingKey { + case line1 = "address_line_1" + case line2 = "address_line_2" + case admin1 = "admin_area_1" + case admin2 = "admin_area_2" + case postalCode = "postal_code" + case country = "country_code" + } +} diff --git a/Sources/V2/Models/ApplicationContext/AppContext.swift b/Sources/V2/Models/ApplicationContext/AppContext.swift new file mode 100644 index 00000000..421d0311 --- /dev/null +++ b/Sources/V2/Models/ApplicationContext/AppContext.swift @@ -0,0 +1,121 @@ +import Failable +import PayPal + +/// Used to customize the payer's experience during the approval process for a PayPal payment. +public struct AppContext: Codable { + + /// The label that overrides the business name in the PayPal account on the PayPal site. + public var brand: Optional127String + + /// The BCP 47-formatted locale of pages that the PayPal payment experience shows. PayPal supports a five-character code. + /// For example, `da-DK`, `he-IL`, `id-ID`, `ja-JP`, `no-NO`, `pt-BR`, `ru-RU`, `sv-SE`, `th-TH`, `zh-CN`, or `zh-HK`. + public var locale: Failable> + + /// The type of landing page to show on the PayPal site for customer checkout. + public var landingPage: LandingPage? + + /// The shipping preference: + /// - Displays the shipping address to the customer. + /// - Enables the customer to choose an address on the PayPal site. + /// - Restricts the customer from changing the address during the payment-approval process. + public var shipping: ShippingPreference? + + /// Configures a **Continue** or **Pay Now** checkout flow. + public var userAction: UserAction? + + /// The customer and merchant payment preferences. + public var payment: PaymentMethod? + + /// The URL where the customer is redirected after the customer approves the payment. + public var `return`: String? + + /// The URL where the customer is redirected after the customer cancels the payment. + public var cancel: String? + + + /// Creates a new `AppContext` instance. + /// + /// - Parameters: + /// - brand: The label that overrides the business name in the PayPal account on the PayPal site. + /// - locale: The BCP 47-formatted locale of pages that the PayPal payment experience shows. + /// - landingPage: The type of landing page to show on the PayPal site for customer checkout. Defaults to `.login`. + /// - shipping: The shipping preference: + /// - Displays the shipping address to the customer. + /// - Enables the customer to choose an address on the PayPal site. + /// - Restricts the customer from changing the address during the payment-approval process. + /// Detaults to `.fromFile`. + /// - userAction: Configures a **Continue** or **Pay Now** checkout flow. + /// - payment: The customer and merchant payment preferences. + /// - return: The URL where the customer is redirected after the customer approves the payment. + /// - cancel: The URL where the customer is redirected after the customer cancels the payment. + public init( + brand: Optional127String, + locale: Failable>, + landingPage: LandingPage? = .login, + shipping: ShippingPreference? = .fromFile, + userAction: UserAction?, + payment: PaymentMethod?, + `return`: String?, + cancel: String? + ) { + self.brand = brand + self.locale = locale + self.landingPage = landingPage + self.shipping = shipping + self.userAction = userAction + self.payment = payment + self.`return` = `return` + self.cancel = cancel + } + + /// The options for what type of landing page to show on the PayPal site for customer checkout. + public enum LandingPage: String, Hashable, CaseIterable, Codable { + + /// (Default) When the customer clicks **PayPal Checkout**, the customer is redirected to a page + /// to log in to PayPal and approve the payment. + case login = "LOGIN" + + /// When the customer clicks **PayPal Checkout**, the customer is redirected to a page to enter credit + /// or debit card and other relevant billing information required to complete the purchase. + case billing = "BILLING" + } + + /// The shipping preferance options for a given app context. + public enum ShippingPreference: String, Hashable, CaseIterable, Codable { + + /// (Default) Use the customer-provided shipping address on the PayPal site. + case fromFile = "GET_FROM_FILE" + + /// Redact the shipping address from the PayPal site. Recommended for digital goods. + case none = "NO_SHIPPING" + + /// Use the merchant-provided address. The customer cannot change this address on the PayPal site. + case provided = "SET_PROVIDED_ADDRESS" + } + + + /// The configuration options for a **Continue** or **Pay Now** checkout flow. + public enum UserAction: String, Hashable, CaseIterable, Codable { + + /// (Default) After you redirect the customer to the PayPal payment page, a **Continue** button appears. + /// Use this option when the final amount is not known when the checkout flow is initiated and you want + /// to redirect the customer to the merchant page without processing the payment. + case `continue` = "CONTINUE" + + /// After you redirect the customer to the PayPal payment page, a **Pay Now** button appears. + /// Use this option when the final amount is known when the checkout is initiated and you want to + /// process the payment immediately when the customer clicks **Pay Now**. + case payNow = "PAY_NOW" + } + + enum CodingKeys: String, CodingKey { + case locale + case brand = "brand_name" + case landingPage = "landing_page" + case shipping = "shipping_preference" + case userAction = "user_action" + case payment = "payment_method" + case `return` = "return_url" + case cancel = "cancel_url" + } +} diff --git a/Sources/V2/Models/ApplicationContext/PaymentMethod.swift b/Sources/V2/Models/ApplicationContext/PaymentMethod.swift new file mode 100644 index 00000000..87ec5734 --- /dev/null +++ b/Sources/V2/Models/ApplicationContext/PaymentMethod.swift @@ -0,0 +1,35 @@ +/// The customer and merchant payment preferences for a given app context. +public struct PaymentMethod: Codable { + + /// The customer-selected payment method on the merchant site. + public var payer: PayerSelected? + + /// The merchant-preferred payment sources. + public var payee: PayeePrefered? + + public init(payer: PayerSelected?, payee: PayeePrefered? = .unrestricted) { + self.payer = payer + self.payee = payee + } + + /// The customer-selected payment methods. + public enum PayerSelected: String, Hashable, CaseIterable, Codable { + + /// When payer chooses PayPal Credit as the payment method. + case credit = "PAYPAL_CREDIT" + + /// When payer chooses PayPal as the payment method + case paypal = "PAYPAL" + } + + /// The merchant-preferred payment sources. + public enum PayeePrefered: String, Hashable, CaseIterable, Codable { + + /// (Default) Accepts any type of payment from the customer. + case unrestricted = "UNRESTRICTED" + + /// Accepts only immediate payment from the customer. For example, credit card, PayPal balance, or instant ACH. + /// Ensures that at the time of capture, the payment does not have the `pending` status. + case immediate = "IMMEDIATE_PAYMENT_REQUIRED" + } +} diff --git a/Sources/V2/Models/DetailedAmount.swift b/Sources/V2/Models/DetailedAmount.swift new file mode 100644 index 00000000..257e543e --- /dev/null +++ b/Sources/V2/Models/DetailedAmount.swift @@ -0,0 +1,132 @@ +import Foundation +import PayPal + +/// A currency amount with a breakdown that provides details about shipping, handling, tax, etc. +public struct DetailedAmount: Codable { + + /// The [three-character ISO-4217 currency code](https://developer.paypal.com/docs/integration/direct/rest/currency-codes/) + /// that identifies the currency. + public var currency: Currency + + /// The amount of the given currency to represent. + /// + /// The value, which might be: + /// - An integer for currencies like `JPY` that are not typically fractional. + /// - A decimal fraction for currencies like `TND` that are subdivided into thousandths. + /// + /// For the required number of decimal places for a currency code, see + /// [Currency Codes](https://developer.paypal.com/docs/integration/direct/rest/currency-codes/). + public var value: Decimal + + /// The breakdown of the amount. Breakdown provides details such as total item amount, total tax amount, shipping, + /// handling, insurance, and discounts, if any. + public var breakdown: Breakdown? + + /// Creates a new `DetailedAmount` instance. + /// + /// - Parameters: + /// - currency: The three-character ISO-4217 currency code that identifies the currency. + /// - value: The amount of the given currency to represent. + /// - breakdown: The breakdown of the amount. + public init(currency: Currency, value: Decimal, breakdown: Breakdown?) { + self.currency = currency + self.value = value + self.breakdown = breakdown + } + + /// See [`Decodable.init(from:)`](https://developer.apple.com/documentation/swift/decodable/2894081-init). + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let value = try container.decode(String.self, forKey: .value) + guard let decimal = Decimal(string: value) else { + throw DecodingError.dataCorruptedError( + forKey: .value, + in: container, + debugDescription: "`value` string must be convertible to a decimal type" + ) + } + + self.currency = try container.decode(Currency.self, forKey: .currency) + self.breakdown = try container.decode(Breakdown.self, forKey: .breakdown) + self.value = decimal + } + + /// See [`Encodable.encode(to:)`](https://developer.apple.com/documentation/swift/encodable/2893603-encode). + /// + /// This implementation rounds the `value` property before encoding it as a string. + /// The actual `value` property is not modified. + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + var rounded: Decimal = self.value + + if let exponent = self.currency.e { + var value: Decimal = self.value + NSDecimalRound(&rounded, &value, exponent, .bankers) + } + + try container.encode(self.currency, forKey: .currency) + try container.encode(self.breakdown, forKey: .breakdown) + try container.encode(rounded.description, forKey: .value) + } + + /// The breakdown of the amount of a purchase unit in an order. + public struct Breakdown: Codable { + + /// The subtotal for all items. Required if the request includes `purchase_units[].items[].unit_amount`. + /// Must equal the sum of `(items[].unit_amount * items[].quantity)` for all items. + public var total: CurrencyCodeAmount? + + /// The shipping fee for all items within a given `purchase_unit`. + public var shipping: CurrencyCodeAmount? + + /// The handling fee for all items within a given `purchase_unit`. + public var handling: CurrencyCodeAmount? + + /// The total tax for all items. Required if the request includes `purchase_units.items.tax`. + /// Must equal the sum of `(items[].tax * items[].quantity)` for all items. + public var tax: CurrencyCodeAmount? + + /// The insurance fee for all items within a given `purchase_unit`. + public var insurance: CurrencyCodeAmount? + + /// The shipping discount for all items within a given `purchase_unit`. + public var shippingDiscount: CurrencyCodeAmount? + + /// Creates a new `DetailedAmount.Breakdown` instance. + /// + /// - Parameters: + /// - total: The subtotal for all items. + /// - shipping: The shipping fee for all items within a given `purchase_unit`. + /// - handling: The handling fee for all items within a given `purchase_unit`. + /// - tax: The total tax for all items. + /// - insurance: The insurance fee for all items within a given `purchase_unit`. + /// - shippingDiscount: The shipping discount for all items within a given `purchase_unit`. + public init( + total: CurrencyCodeAmount?, + shipping: CurrencyCodeAmount?, + handling: CurrencyCodeAmount?, + tax: CurrencyCodeAmount?, + insurance: CurrencyCodeAmount?, + shippingDiscount: CurrencyCodeAmount? + ) { + self.total = total + self.shipping = shipping + self.handling = handling + self.tax = tax + self.insurance = insurance + self.shippingDiscount = shippingDiscount + } + + enum CodingKeys: String, CodingKey { + case shipping, handling, insurance + case total = "item_total" + case tax = "tax_total" + case shippingDiscount = "shipping_discount" + } + } + + enum CodingKeys: String, CodingKey { + case value, breakdown + case currency = "currency_code" + } +} diff --git a/Sources/V2/Models/Order/Order.swift b/Sources/V2/Models/Order/Order.swift new file mode 100644 index 00000000..e4409ecf --- /dev/null +++ b/Sources/V2/Models/Order/Order.swift @@ -0,0 +1,114 @@ +import Foundation +import PayPal + +/// And order object from PayPal. +public struct Order: Codable { + + /// The intent to either capture payment immediately or authorize a payment for an order after order creation. + public var intent: Intent? + + /// The customer who approves and pays for the order. The customer is also known as the payer. + public var payer: Payer? + + /// An array of purchase units. Each purchase unit establishes a contract between a customer and merchant. + /// Each purchase unit represents either a full or partial order that the customer intends to purchase from the merchant. + public var purchaseUnits: [PurchaseUnit]? + + /// The date and time when the transaction occurred. + public let created: ISO8601Date? + + /// The date and time when the transaction was last updated. + public let updated: ISO8601Date? + + /// The ID of the order. + public let id: String? + + /// The order status. + public let status: Status? + + /// An array of request-related [HATEOAS links](https://developer.paypal.com/docs/api/overview/#hateoas-links). + /// To complete payer approval, use the `approve` link with the `GET` method. + public let links: [LinkDescription]? + + /// Creates a new `Order` instance. + /// + /// - Parameters: + /// - intent: The intent to either capture payment immediately or authorize a payment for an order after order creation. + /// - payer: The customer who approves and pays for the order. The customer is also known as the payer. + /// - purchaseUnits: An array of purchase units. Each purchase unit establishes a contract between a customer and + /// merchant. Each purchase unit represents either a full or partial order that the customer intends to purchase + /// from the merchant. + public init(intent: Intent?, payer: Payer?, purchaseUnits: [PurchaseUnit]?) { + self.intent = intent + self.payer = payer + self.purchaseUnits = purchaseUnits + + self.created = nil + self.updated = nil + self.id = nil + self.status = nil + self.links = nil + } + + /// The request structure to create a new `Order`. + public struct Request: Codable { + + /// The intent to either capture payment immediately or authorize a payment for an order after order creation. + public var intent: Intent + + /// The customer who approves and pays for the order. The customer is also known as the payer. + public var payer: Payer? + + /// An array of purchase units. At present only 1 purchase_unit is supported. Each purchase unit establishes a + /// contract between a payer and the payee. Each purchase unit represents either a full or partial order that + /// the payer intends to purchase from the payee. + public var purchaseUnits: [PurchaseUnit] + + /// Customize the payer experience during the approval process for the payment with PayPal. + public var context: AppContext? + + /// Creates a new `Order.Request` instance. + /// + /// - Parameters: + /// - intent: The intent to either capture payment immediately or + /// authorize a payment for an order after order creation. + /// - payer: The customer who approves and pays for the order. + /// - purchaseUnits: An array of purchase units. + /// - context: Customize the payer experience during the approval process for the payment with PayPal. + public init (intent: Intent, payer: Payer?, purchaseUnits: [PurchaseUnit], context: AppContext?) { + self.intent = intent + self.payer = payer + self.purchaseUnits = purchaseUnits + self.context = context + } + + enum CodingKeys: String, CodingKey { + case intent, payer + case purchaseUnits = "purchase_units" + case context = "application_context" + } + } + + enum CodingKeys: String, CodingKey { + case intent, payer, id, status, links + case purchaseUnits = "purchase_units" + case created = "create_time" + case updated = "update_time" + } +} + +extension Order { + + /// The intent to either capture payment immediately or authorize a payment for an order after order creation. + public enum Intent: String, Codable, Hashable, CaseIterable { + + /// The merchant intends to capture payment immediately after the customer makes a payment. + case capture = "CAPTURE" + + /// The merchant intends to authorize a payment and place funds on hold after the customer makes a payment. + /// Authorized payments are guaranteed for up to three days but are available to capture for up to 29 days. + /// After the three-day honor period, the original authorized payment expires and you must re-authorize the payment. + /// You must make a separate request to capture payments on demand. + case authorize = "AUTHORIZE" + } +} diff --git a/Sources/V2/Models/Order/OrderItem.swift b/Sources/V2/Models/Order/OrderItem.swift new file mode 100644 index 00000000..edfcf619 --- /dev/null +++ b/Sources/V2/Models/Order/OrderItem.swift @@ -0,0 +1,91 @@ +import Failable +import PayPal + +extension Order { + + /// An item that a customer is purchasing from a merchant. + public struct Item: Codable { + + /// The item name or title. + public var name: Failable + + /// The item price or rate per unit. If you specify `unit_amount`, `purchase_units[].amount.breakdown.item_total` + /// is required. Must equal `unit_amount * quantity` for all items. + public var amount: CurrencyCodeAmount + + /// The item tax for each unit. If `tax` is specified, `purchase_units[].amount.breakdown.tax_total` is required. + /// Must equal `tax * quantity` for all items. + public var tax: CurrencyCodeAmount? + + /// The item quantity. + public var quantity: Failable> + + /// The detailed item description. + public var description: Optional127String + + /// The stock keeping unit (SKU) for the item. + public var sku: Optional127String + + /// The item category type. + public var category: ItemCategory? + + /// Creates a new `Order.Item` instance. + /// + /// - Parameters: + /// - name: The item name or title. + /// - amount: The item price or rate per unit. + /// - tax: The item tax for each unit. + /// - quantity: The item quantity. + /// - description: The detailed item description. + /// - sku: The stock keeping unit (SKU) for the item. + /// - category: The item category type. + public init( + name: Failable, + amount: CurrencyCodeAmount, + tax: CurrencyCodeAmount?, + quantity: Failable>, + description: Optional127String, + sku: Optional127String, + category: ItemCategory? + ) { + self.name = name + self.amount = amount + self.tax = tax + self.quantity = quantity + self.description = description + self.sku = sku + self.category = category + } + + /// The validator for the `Order.Item.name` property value. + public struct NameLength: LengthValidation { + + /// See `Validation.Supported`. + public typealias Supported = String + + /// See `LengthValidation.minLength`. + /// + /// The minimum valid string length is 1. + public static var minLength: Int = 1 + + /// See `LengthValidation.maxLength`. + /// + /// The maximum valid string length is 127. + public static var maxLength: Int = 127 + } + + enum CodingKeys: String, CodingKey { + case name, tax, quantity, description, sku, category + case amount = "unit_amount" + } + } + + public enum ItemCategory: String, Hashable, Codable, CaseIterable { + + /// Goods that are stored, delivered, and used in their electronic format. + case digital = "DIGITAL_GOODS" + + /// A tangible item that can be shipped with proof of delivery. + case physical = "PHYSICAL_GOODS" + } +} diff --git a/Sources/V2/Models/Order/OrderStatus.swift b/Sources/V2/Models/Order/OrderStatus.swift new file mode 100644 index 00000000..2057f5dc --- /dev/null +++ b/Sources/V2/Models/Order/OrderStatus.swift @@ -0,0 +1,23 @@ +extension Order { + + /// The status of an order. + public enum Status: String, Hashable, Codable, CaseIterable { + + /// The order was created with the specified context. + case CREATED + + /// The order was saved and persisted. The order status continues to be in progress until + /// a capture is made with `final_capture = true` for all purchase units within the order. + case SAVED + + /// The customer approved the payment through the PayPal wallet or another form of guest or unbranded payment. + /// For example, a card, bank account, or so on. + case APPROVED + + /// All purchase units in the order are voided. + case VOIDED + + /// The payment was authorized or the authorized payment was captured for the order. + case COMPLETED + } +} diff --git a/Sources/V2/Models/Order/Payer/Payer.swift b/Sources/V2/Models/Order/Payer/Payer.swift new file mode 100644 index 00000000..e45303cc --- /dev/null +++ b/Sources/V2/Models/Order/Payer/Payer.swift @@ -0,0 +1,66 @@ +import Failable +import PayPal + +/// The customer who approves and pays for an order. +public struct Payer: Codable { + + /// The name of the payer. Supports only the `given_name` and `surname` properties. + public var name: Name? + + /// The email address of the payer. + public var email: Failable> + + /// The PayPal assigned ID for the payer. + public var payer: Failable> + + /// The phone number of the customer. Available only when you enable the **Contact Telephone Number** option in the + /// [Profile & Settings](https://www.paypal.com/cgi-bin/customerprofileweb?cmd=_profile-website-payments) for the + /// merchant's PayPal account. The `phone.phone_number` supports only `national_number`. + public var phone: Phone? + + /// The birth date of the payer in `YYYY-MM-DD` format. + public var birthdate: TimelessDate? + + /// The tax information of the payer. Required only for Brazilian payer's. Both `tax_id` and `tax_id_type` are required. + public var tax: TaxInfo? + + /// The address of the payer. Supports only the `address_line_1`, `address_line_2`, `admin_area_1`, `admin_area_2`, + /// `postal_code`, and `country_code` properties. Also referred to as the billing address of the customer. + public var address: Address? + + /// Creates a new `Payer` instance. + /// + /// - Parameters: + /// - name: The name of the payer. + /// - email: The email address of the payer. + /// - payer: The PayPal assigned ID for the payer. + /// - phone: The phone number of the customer. + /// - birthdate: The birth date of the payer in `YYYY-MM-DD` format. + /// - tax: The tax information of the payer. + /// - address: The address of the payer. + public init( + name: Name?, + email: Failable>, + payer: Failable>, + phone: Phone?, + birthdate: TimelessDate?, + tax: TaxInfo?, + address: Address? + ) { + self.name = name + self.email = email + self.payer = payer + self.phone = phone + self.birthdate = birthdate + self.tax = tax + self.address = address + } + + enum CodingKeys: String, CodingKey { + case name, phone, address + case email = "email_address" + case payer = "payer_id" + case birthdate = "birth_date" + case tax = "tax_info" + } +} diff --git a/Sources/V2/Models/Order/Payer/PayerName.swift b/Sources/V2/Models/Order/Payer/PayerName.swift new file mode 100644 index 00000000..0d6ec5ca --- /dev/null +++ b/Sources/V2/Models/Order/Payer/PayerName.swift @@ -0,0 +1,34 @@ +import PayPal + +extension Payer { + + /// The name of a payer. Supports only the `given_name` and `surname` properties + public struct Name: Codable { + + /// When the party is a person, the party's given, or first, name. + public var given: Failable> + + /// When the party is a person, the party's surname or family name. Also known as the last name. + /// Required when the party is a person. Use also to store multiple surnames including the matronymic, + /// or mother's, surname. + public var surname: Failable> + + /// Creates a new `Payer.Name` instance. + /// + /// - Parameters: + /// - given: When the party is a person, the party's given, or first, name. + /// - surname: When the party is a person, the party's surname or family name. + public init( + given: Failable>, + surname: Failable> + ) { + self.given = given + self.surname = surname + } + + enum CodingKeys: String, CodingKey { + case given = "given_name" + case surname + } + } +} diff --git a/Sources/V2/Models/Order/Payer/TaxInfo.swift b/Sources/V2/Models/Order/Payer/TaxInfo.swift new file mode 100644 index 00000000..e99c79e2 --- /dev/null +++ b/Sources/V2/Models/Order/Payer/TaxInfo.swift @@ -0,0 +1,47 @@ +import Failable +import PayPal + +/// The tax information for a payer, typically in an order. +public struct TaxInfo: Codable { + + /// The customer's tax ID. Supported for the PayPal payment method only. Typically, + /// the tax ID is 11 characters long for individuals and 14 characters long for businesses. + public let id: Failable + + /// The customer's tax ID type. Supported for the PayPal payment method only. + public let type: TaxType + + /// Creates a new `TaxInfo` instance. + /// + /// - Parameters: + /// - id: The customer's tax ID. + /// - type: The customer's tax ID type. + public init(id: Failable, type: TaxType) { + self.id = id + self.type = type + } + + /// The validator for the `TaxInfo.id` property value. + public struct ID: StringLengthValidation { + + /// See `StringLengthValidation.maxLength`. + /// + /// The maximum length of a string is 14 characters. + public static let maxLength: Int = 14 + } + + enum CodingKeys: String, CodingKey { + case id = "tax_id" + case type = "tax_id_type" + } +} + +/// The type of ID for a `TaxInfo` instance. +public enum TaxType: String, Hashable, CaseIterable, Codable { + + /// The individual tax ID type. + case cff = "BR_CPF" + + /// The business tax ID type. + case cnpj = "BR_CNPJ" +} diff --git a/Sources/V2/Models/Order/Phone/Phone.swift b/Sources/V2/Models/Order/Phone/Phone.swift new file mode 100644 index 00000000..4b8ca3a8 --- /dev/null +++ b/Sources/V2/Models/Order/Phone/Phone.swift @@ -0,0 +1,93 @@ +import Failable + +/// The phone number of a customer, merchant, or organization. +public struct Phone: Codable { + + /// The country calling code (CC), in its canonical international + /// [E.164 numbering plan format](https://www.itu.int/rec/T-REC-E.164/en). The combined length of the CC and the + /// national number must not be greater than 15 digits. The national number consists of a national + /// destination code (NDC) and subscriber number (SN). + public var country: Failable + + /// The national number, in its canonical international + /// [E.164 numbering plan format](https://www.itu.int/rec/T-REC-E.164/en). The combined length of the country + /// calling code (CC) and the national number must not be greater than 15 digits. The national number consists + /// of a national destination code (NDC) and subscriber number (SN). + public var national: Failable + + /// The extension number. + public var `extension`: Failable> + + /// Creates a new `Phone` instance. + /// + /// - Parameters: + /// - country: The country calling code (CC), in its canonical international E.164 numbering plan format. + /// - national: The national number, in its canonical international E.164 numbering plan format. + /// - extension: The extension number. + public init( + country: Failable, + national: Failable, + `extension`: Failable> + ) { + self.country = country + self.national = national + self.extension = `extension` + } + + /// The validation for the `Phone.country` property value. + public struct CountryCode: InRangeValidation { + + /// See `Validation.Supported`. + public typealias Supported = Int + + /// See `InRangeValidation.min`. + /// + /// The minumum allowed value is `0`. + public static let min: Int? = 0 + + /// See `InRangeValidation.max`. + /// + /// The minumum allowed value is `999`. + public static let max: Int? = 999 + } + + /// The validation for the `Phone.national` property value. + public struct NationalNumber: InRangeValidation { + + /// See `Validation.Supported`. + public typealias Supported = Int + + /// See `InRangeValidation.min`. + /// + /// The minumum allowed value is `0`. + public static let min: Int? = 0 + + /// See `InRangeValidation.max`. + /// + /// The minumum allowed value is `99,999,999,999,999`. + public static let max: Int? = 99_999_999_999_999 + } + + /// The validation for the `Phone.extension` property value. + public struct ExtensionNumber: InRangeValidation { + + /// See `Validation.Supported`. + public typealias Supported = Int + + /// See `InRangeValidation.min`. + /// + /// The minumum allowed value is `0`. + public static let min: Int? = 0 + + /// See `InRangeValidation.max`. + /// + /// The minumum allowed value is `999,999,999,999,999`. + public static let max: Int? = 999_999_999_999_999 + } + + enum CodingKeys: String, CodingKey { + case country = "country_code" + case national = "national_number" + case `extension` = "extension_number" + } +} diff --git a/Sources/V2/Models/Order/Phone/PhoneType.swift b/Sources/V2/Models/Order/Phone/PhoneType.swift new file mode 100644 index 00000000..813037ce --- /dev/null +++ b/Sources/V2/Models/Order/Phone/PhoneType.swift @@ -0,0 +1,76 @@ +import Failable + +/// The type of phone that a phone number is connected to. +public enum PhoneType: String, Hashable, Codable, CaseIterable { + + /// `FAX` type. + case fax = "FAX" + + /// `HOME` type. + case home = "HOME" + + /// `MOBILE` type. + case mobile = "MOBILE" + + /// `OTHER` type. + case other = "OTHER" + + /// `PAGER` type. + case pager = "PAGER" +} + +/// A phone number that has a specified phone type it is connected to. +public struct TypedPhone: Codable { + + /// The phone type. + public var type: PhoneType? + + /// The national number, in its canonical international + /// [E.164 numbering plan format](https://www.itu.int/rec/T-REC-E.164/en). The combined length of the country + /// calling code (CC) and the national number must not be greater than 15 digits. The national number + /// consists of a national destination code (NDC) and subscriber number (SN). + /// + /// - Note: To be compatible with the PayPal API, this value is encoded/decoded as a `String`. + public var national: Failable + + /// Creates a new `TypedPhone` instance. + /// + /// - Parameters: + /// - type: The phone type. + /// - national: The national number, in its canonical international E.164 numbering plan format + public init(type: PhoneType?, national: Failable) { + self.type = type + self.national = national + } + + /// See [`Decodable.init(from:)`](https://developer.apple.com/documentation/swift/decodable/2894081-init). + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.type = try container.decodeIfPresent(PhoneType.self, forKey: .type) + + let number = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .number) + guard let int = try Int(number.decode(String.self, forKey: .national)) else { + throw DecodingError.dataCorruptedError( + forKey: CodingKeys.national, + in: number, + debugDescription: "`phone_number.national_number` string value must be convertible to an int" + ) + } + self.national = try Failable(int) + } + + /// See [`Encodable.encode(to:)`](https://developer.apple.com/documentation/swift/encodable/2893603-encode). + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(self.type, forKey: .type) + + var number = container.nestedContainer(keyedBy: CodingKeys.self, forKey: .number) + try number.encode(String(describing: self.national.value), forKey: .national) + } + + enum CodingKeys: String, CodingKey { + case type = "phone_type" + case number = "phone_number" + case national = "national_number" + } +} diff --git a/Sources/V2/Models/Order/PurchaseUnit/PurchaseUnit.swift b/Sources/V2/Models/Order/PurchaseUnit/PurchaseUnit.swift new file mode 100644 index 00000000..70e8c3b3 --- /dev/null +++ b/Sources/V2/Models/Order/PurchaseUnit/PurchaseUnit.swift @@ -0,0 +1,109 @@ +import Failable +import PayPal + +/// The payment information for an order. +public struct PurchaseUnit: Codable { + + /// The ID for the purchase unit. Required for multiple `purchase_units` or if an order must be updated by using `PATCH`. + /// If you omit the `reference_id` for an order with one purchase unit, PayPal sets the `reference_id` to `default`. + public var reference: Failable> + + /// The total order amount with an optional breakdown that provides details, such as the total item amount, + /// total tax amount, shipping, handling, insurance, and discounts, if any. + /// + /// If you specify `amount.breakdown`, the amount equals `item_total` plus `tax_total` plus `shipping` plus `handling` + /// plus `insurance` minus `shipping_discount`. + /// + /// The amount must be a positive number. For listed of supported currencies and decimal precision, + /// see the PayPal REST APIs [Currency Codes](https://developer.paypal.com/docs/integration/direct/rest/currency-codes/). + public var amount: DetailedAmount + + /// The merchant who receives payment for this transaction. + public var payee: PayeeBase? + + /// Any additional payment instructions for PayPal for Partner customers. Enables features for partners and marketplaces, + /// such as delayed disbursement and collection of a platform fee. Applies during order creation for captured payments + /// or during capture of authorized payments. + public var paymentInstruction: PaymentInstruction? + + /// The purchase description. + public var description: Optional127String + + /// The API caller-provided external ID. Used to reconcile client transactions with PayPal transactions. + /// Appears in transaction and settlement reports but is not visible to the payer. + public var customID: Optional127String + + /// The API caller-provided external invoice number for this order. Appears in both the payer's transaction history + /// and the emails that the payer receives. + public var invoice: Optional127String + + /// The payment descriptor on the customer's credit card statement of account transactions. + /// + /// The maximum length of the soft descriptor is 22 characters. Of this, the PayPal prefix uses eight characters + /// (PAYPAL *) of the data format. Thus, the maximum length of the soft descriptor information that you can pass + /// in this field is: + /// + /// 22 - length() - length( + 1) + /// + /// For example, assume the following conditions: + /// - The PayPal prefix toggle is "PAYPAL *". + /// - The merchant descriptor set in the Profile is VENMO. + /// - The soft descriptor is passed in as JanesFlowerGifts LLC. + /// + /// PAYPAL *VENMO JanesFlo + /// + /// If the total length of the soft_descriptor exceeds 22 characters, the overflow will be truncated. + public var softDescriptor: Failable> + + /// An array of items that the customer is purchasing from the merchant. + public var items: [Order.Item]? + + /// The name and address of the person to whom to ship the items. + public var shipping: Shipping? + + /// Creates a new `PurchaseUnit` instance. + /// + /// - Parameters: + /// - reference: The ID for the purchase unit. + /// - amount: The total order amount with an optional breakdown that provides details. + /// - payee: The merchant who receives payment for this transaction. + /// - paymentInstruction: Any additional payment instructions for PayPal for Partner customers. + /// - description: The purchase description. + /// - customID: The API caller-provided external ID. + /// - invoice: The API caller-provided external invoice number for this order. + /// - softDescriptor: The payment descriptor on the customer's credit card statement of account transactions. + /// - items: An array of items that the customer is purchasing from the merchant. + /// - shipping: The name and address of the person to whom to ship the items. + public init( + reference: Failable>, + amount: DetailedAmount, + payee: PayeeBase?, + paymentInstruction: PaymentInstruction?, + description: Optional127String, + customID: Optional127String, + invoice: Optional127String, + softDescriptor: Failable>, + items: [Order.Item]?, + shipping: Shipping? + ) { + self.reference = reference + self.amount = amount + self.payee = payee + self.paymentInstruction = paymentInstruction + self.description = description + self.customID = customID + self.invoice = invoice + self.softDescriptor = softDescriptor + self.items = items + self.shipping = shipping + } + + enum CodingKeys: String, CodingKey { + case amount, payee, description, items, shipping + case reference = "reference_id" + case paymentInstruction = "payment_instruction" + case customID = "custom_id" + case invoice = "invoice_id" + case softDescriptor = "soft_descriptor" + } +} diff --git a/Sources/V2/Models/Order/PurchaseUnit/Shipping.swift b/Sources/V2/Models/Order/PurchaseUnit/Shipping.swift new file mode 100644 index 00000000..cb6b160b --- /dev/null +++ b/Sources/V2/Models/Order/PurchaseUnit/Shipping.swift @@ -0,0 +1,26 @@ +import PayPal + +extension PurchaseUnit { + + /// The name and address of the person to ship items to. + public struct Shipping: Codable { + + /// The name of the person to whom to ship the items. + public var name: Failable> + + /// The address of the person to whom to ship the items. Supports only the `address_line_1`, `address_line_2`, + /// `admin_area_1`, `admin_area_2`, `postal_code`, and `country_code` properties. + public var address: Address? + + /// Creates a new `PurchaseUnit.Shipping` inctance. + /// + /// - Parameters: + /// - name: The name of the person to whom to ship the items. + /// - address: The address of the person to whom to ship the items. + public init(name: Failable>, address: Address?) { + self.name = name + self.address = address + } + } + +} diff --git a/Sources/V2/Models/Payee/PayeeBase.swift b/Sources/V2/Models/Payee/PayeeBase.swift new file mode 100644 index 00000000..24843c3c --- /dev/null +++ b/Sources/V2/Models/Payee/PayeeBase.swift @@ -0,0 +1,29 @@ +import Failable + +/// The recipient of the fee for a transaction. +public struct PayeeBase: Codable { + + /// The email address of merchant. + public let email: Failable> + + /// The encrypted PayPal account ID of the merchant. + public let merchant: Failable> + + /// Creates a new `PayeeBase` instance. + /// + /// - Parameters: + /// - email: The email address of merchant. + /// - merchant: The encrypted PayPal account ID of the merchant. + public init( + email: Failable>, + merchant: Failable> + ) { + self.email = email + self.merchant = merchant + } + + enum CodingKeys: String, CodingKey { + case email = "email_address" + case merchant = "merchant_id" + } +} diff --git a/Sources/V2/Models/Payment/Authorization/Authorization.swift b/Sources/V2/Models/Payment/Authorization/Authorization.swift new file mode 100644 index 00000000..f83cdcb1 --- /dev/null +++ b/Sources/V2/Models/Payment/Authorization/Authorization.swift @@ -0,0 +1,75 @@ +/// The details of an authorized payment. +public struct Authorization: Codable { + /// The status for the authorized payment. + public let status: PaymentStatus? + + /// The PayPal-generated ID for the authorized payment. + public let id: String? + + /// The amount for this authorized payment. + public let amount: CurrencyCodeAmount? + + /// The API caller-provided external invoice number for this order. + /// Appears in both the payer's transaction history and the emails that the payer receives. + public let invoice: String? + + /// The level of protection offered as defined by + /// [PayPal Seller Protection for Merchants](https://www.paypal.com/us/webapps/mpp/security/seller-protection). + public let sellerProtection: SellerProtection? + + /// The date and time when the authorized payment expires, + /// in [Internet date and time format](https://tools.ietf.org/html/rfc3339#section-5.6). + public let expiration: ISO8601Date? + + /// An array of related [HATEOAS links](https://developer.paypal.com/docs/api/overview/#hateoas-links). + public let links: [LinkDescription]? + + /// The date and time when the transaction occurred, + /// in [Internet date and time format](https://tools.ietf.org/html/rfc3339#section-5.6). + public let created: ISO8601Date? + + /// The date and time when the transaction was last updated, + /// in [Internet date and time format](https://tools.ietf.org/html/rfc3339#section-5.6). + public let updated: ISO8601Date? + + /// Creates a new `Authorization` instance. + /// + /// - Parameters: + /// - status: The status for the authorized payment. + /// - amount: The PayPal-generated ID for the authorized payment. + /// - invoice: The amount for this authorized payment. + /// - sellerProtection: The level of protection offered as defined by PayPal Seller Protection for Merchants. + /// - expiration: The date and time when the authorized payment expires. + /// - links: An array of related HATEOAS links. + /// - created: The date and time when the transaction occurred. + /// - updated: The date and time when the transaction was last updated. + public init( + status: PaymentStatus?, + amount: CurrencyCodeAmount?, + invoice: String?, + sellerProtection: SellerProtection?, + expiration: ISO8601Date?, + links: [LinkDescription]?, + created: ISO8601Date?, + updated: ISO8601Date? + ) { + self.id = nil + self.status = status + self.amount = amount + self.invoice = invoice + self.sellerProtection = sellerProtection + self.expiration = expiration + self.links = links + self.created = created + self.updated = updated + } + + enum CodingKeys: String, CodingKey { + case status, id, amount, links + case invoice = "invoice_id" + case sellerProtection = "seller_protection" + case expiration = "expiration_time" + case created = "create_time" + case updated = "update_time" + } +} diff --git a/Sources/V2/Models/Payment/Authorization/AuthorizationCapture.swift b/Sources/V2/Models/Payment/Authorization/AuthorizationCapture.swift new file mode 100644 index 00000000..6a1cf36e --- /dev/null +++ b/Sources/V2/Models/Payment/Authorization/AuthorizationCapture.swift @@ -0,0 +1,53 @@ +import PayPal + +extension Authorization { + + /// A capture for an authorized payment. + public struct Capture: Codable { + + /// The amount to capture. To capture a portion of the full authorized amount, specify an amount. + /// If amount is not specified, the full authorized amount is captured. The amount must be a positive number + /// and in the same currency as the authorization against which the payment is being captured. + public let amount: CurrencyCodeAmount? + + /// The API caller-provided external invoice number for this order. + /// Appears in both the payer's transaction history and the emails that the payer receives. + public let invoice: Optional127String + + /// Indicates whether you can make additional captures against the authorized payment. + /// Set to true if you do not intend to capture additional payments against the authorization. + /// Set to false if you intend to capture additional payments against the authorization. + public let final: Bool? + + /// Any additional payment instructions for PayPal for Partner customers. + /// Enables features for partners and marketplaces, such as delayed disbursement and collection of a platform fee. + /// Applies during order creation for captured payments or during capture of authorized payments. + public let instruction: PaymentInstruction? + + /// Creates a new `Authorization.Capture` instance. + /// + /// - Parameters: + /// - amount: The amount to capture. + /// - invoice: The API caller-provided external invoice number for this order. + /// - final: Indicates whether you can make additional captures against the authorized payment. Defaults to `false`. + /// - instruction: Any additional payment instructions for PayPal for Partner customers. + public init( + amount: CurrencyCodeAmount?, + invoice: Optional127String, + final: Bool? = false, + instruction: PaymentInstruction? + ) { + self.amount = amount + self.invoice = invoice + self.final = final + self.instruction = instruction + } + + enum CodingKeys: String, CodingKey { + case amount + case invoice = "invoice_id" + case final = "final_capture" + case instruction = "payment_instruction" + } + } +} diff --git a/Sources/V2/Models/Payment/Capture/Capture.swift b/Sources/V2/Models/Payment/Capture/Capture.swift new file mode 100644 index 00000000..90826aaf --- /dev/null +++ b/Sources/V2/Models/Payment/Capture/Capture.swift @@ -0,0 +1,98 @@ +import PayPal + +/// A captured payment. +public struct Capture: Codable { + /// The status for the authorized payment. + public let status: PaymentStatus? + + /// The details of the captured payment status. + public let statusDetails: PaymentStatusDetails? + + /// The PayPal-generated ID for the authorized payment. + public let id: String? + + /// The amount for this authorized payment. + public let amount: CurrencyCodeAmount? + + /// The API caller-provided external invoice number for this order. + /// Appears in both the payer's transaction history and the emails that the payer receives. + public let invoice: String? + + /// The level of protection offered as defined by + /// [PayPal Seller Protection for Merchants](https://www.paypal.com/us/webapps/mpp/security/seller-protection). + public let sellerProtection: SellerProtection? + + /// Indicates whether you can make additional captures against the authorized payment. + /// Set to `true` if you do not intend to capture additional payments against the authorization. + /// Set to `false` if you intend to capture additional payments against the authorization. + public let `final`: Bool? + + /// The detailed breakdown of the captured payment. + public let breakdown: SellerReceivableBreakdown? + + /// The funds that are held on behalf of the merchant. + public let disbursement: DisbursementMode? + + /// An array of related [HATEOAS links](https://developer.paypal.com/docs/api/overview/#hateoas-links). + public let links: [LinkDescription]? + + /// The date and time when the transaction occurred, + /// in [Internet date and time format](https://tools.ietf.org/html/rfc3339#section-5.6). + public let created: ISO8601Date? + + /// The date and time when the transaction was last updated, + /// in [Internet date and time format](https://tools.ietf.org/html/rfc3339#section-5.6). + public let updated: ISO8601Date? + + /// Creates a new `Authorization` instance. + /// + /// - Parameters: + /// - status: The status for the authorized payment. + /// - amount: The PayPal-generated ID for the authorized payment. + /// - invoice: The amount for this authorized payment. + /// - sellerProtection: The level of protection offered as defined by PayPal Seller Protection for Merchants. + /// - final: Indicates whether you can make additional captures against the authorized payment. + /// - breakdown: The detailed breakdown of the captured payment. + /// - disbursement: The funds that are held on behalf of the merchant. + /// - links: An array of related HATEOAS links. + /// - created: The date and time when the transaction occurred. + /// - updated: The date and time when the transaction was last updated. + public init( + status: PaymentStatus?, + statusDetails: PaymentStatusDetails?, + amount: CurrencyCodeAmount?, + invoice: String?, + sellerProtection: SellerProtection?, + `final`: Bool?, + breakdown: SellerReceivableBreakdown?, + disbursement: DisbursementMode?, + links: [LinkDescription]?, + created: ISO8601Date?, + updated: ISO8601Date? + ) { + self.id = nil + self.status = status + self.statusDetails = statusDetails + self.amount = amount + self.invoice = invoice + self.sellerProtection = sellerProtection + self.`final` = `final` + self.breakdown = breakdown + self.disbursement = disbursement + self.links = links + self.created = created + self.updated = updated + } + + enum CodingKeys: String, CodingKey { + case status, id, amount, links + case statusDetails = "status_details" + case invoice = "invoice_id" + case sellerProtection = "seller_protection" + case `final` = "final_capture" + case breakdown = "seller_receivable_breakdown" + case disbursement = "disbursement_mode" + case created = "create_time" + case updated = "update_time" + } +} diff --git a/Sources/V2/Models/Payment/Capture/CaptureRefund.swift b/Sources/V2/Models/Payment/Capture/CaptureRefund.swift new file mode 100644 index 00000000..75fd669a --- /dev/null +++ b/Sources/V2/Models/Payment/Capture/CaptureRefund.swift @@ -0,0 +1,42 @@ +import PayPal + +extension Capture { + + /// A refund for a captured payment. + public struct Refund: Codable { + + /// The amount to refund. To refund a portion of the captured amount, specify an amount. + /// If amount is not specified, an amount equal to captured amount - previous refunds is refunded. + /// The amount must be a positive number and in the same currency as the one in which the payment was captured. + public var amount: CurrencyCodeAmount? + + /// The API caller-provided external invoice number for this order. + /// Appears in both the payer's transaction history and the emails that the payer receives. + public var invoice: Optional127String + + /// The reason for the refund. Appears in both the payer's transaction history and the emails that the payer receives. + public var note: Failable> + + /// Creates a new `Capture.Refund` instance. + /// + /// - Parameters: + /// - amount: The amount to refund. If `nil`, a full refund is made. + /// - invoice: The API caller-provided external invoice number for this order. + /// - note: The reason for the refund. + public init( + amount: CurrencyCodeAmount?, + invoice: Optional127String, + note: Failable> + ) { + self.amount = amount + self.invoice = invoice + self.note = note + } + + enum CodingKeys: String, CodingKey { + case amount + case invoice = "invoice_id" + case note = "note_to_payer" + } + } +} diff --git a/Sources/V2/Models/Payment/DisbursementMode.swift b/Sources/V2/Models/Payment/DisbursementMode.swift new file mode 100644 index 00000000..ebe6f866 --- /dev/null +++ b/Sources/V2/Models/Payment/DisbursementMode.swift @@ -0,0 +1,11 @@ +/// Funds that are held on behalf of the merchant. +public enum DisbursementMode: String, Hashable, Codable, CaseIterable { + + /// The funds are released to the merchant immediately. + case instant = "INSTANT" + + /// The funds are held for a finite number of days. The actual duration depends on the region and type of integration. + /// You can release the funds through a referenced payout. + /// Otherwise, the funds disbursed automatically after the specified duration. + case delayed = "DELAYED" +} diff --git a/Sources/V2/Models/Payment/ExchangeRate.swift b/Sources/V2/Models/Payment/ExchangeRate.swift new file mode 100644 index 00000000..c6d9bc79 --- /dev/null +++ b/Sources/V2/Models/Payment/ExchangeRate.swift @@ -0,0 +1,39 @@ +import Foundation +import PayPal + +/// Defines a relationship between two different currencies, where the value is equal to 1 unit of the source currency. +/// +/// If you where going to represent the exchange rate between `USD` and `EUR`, it might look like this: +/// +/// // Rate from Mar 28, 2019, 3:48 PM UTC +/// ExchangeRate(source: .usd, target: .eur, value: 0.89) +public struct ExchangeRate: Codable { + + /// The source currency from which to convert an amount. + public let source: Currency? + + /// The target currency into which to convert an amount. + public let target: Currency? + + /// The target currency amount. Equivalent to one unit of the source currency. + /// Formatted as integer or decimal value with one to 15 digits to the right of the decimal point. + public let value: Decimal? + + /// Creates a new `ExchangeRate` instance. + /// + /// - Parameters: + /// - source: The source currency from which to convert an amount. + /// - target: The target currency into which to convert an amount. + /// - value: The target currency amount. + public init(source: Currency?, target: Currency?, value: Decimal?) { + self.source = source + self.target = target + self.value = value + } + + enum CodingKeys: String, CodingKey { + case source = "source_currency" + case target = "target_currency" + case value + } +} diff --git a/Sources/V2/Models/Payment/PaymentInstruction.swift b/Sources/V2/Models/Payment/PaymentInstruction.swift new file mode 100644 index 00000000..016b0e39 --- /dev/null +++ b/Sources/V2/Models/Payment/PaymentInstruction.swift @@ -0,0 +1,27 @@ +import PayPal + +/// Additional payment instructions for PayPal for Partner customers. +/// Enables features for partners and marketplaces, such as delayed disbursement and collection of a platform fee. +public struct PaymentInstruction: Codable { + + /// An array of various fees, commissions, tips, or donations. + public var fees: [PlatformFee]? + + /// The funds that are held on behalf of the merchant. + public var disbursement: DisbursementMode? + + /// Creates a new `PaymentInstruction` instance. + /// + /// - Parameters: + /// - fees: An array of various fees, commissions, tips, or donations. + /// - disbursement: The funds that are held on behalf of the merchant. Defaults to `.instant`. + public init(fees: [PlatformFee]?, disbursement: DisbursementMode? = .instant) { + self.fees = fees + self.disbursement = disbursement + } + + enum CodingKeys: String, CodingKey { + case fees = "platform_fees" + case disbursement = "disbursement_mode" + } +} diff --git a/Sources/V2/Models/Payment/PlatformFee.swift b/Sources/V2/Models/Payment/PlatformFee.swift new file mode 100644 index 00000000..9f466c7c --- /dev/null +++ b/Sources/V2/Models/Payment/PlatformFee.swift @@ -0,0 +1,21 @@ +import PayPal + +/// A fee, commission, tip, or donation. +public struct PlatformFee: Codable { + + /// The fee for a transaction. + public let amount: CurrencyCodeAmount + + /// The recipient of the fee for this transaction. If you omit this value, the default is the API caller. + public let payee: PayeeBase? + + /// Creates a new `PlatformFee` instance. + /// + /// - Parameters: + /// - amount: The fee for a transaction. + /// - payee: The recipient of the fee for this transaction. + public init(amount: CurrencyCodeAmount, payee: PayeeBase? = nil) { + self.amount = amount + self.payee = payee + } +} diff --git a/Sources/V2/Models/Payment/Refund/Refund.swift b/Sources/V2/Models/Payment/Refund/Refund.swift new file mode 100644 index 00000000..35883da4 --- /dev/null +++ b/Sources/V2/Models/Payment/Refund/Refund.swift @@ -0,0 +1,83 @@ +import PayPal + +/// A refunded payment. +public struct Refund: Codable { + /// The status for the authorized payment. + public let status: PaymentStatus? + + /// The details of the captured payment status. + public let statusDetails: PaymentStatusDetails? + + /// The PayPal-generated ID for the authorized payment. + public let id: String? + + /// The amount for this authorized payment. + public let amount: CurrencyCodeAmount? + + /// The API caller-provided external invoice number for this order. + /// Appears in both the payer's transaction history and the emails that the payer receives. + public let invoice: String? + + /// The reason for the refund. Appears in both the payer's transaction history and the emails that the payer receives. + public let note: String? + + /// The level of protection offered as defined by + /// [PayPal Seller Protection for Merchants](https://www.paypal.com/us/webapps/mpp/security/seller-protection). + public let sellerProtection: SellerProtection? + + /// An array of related [HATEOAS links](https://developer.paypal.com/docs/api/overview/#hateoas-links). + public let links: [LinkDescription]? + + /// The date and time when the transaction occurred, + /// in [Internet date and time format](https://tools.ietf.org/html/rfc3339#section-5.6). + public let created: ISO8601Date? + + /// The date and time when the transaction was last updated, + /// in [Internet date and time format](https://tools.ietf.org/html/rfc3339#section-5.6). + public let updated: ISO8601Date? + + /// Creates a new `Authorization` instance. + /// + /// - Parameters: + /// - status: The status for the authorized payment. + /// - amount: The PayPal-generated ID for the authorized payment. + /// - invoice: The amount for this authorized payment. + /// - note: The reason for the refund. + /// - sellerProtection: The level of protection offered as defined by PayPal Seller Protection for Merchants. + /// - expiration: The date and time when the authorized payment expires. + /// - links: An array of related HATEOAS links. + /// - created: The date and time when the transaction occurred. + /// - updated: The date and time when the transaction was last updated. + public init( + status: PaymentStatus?, + statusDetails: PaymentStatusDetails?, + amount: CurrencyCodeAmount?, + invoice: String?, + note: String?, + sellerProtection: SellerProtection?, + links: [LinkDescription]?, + created: ISO8601Date?, + updated: ISO8601Date? + ) { + self.id = nil + self.status = status + self.statusDetails = statusDetails + self.amount = amount + self.invoice = invoice + self.note = note + self.sellerProtection = sellerProtection + self.links = links + self.created = created + self.updated = updated + } + + enum CodingKeys: String, CodingKey { + case status, id, amount, links + case statusDetails = "status_details" + case invoice = "invoice_id" + case note = "note_to_payer" + case sellerProtection = "seller_protection" + case created = "create_time" + case updated = "update_time" + } +} diff --git a/Sources/V2/Models/Payment/Seller/SellerProtection.swift b/Sources/V2/Models/Payment/Seller/SellerProtection.swift new file mode 100644 index 00000000..577e5557 --- /dev/null +++ b/Sources/V2/Models/Payment/Seller/SellerProtection.swift @@ -0,0 +1,40 @@ +/// A transcation's protection level. +/// +/// This will be defined for a transaction by the +/// [PayPal Seller Protection for Merchants](https://www.paypal.com/us/webapps/mpp/security/seller-protection). +public struct SellerProtection: Codable { + + /// Indicates whether the transaction is eligible for seller protection. For information, + /// see [PayPal Seller Protection for Merchants](https://www.paypal.com/us/webapps/mpp/security/seller-protection). + public let status: Status? + + /// An array of conditions that are covered for the transaction. + public let disputes: [DisputeCategories]? + + /// Creates a new `SellerProtection` instance + /// + /// - Parameters: + /// - status: Indicates whether the transaction is eligible for seller protection. + /// - disputes: An array of conditions that are covered for the transaction. + public init(status: Status?, disputes: [DisputeCategories]?) { + self.status = status + self.disputes = disputes + } + + internal enum CodingKeys: String, CodingKey { + case status + case disputes = "dispute_categories" + } +} + +extension SellerProtection { + + /// The dispute conditions that can be covered by a transaction. + public enum DisputeCategories: String, Hashable, Codable, CaseIterable { + /// The payer paid for an item that he or she did not receive. + case itemNotReceived = "ITEM_NOT_RECEIVED" + + /// The payer did not authorize the payment. + case unauthorizedTransaction = "UNAUTHORIZED_TRANSACTION" + } +} diff --git a/Sources/V2/Models/Payment/Seller/SellerProtectionStatus.swift b/Sources/V2/Models/Payment/Seller/SellerProtectionStatus.swift new file mode 100644 index 00000000..bd873852 --- /dev/null +++ b/Sources/V2/Models/Payment/Seller/SellerProtectionStatus.swift @@ -0,0 +1,15 @@ +extension SellerProtection { + + /// The transaction eligibility statuses for seller protection. + public enum Status: String, Hashable, Codable, CaseIterable { + /// Your PayPal balance remains intact if the customer claims that he or she did not + /// receive an item or the account holder claims that he or she did not authorize the payment. + case eligible = "ELIGIBLE" + + /// Your PayPal balance remains intact if the customer claims that he or she did not receive an item. + case partiallyEligible = "PARTIALLY_ELIGIBLE" + + /// This transaction is not eligible for seller protection. + case notEligible = "NOT_ELIGIBLE" + } +} diff --git a/Sources/V2/Models/Payment/Seller/SellerReceivableBreakdown.swift b/Sources/V2/Models/Payment/Seller/SellerReceivableBreakdown.swift new file mode 100644 index 00000000..44c5e6e2 --- /dev/null +++ b/Sources/V2/Models/Payment/Seller/SellerReceivableBreakdown.swift @@ -0,0 +1,62 @@ +import PayPal + +/// The detailed breakdown of a captured payment. +public struct SellerReceivableBreakdown: Codable { + + /// The amount for this captured payment. + public let gross: CurrencyCodeAmount? + + /// The applicable fee for this captured payment. + public let fee: CurrencyCodeAmount? + + /// The net amount that the payee receives for this captured payment in their PayPal account. + /// The net amount is computed as `gross_amount` minus the `paypal_fee` minus the `platform_fees`. + public let net: CurrencyCodeAmount? + + /// The net amount that is credited to the payee's PayPal account. + /// Returned only when the currency of the captured payment is different from the currency of the PayPal account + /// where the payee wants to credit the funds. The amount is computed as `net_amount` times `exchange_rate`. + public let receivable: CurrencyCodeAmount? + + /// The exchange rate that determines the amount that is credited to the payee's PayPal account. + /// Returned when the currency of the captured payment is different from the currency of the PayPal account + /// where the payee wants to credit the funds. + public let exchangeRate: ExchangeRate? + + /// An array of platform or partner fees, commissions, or brokerage fees that associated with the captured payment. + public let fees: [PlatformFee]? + + /// Creates a new `SellerReceivableBreakdown` instance. + /// + /// - Parameters: + /// - gross: The amount for this captured payment. + /// - fee: The applicable fee for this captured payment. + /// - net: The net amount that the payee receives for this captured payment in their PayPal account. + /// - receivable: The net amount that is credited to the payee's PayPal account. + /// - exchangeRate: The exchange rate that determines the amount that is credited to the payee's PayPal account. + /// - fees: Platform or partner fees, commissions, or brokerage fees that associated with a captured payment. + public init( + gross: CurrencyCodeAmount?, + fee: CurrencyCodeAmount?, + net: CurrencyCodeAmount?, + receivable: CurrencyCodeAmount?, + exchangeRate: ExchangeRate?, + fees: [PlatformFee]? + ) { + self.gross = gross + self.fee = fee + self.net = net + self.receivable = receivable + self.exchangeRate = exchangeRate + self.fees = fees + } + + enum CodingKeys: String, CodingKey { + case gross = "gross_amount" + case fee = "paypal_fee" + case net = "net_amount" + case receivable = "receivable_amount" + case exchangeRate = "exchange_rate" + case fees = "platform_fees" + } +} diff --git a/Sources/V2/Models/Payment/Status/PaymentStatus.swift b/Sources/V2/Models/Payment/Status/PaymentStatus.swift new file mode 100644 index 00000000..e2a48ee5 --- /dev/null +++ b/Sources/V2/Models/Payment/Status/PaymentStatus.swift @@ -0,0 +1,63 @@ +/// The possible statuses for an authorized payment. +public enum PaymentStatus: String, Hashable, Codable, CaseIterable { + /// The authorized payment is created. No captured payments have been made for this authorized payment. + case created = "CREATED" + + /// The authorized payment has one or more captures against it. + /// The sum of these captured payments is greater than the amount of the original authorized payment. + case captured = "CAPTURED" + + /// PayPal cannot authorize funds for this authorized payment. + case denied = "DENIED" + + /// The authorized payment has expired. + case expired = "EXPIRED" + + /// A captured payment was made for the authorized payment for an amount that is less + /// than the amount of the original authorized payment. + case partiallyCaptured = "PARTIALLY_CAPTURED" + + /// The authorized payment was voided. No more captured payments can be made against this authorized payment. + case voided = "VOIDED" +} + +/// The reason why a captured payment status is `PENDING` or `DENIED`. +public enum PaymentStatusDetails: String, Hashable, Codable, CaseIterable { + /// The payer initiated a dispute for this captured payment with PayPal. + case buyerComplaint = "BUYER_COMPLAINT" + + /// The captured funds were reversed in response to the payer disputing this captured payment + /// with the issuer of the financial instrument used to pay for this captured payment. + case chargeback = "CHARGEBACK" + + /// The payer paid by an eCheck that has not yet cleared. + case echeck = "ECHECK" + + /// Visit your online account. In your **Account Overview**, accept and deny this payment. + case internationalWithdrawal = "INTERNATIONAL_WITHDRAWAL" + + /// No additional specific reason can be provided. For more information about this captured payment, + /// visit your account online or contact PayPal. + case other = "OTHER" + + /// The captured payment is pending manual review. + case pendingReview = "PENDING_REVIEW" + + /// The payee has not yet set up appropriate receiving preferences for their account. + /// For more information about how to accept or deny this payment, visit your account online. + /// This reason is typically offered in scenarios such as when the currency of the captured payment + /// is different from the primary holding currency of the payee. + case waitingManualAction = "RECEIVING_PREFERENCE_MANDATES_MANUAL_ACTION" + + /// The captured funds were refunded. + case refunded = "REFUNDED" + + /// The payer must send the funds for this captured payment. This code generally appears for manual EFTs. + case awaitingFunding = "TRANSACTION_APPROVED_AWAITING_FUNDING" + + /// The payee does not have a PayPal account. + case unilateral = "UNILATERAL" + + /// The payee's PayPal account is not verified. + case verificationRequired = "VERIFICATION_REQUIRED" +} diff --git a/Sources/V2/Models/PaymentSource/Card.swift b/Sources/V2/Models/PaymentSource/Card.swift new file mode 100644 index 00000000..b614902b --- /dev/null +++ b/Sources/V2/Models/PaymentSource/Card.swift @@ -0,0 +1,139 @@ +import PayPal + +extension PaymentSource { + + /// A payment card used to fund a transaction. This can be a credit card or a debit card. + public struct Card: Codable { + + /// The PayPal-generated ID for the card. + public let id: String? + + /// The last digits of the payment card. + public let suffix: Failable> + + /// The card brand or network. Typically used in the response. + public let type: CardType? + + /// The card holder's name as it appears on the card. + public var name: Optional300String + + /// The primary account number (PAN) for the payment card. + public var number: Failable + + /// The card expiration year and month. + public var expiry: YearMonthDate + + /// The three- or four-digit security code of the card. Also known as the CVV, CVC, CVN, CVE, or CID. + public var securityCode: Failable> + + /// The billing address for this card. Supports only the `address_line_1`, `address_line_2`, `admin_area_1`, + /// `admin_area_2`, `postal_code`, and `country_code` properties. + public var billing: Address? + + /// Creates a new `PaymentSource.Card` instance. + /// + /// - Parameters: + /// - name: The card holder's name as it appears on the card. + /// - number: The primary account number (PAN) for the payment card. + /// - expiry: The card expiration year and month. + /// - securityCode: The three- or four-digit security code of the card. + public init( + name: Optional300String, + number: Failable, + expiry: YearMonthDate, + securityCode: Failable>, + billing: Address? + ) { + self.id = nil + self.suffix = nil + self.type = nil + + self.name = name + self.number = number + self.expiry = expiry + self.securityCode = securityCode + self.billing = billing + } + + /// The validator for the `PaymentSource.Card.number` property value. + public struct Number: RegexValidation { + + /// See `RegexValidator.patter`. + public static let pattern: String = #"^\d{13,19}$"# + } + + /// The validator for the `PaymentSource.Card.securityCode` property value. + public struct SecurityCode: RegexValidation { + + /// See `RegexValidator.patter`. + public static let pattern: String = "[0-9]{3,4}" + } + + /// The validator for the `PaymentSource.Card.suffix` property, + public struct Suffix: RegexValidation { + + /// See `RegexValidator.patter`. + public static let pattern: String = "[0-9]{2,}" + } + + enum CodingKeys: String, CodingKey { + case id, name, number, expiry + case suffix = "last_digits" + case type = "card_type" + case securityCode = "security_code" + case billing = "billing_address" + } + } + + /// The valid card brand or network options for a `PaymentSource.Card` instance. + public enum CardType: String, Hashable, CaseIterable, Codable { + + /// Visa card. + case visa = "VISA" + + /// MasterCard card. + case mastercard = "MASTERCARD" + + /// Discover card. + case discover = "DISCOVER" + + /// American Express card. + case amex = "AMEX" + + /// Solo debit card. + case solo = "SOLO" + + /// Japan Credit Bureau card. + case jcb = "JCB" + + /// Military Star card. + case star = "STAR" + + /// Delta Airlines card. + case delta = "DELTA" + + /// Switch credit card. + case `switch` = "SWITCH" + + /// Maestro credit card. + case maestro = "MAESTRO" + + /// Carte Bancaire (CB) credit card. + case cbNationale = "CB_NATIONALE" + + /// Configoga credit card. + case configoga = "CONFIGOGA" + + /// Confidis credit card. + case confidis = "CONFIDIS" + + /// Visa Electron credit card. + case electron = "ELECTRON" + + /// Cetelem credit card. + case cetelem = "CETELEM" + + /// China union pay credit card. + case chinaUnionPay = "CHINA_UNION_PAY" + } +} diff --git a/Sources/V2/Models/PaymentSource/PaymentSource.swift b/Sources/V2/Models/PaymentSource/PaymentSource.swift new file mode 100644 index 00000000..48d3da6d --- /dev/null +++ b/Sources/V2/Models/PaymentSource/PaymentSource.swift @@ -0,0 +1,19 @@ +/// The source of payment for a transaction, which can be a token or a card. +public struct PaymentSource: Codable { + + /// The payment card to use to fund a payment. Can be a credit or debit card. + public var card: Card? + + /// The tokenized payment source to fund a payment. + public var token: Token? + + /// Creates a new `PaymentSource` instance. + /// + /// - Parameters: + /// - card: The payment card to use to fund a payment. + /// - token: The tokenized payment source to fund a payment. + public init(card: Card?, token: Token?) { + self.card = card + self.token = token + } +} diff --git a/Sources/V2/Models/PaymentSource/Token.swift b/Sources/V2/Models/PaymentSource/Token.swift new file mode 100644 index 00000000..f01b73ee --- /dev/null +++ b/Sources/V2/Models/PaymentSource/Token.swift @@ -0,0 +1,51 @@ +import Failable + +extension PaymentSource { + + /// A tokenized payment source to fund a payment. + public struct Token: Codable { + + /// The PayPal-generated ID for the token. + public var id: Failable + + /// The tokenization method that was used to generate the ID. + public var type: TokenType + + /// Creates a new `PaymentSource.Token` instance. + /// + /// - Parameters: + /// - id: The PayPal-generated ID for the token. + /// - type: The tokenization method that was used to generate the ID. + public init(id: Failable, type: TokenType) { + self.id = id + self.type = type + } + + /// The validation for the `PaymentSource.Token.id` property value. + public struct ID: LengthValidation { + + /// See `Validation.Suppoorted`. + public typealias Supported = String + + /// See `LengthValidation.minLength`. + public static var minLength: Int = 1 + + /// See `LengthValidation.maxLength`. + public static var maxLength: Int = 255 + } + } + + /// The tokenization method that was used to generate the ID for a `PaymentSource.Token` instance. + public enum TokenType: String, Hashable, CaseIterable, Codable { + + /// A secure, one-time-use reference to a payment source, such as payment card, PayPal account, and so on. + case nonce = "NONCE" + + /// The payment method token, which is a reference to a transactional payment source. + /// Typically stored on the merchant's server. + case paymentMethod = "PAYMENT_METHOD_TOKEN" + + /// The PayPal billing agreement ID. References an approved recurring payment for goods or services. + case billingAgreement = "BILLING_AGREEMENT" + } +} diff --git a/Sources/V2/Models/PreferResponse.swift b/Sources/V2/Models/PreferResponse.swift new file mode 100644 index 00000000..7619ed1a --- /dev/null +++ b/Sources/V2/Models/PreferResponse.swift @@ -0,0 +1,10 @@ +/// The preferred server response upon successful completion of a request. +public enum PreferResponse: String { + + /// The server returns a minimal response to optimize communication between the API caller and the server. + /// A minimal response includes the `id`, `status` and HATEOAS links. + case minimal = "return=minimal" + + /// The server returns a complete resource representation, including the current state of the resource. + case representation = "return=representation" +} diff --git a/Sources/V2/Utilities/Validations.swift b/Sources/V2/Utilities/Validations.swift new file mode 100644 index 00000000..5a51ea2c --- /dev/null +++ b/Sources/V2/Utilities/Validations.swift @@ -0,0 +1,15 @@ +import Failable + +/// A validation for email addresses for v2 of the PayPal REST API. +public struct EmailValidation: RegexValidation { + + /// See `RegexValidation.pattern`. + public static var pattern: String = #"(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])"# +} + +/// A validation for the `PayeeBase.merchant` property value. +public struct IDValidation: RegexValidation { + + /// See `RegexValidation.pattern`. + public static var pattern: String = #"^[2-9A-HJ-NP-Z]{13}$"# +} diff --git a/Sources/V2/Utilities/YearMonthDate.swift b/Sources/V2/Utilities/YearMonthDate.swift new file mode 100644 index 00000000..a474ed0e --- /dev/null +++ b/Sources/V2/Utilities/YearMonthDate.swift @@ -0,0 +1,68 @@ +import Foundation +import PayPal +import NIO + +/// A date that only contains year and month information, like a credit card expiration date. +public struct YearMonthDate: Codable { + internal static let typeSafeFormatter: ThreadSpecificVariable = { + let formatter = DateFormatter() + formatter.calendar = Calendar(identifier: .iso8601) + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.dateFormat = "yyyy-MM" + return ThreadSpecificVariable(value: formatter) + }() + + internal static var formatter: DateFormatter? { + return YearMonthDate.typeSafeFormatter.currentValue + } + + /// The underlying date instance. + public var date: Date + + /// Creates a new `YearMonthDate` instance from a `Date`. + /// + /// - Parameter date: The `Date` instance to initialize from. The date that will be stored will have all + /// information except that year and month removed, so `2019-04-02 20:16:53 +0000` becomes `2019-04-01 00:00:00 +0000`. + public init(_ date: Date) { + var calendar = Calendar(identifier: .iso8601) + calendar.timeZone = TimeZone(secondsFromGMT: 0) ?? calendar.timeZone + self.date = calendar.date(from: calendar.dateComponents([.year, .month], from: date)) ?? date + } + + /// Creates a new `YearMonthDate` instance from a `String` containg that date information. + /// + /// - Parameter string: The string with the date information, using the `yyyy-MM` format. + /// If a date cannot be extracted from the string, the initializer will return `nil`. + public init?(string: String) { + guard let date = YearMonthDate.formatter?.date(from: string) else { return nil } + self.date = date + } + + /// See [`Decodable.init(from:)`](https://developer.apple.com/documentation/swift/decodable/2894081-init). + public init(from decoder: Decoder)throws { + let string = try decoder.singleValueContainer().decode(String.self) + guard let date = YearMonthDate.formatter?.date(from: string) else { + throw DecodingError.typeMismatch( + Date.self, + DecodingError.Context(codingPath: [], debugDescription: "Cannot get date from string `\(string)`") + ) + } + + self.date = date + } + + /// See [`Encodable.encode(to:)`](https://developer.apple.com/documentation/swift/encodable/2893603-encode). + public func encode(to encoder: Encoder)throws { + var container = encoder.singleValueContainer() + guard let string = YearMonthDate.formatter?.string(from: date) else { + throw PayPalError( + status: .internalServerError, + identifier: "missingFormatter", + reason: "No date formatter has been initialized for the current thread for `YearMonthDate`" + ) + } + + try container.encode(string) + } +} diff --git a/Sources/V2/V2.swift b/Sources/V2/V2.swift new file mode 100644 index 00000000..9a4b2526 --- /dev/null +++ b/Sources/V2/V2.swift @@ -0,0 +1,28 @@ +@_exported import PayPal + +extension API { + + /// Version 2 of the PayPal API resources. + public var v2: V2 { + return V2(client: self.client) + } +} + +/// A container for the controllers for version 2 of the PayPal API resources. +public struct V2 { + + /// The client used to send requests to PayPal. + internal let client: PayPalClient + + /// Creates a new `V2` instance with the `PayPalClient` instance it will use. + internal init(client: PayPalClient) { + assert(client.version == .v2, "Make sure your PayPalClient instance is configured with the correct API version") + self.client = client + } + + + /// The controller for the `/v2/payments` resource. + public var payments: Payments { + return Payments(client: self.client) + } +} diff --git a/Tests/ConfigTests/ConfigTests.swift b/Tests/ConfigTests/ConfigTests.swift index 2348d536..4782e9ea 100644 --- a/Tests/ConfigTests/ConfigTests.swift +++ b/Tests/ConfigTests/ConfigTests.swift @@ -1 +1 @@ -@_exported import TestsUtilities +@_exported import TestUtilities diff --git a/Tests/ConfigTests/EnvironmentTests.swift b/Tests/ConfigTests/EnvironmentTests.swift index 6a385d4e..39b52ee2 100644 --- a/Tests/ConfigTests/EnvironmentTests.swift +++ b/Tests/ConfigTests/EnvironmentTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class EnvironmentTests: XCTestCase { +public final class EnvironmentTests: XCTestCase { func testCaseRawValues() { XCTAssertEqual(Environment.production.rawValue, "production") XCTAssertEqual(Environment.sandbox.rawValue, "sandbox") @@ -17,7 +17,7 @@ final class EnvironmentTests: XCTestCase { XCTAssertEqual(Environment.allCases, [.sandbox, .production]) } - static var allTests: [(String, (EnvironmentTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (EnvironmentTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testCaseDomains", testCaseDomains), ("testAllCase", testAllCase) diff --git a/Tests/ConfigTests/ProviderTests.swift b/Tests/ConfigTests/ProviderTests.swift index b8cb14ec..e8566877 100644 --- a/Tests/ConfigTests/ProviderTests.swift +++ b/Tests/ConfigTests/ProviderTests.swift @@ -2,11 +2,11 @@ import XCTest import Vapor @testable import PayPal -final class ProviderTests: XCTestCase { +public final class ProviderTests: XCTestCase { var environment: Vapor.Environment = .testing var app: Application! - override func setUp() { + override public func setUp() { super.setUp() setPaypalVars() @@ -43,7 +43,7 @@ final class ProviderTests: XCTestCase { self.environment = .testing } - static var allTests: [(String, (ProviderTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ProviderTests) -> ()throws -> ())] = [ ("testBootSucceeds", testBootSucceeds), ("testConfigurationRegistered", testConfigurationRegistered), ("testConfigurationHasExpectedValues", testConfigurationHasExpectedValues) diff --git a/Tests/ControllerTests/APITests.swift b/Tests/ControllerTests/APITests.swift index 31f620c2..72c7d3d0 100644 --- a/Tests/ControllerTests/APITests.swift +++ b/Tests/ControllerTests/APITests.swift @@ -2,11 +2,12 @@ import XCTest import Vapor @testable import PayPal -final class APITests: XCTestCase { +// MARK: - Passing ✅ +public final class APITests: XCTestCase { var app: Application! - override func setUp() { + override public func setUp() { super.setUp() setPaypalVars() @@ -32,7 +33,7 @@ final class APITests: XCTestCase { XCTAssertNotNil(info.token) } - static var allTests: [(String, (APITests) -> ()throws -> ())] = [ + public static var allTests: [(String, (APITests) -> ()throws -> ())] = [ ("testQueryStringEncoding", testQueryStringEncoding), ("testAPIHelper", testAPIHelper) ] diff --git a/Tests/ControllerTests/ActivitiesTests.swift b/Tests/ControllerTests/ActivitiesTests.swift index af45cc99..39ded1f8 100644 --- a/Tests/ControllerTests/ActivitiesTests.swift +++ b/Tests/ControllerTests/ActivitiesTests.swift @@ -2,11 +2,12 @@ import XCTest import Vapor @testable import PayPal -final class ActivitiesTests: XCTestCase { +// MARK: - Passing ✅ +public final class ActivitiesTests: XCTestCase { var app: Application! - override func setUp() { + override public func setUp() { super.setUp() setPaypalVars() @@ -30,7 +31,7 @@ final class ActivitiesTests: XCTestCase { XCTAssertLessThanOrEqual(queried.items?.count ?? 0, 5) } - static var allTests: [(String, (ActivitiesTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ActivitiesTests) -> ()throws -> ())] = [ ("testServiceExists", testServiceExists), ("testActivitiesEndpoint", testActivitiesEndpoint) ] diff --git a/Tests/ControllerTests/AuthenticationTests.swift b/Tests/ControllerTests/AuthenticationTests.swift index f5df6f63..ed79fb5b 100644 --- a/Tests/ControllerTests/AuthenticationTests.swift +++ b/Tests/ControllerTests/AuthenticationTests.swift @@ -2,11 +2,12 @@ import XCTest import Vapor @testable import PayPal -final class AuthenticationTests: XCTestCase { +// MARK: - Passing ✅ +public final class AuthenticationTests: XCTestCase { var app: Application! - override func setUp() { + override public func setUp() { super.setUp() setPaypalVars() @@ -35,7 +36,7 @@ final class AuthenticationTests: XCTestCase { XCTAssertEqual(auth.tokenExpired, false) } - static var allTests: [(String, (AuthenticationTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AuthenticationTests) -> ()throws -> ())] = [ ("testTokenExpired", testTokenExpired), ("testAPIAuthentication", testAPIAuthentication) ] diff --git a/Tests/ControllerTests/BillingAgreementsTests.swift b/Tests/ControllerTests/BillingAgreementsTests.swift index b7f60d4f..0db2dc7b 100644 --- a/Tests/ControllerTests/BillingAgreementsTests.swift +++ b/Tests/ControllerTests/BillingAgreementsTests.swift @@ -2,12 +2,12 @@ import XCTest import Vapor @testable import PayPal -final class BillingAgreementsTests: XCTestCase { +public final class BillingAgreementsTests: XCTestCase { var app: Application! var id: String? - override func setUp() { + override public func setUp() { super.setUp() setPaypalVars() @@ -16,9 +16,9 @@ final class BillingAgreementsTests: XCTestCase { app = try! Application.testable(services: services) - if self.id == nil { - try! self.testCreateEndpoint() - } +// if self.id == nil { +// try! self.testCreateEndpoint() +// } } func testServiceExists()throws { @@ -153,7 +153,7 @@ final class BillingAgreementsTests: XCTestCase { XCTAssertNotEqual(details.id, id) } - static var allTests: [(String, (BillingAgreementsTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BillingAgreementsTests) -> ()throws -> ())] = [ ("testServiceExists", testServiceExists), ("testCreateEndpoint", testCreateEndpoint), ("testUpdateEndpoint", testUpdateEndpoint), diff --git a/Tests/ControllerTests/BillingPlansTests.swift b/Tests/ControllerTests/BillingPlansTests.swift index 3b5656d2..d2d0ac45 100644 --- a/Tests/ControllerTests/BillingPlansTests.swift +++ b/Tests/ControllerTests/BillingPlansTests.swift @@ -2,12 +2,13 @@ import XCTest import Vapor @testable import PayPal -final class BillingPlansTests: XCTestCase { +// MARK: - Passing ✅ +public final class BillingPlansTests: XCTestCase { var app: Application! var id: String? - override func setUp() { + override public func setUp() { super.setUp() setPaypalVars() @@ -15,17 +16,21 @@ final class BillingPlansTests: XCTestCase { try! services.register(PayPalProvider()) app = try! Application.testable(services: services) - - let plans = try! self.app.make(BillingPlans.self) - let list = try! plans.list(parameters: QueryParamaters(totalCountRequired: true)).wait() - self.id = list.plans?.first?.id.value } func testServiceExists()throws { _ = try app.make(BillingPlans.self) } - func testCreateEndpoint()throws { + func testEndpoints()throws { + try self.createEndpoint() + try self.listEndpoint() + try self.updateEndpoint() + try self.detailsEndpoint() + try self.setStateHelper() + } + + func createEndpoint()throws { let plans = try self.app.make(BillingPlans.self) let plan = try BillingPlan( name: .init("Monthly Water"), @@ -54,19 +59,20 @@ final class BillingPlansTests: XCTestCase { ) let created = try plans.create(with: plan).wait() + self.id = created.id.value XCTAssertEqual(created.name, plan.name) XCTAssertNotNil(created.id) } - func testListEndpoint()throws { + func listEndpoint()throws { let plans = try self.app.make(BillingPlans.self) let list = try plans.list(parameters: QueryParamaters(totalCountRequired: true)).wait() XCTAssertNotNil(list.plans) } - func testUpdateEndpoint()throws { + func updateEndpoint()throws { let plans = try self.app.make(BillingPlans.self) guard let id = self.id else { throw Abort(.internalServerError, reason: "Cannot get agreement ID to get") @@ -77,7 +83,7 @@ final class BillingPlansTests: XCTestCase { XCTAssertEqual(status, .ok) } - func testDetailsEndpoint()throws { + func detailsEndpoint()throws { let plans = try self.app.make(BillingPlans.self) guard let id = self.id else { throw Abort(.internalServerError, reason: "Cannot get agreement ID to get") @@ -88,7 +94,7 @@ final class BillingPlansTests: XCTestCase { XCTAssert(details.id.value == id) } - func testSetStateHelper()throws { + func setStateHelper()throws { let plans = try self.app.make(BillingPlans.self) guard let id = self.id else { throw Abort(.internalServerError, reason: "Cannot get agreement ID to get") @@ -99,13 +105,9 @@ final class BillingPlansTests: XCTestCase { XCTAssertEqual(status, .ok) } - static var allTests: [(String, (BillingPlansTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BillingPlansTests) -> ()throws -> ())] = [ ("testServiceExists", testServiceExists), - ("testCreateEndpoint", testCreateEndpoint), - ("testListEndpoint", testListEndpoint), - ("testUpdateEndpoint", testUpdateEndpoint), - ("testDetailsEndpoint", testDetailsEndpoint), - ("testSetStateHelper", testSetStateHelper) + ("testEndpoints", testEndpoints) ] } diff --git a/Tests/ControllerTests/ControllerTests.swift b/Tests/ControllerTests/ControllerTests.swift index 2348d536..4782e9ea 100644 --- a/Tests/ControllerTests/ControllerTests.swift +++ b/Tests/ControllerTests/ControllerTests.swift @@ -1 +1 @@ -@_exported import TestsUtilities +@_exported import TestUtilities diff --git a/Tests/ControllerTests/CustomerDiputesTests.swift b/Tests/ControllerTests/CustomerDiputesTests.swift index 68f2b1ea..bcfcfebe 100644 --- a/Tests/ControllerTests/CustomerDiputesTests.swift +++ b/Tests/ControllerTests/CustomerDiputesTests.swift @@ -3,12 +3,12 @@ import Vapor @testable import NIO @testable import PayPal -final class CustomerDisputesTests: XCTestCase { +public final class CustomerDisputesTests: XCTestCase { var app: Application! var id: String? - override func setUp() { + override public func setUp() { super.setUp() setPaypalVars() @@ -16,35 +16,45 @@ final class CustomerDisputesTests: XCTestCase { try! services.register(PayPalProvider()) app = try! Application.testable(services: services) - - let disputes = try! self.app.make(CustomerDisputes.self) - let list = try! disputes.list().wait() - self.id = list.items?.filter { $0.status != .resolved }.first?.id } func testServiceExists()throws { _ = try app.make(CustomerDisputes.self) } - func testListEndpoint()throws { + func testEndpoints()throws { + try self.listEndpoint() + try self.detailsEndpoint() + +// try self.appealEndpoint() +// try self.evidenceEndpoint() +// try self.escalateEndpoint() +// try self.offerEndpoint() +// try self.updateStatusEndpoint() +// try self.messageEndpoint() +// try self.acceptEndpoint() +// try self.settleEndpoint() + } + + func listEndpoint()throws { let disputes = try self.app.make(CustomerDisputes.self) let list = try disputes.list().wait() + self.id = list.items?.filter { $0.status != .resolved }.first?.id XCTAssertGreaterThan(list.items?.count ?? 0, 0) } - func testDetailsEndpoint()throws { + func detailsEndpoint()throws { let disputes = try self.app.make(CustomerDisputes.self) guard let id = self.id else { throw Abort(.internalServerError, reason: "Cannot get dispute ID") } let details = try disputes.details(for: id).wait() - XCTAssertEqual(details.id, id) } - func testAcceptEndpoint()throws { + func acceptEndpoint()throws { let disputes = try self.app.make(CustomerDisputes.self) guard let id = self.id else { throw Abort(.internalServerError, reason: "Cannot get dispute ID") @@ -63,7 +73,7 @@ final class CustomerDisputesTests: XCTestCase { XCTAssertEqual(links.first?.href, "https://api.sandbox.paypal.com/v1/customer/disputes/" + id) } - func testSettleEndpoint()throws { + func settleEndpoint()throws { let disputes = try self.app.make(CustomerDisputes.self) guard let id = self.id else { throw Abort(.internalServerError, reason: "Cannot get dispute ID") @@ -75,7 +85,7 @@ final class CustomerDisputesTests: XCTestCase { XCTAssertEqual(links.first?.href, "https://api.sandbox.paypal.com/v1/customer/disputes/" + id) } - func testAppealEndpoint()throws { + func appealEndpoint()throws { let disputes = try self.app.make(CustomerDisputes.self) guard let id = self.id else { throw Abort(.internalServerError, reason: "Cannot get dispute ID") @@ -101,7 +111,7 @@ final class CustomerDisputesTests: XCTestCase { XCTAssertEqual(links.first?.href, "https://api.sandbox.paypal.com/v1/customer/disputes/" + id) } - func testEscalateEndpoint()throws { + func escalateEndpoint()throws { let disputes = try self.app.make(CustomerDisputes.self) guard let id = self.id else { throw Abort(.internalServerError, reason: "Cannot get dispute ID") @@ -113,7 +123,7 @@ final class CustomerDisputesTests: XCTestCase { XCTAssertEqual(links.first?.href, "https://api.sandbox.paypal.com/v1/customer/disputes/" + id) } - func testOfferEndpoint()throws { + func offerEndpoint()throws { let disputes = try self.app.make(CustomerDisputes.self) guard let id = self.id else { throw Abort(.internalServerError, reason: "Cannot get dispute ID") @@ -132,7 +142,7 @@ final class CustomerDisputesTests: XCTestCase { XCTAssertEqual(links.first?.href, "https://api.sandbox.paypal.com/v1/customer/disputes/" + id) } - func testEvidenceEndpoint()throws { + func evidenceEndpoint()throws { let disputes = try self.app.make(CustomerDisputes.self) guard let id = self.id else { throw Abort(.internalServerError, reason: "Cannot get dispute ID") @@ -157,7 +167,7 @@ final class CustomerDisputesTests: XCTestCase { XCTAssertEqual(links.first?.href, "https://api.sandbox.paypal.com/v1/customer/disputes/" + id) } - func testUpdateStatusEndpoint()throws { + func updateStatusEndpoint()throws { let disputes = try self.app.make(CustomerDisputes.self) guard let id = self.id else { throw Abort(.internalServerError, reason: "Cannot get dispute ID") @@ -169,7 +179,7 @@ final class CustomerDisputesTests: XCTestCase { XCTAssertEqual(links.first?.href, "https://api.sandbox.paypal.com/v1/customer/disputes/" + id) } - func testMessageEndpoint()throws { + func messageEndpoint()throws { let disputes = try self.app.make(CustomerDisputes.self) guard let id = self.id else { throw Abort(.internalServerError, reason: "Cannot get dispute ID") @@ -209,17 +219,8 @@ final class CustomerDisputesTests: XCTestCase { return File(data: data, filename: name) } - static var allTests: [(String, (CustomerDisputesTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (CustomerDisputesTests) -> ()throws -> ())] = [ ("testServiceExists", testServiceExists), - ("testListEndpoint", testListEndpoint), - ("testDetailsEndpoint", testDetailsEndpoint), - ("testAcceptEndpoint", testAcceptEndpoint), - ("testSettleEndpoint", testSettleEndpoint), - ("testAppealEndpoint", testAppealEndpoint), - ("testEscalateEndpoint", testEscalateEndpoint), - ("testOfferEndpoint", testOfferEndpoint), - ("testEvidenceEndpoint", testEvidenceEndpoint), - ("testUpdateStatusEndpoint", testUpdateStatusEndpoint), - ("testMessageEndpoint", testMessageEndpoint) + ("testEndpoints", testEndpoints) ] } diff --git a/Tests/ControllerTests/IdentityTests.swift b/Tests/ControllerTests/IdentityTests.swift index 9833344a..01f310bc 100644 --- a/Tests/ControllerTests/IdentityTests.swift +++ b/Tests/ControllerTests/IdentityTests.swift @@ -2,11 +2,12 @@ import XCTest import Vapor @testable import PayPal -final class IdentityTests: XCTestCase { +// MARK: - Passing ✅ +public final class IdentityTests: XCTestCase { var app: Application! - override func setUp() { + override public func setUp() { super.setUp() setPaypalVars() @@ -27,7 +28,7 @@ final class IdentityTests: XCTestCase { XCTAssertNotNil(info.id) } - static var allTests: [(String, (IdentityTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (IdentityTests) -> ()throws -> ())] = [ ("testServiceExists", testServiceExists), ("testInfoEndpoint", testInfoEndpoint) ] diff --git a/Tests/ControllerTests/InvoicesTests.swift b/Tests/ControllerTests/InvoicesTests.swift index f8b14ac6..33923f29 100644 --- a/Tests/ControllerTests/InvoicesTests.swift +++ b/Tests/ControllerTests/InvoicesTests.swift @@ -3,12 +3,12 @@ import Vapor import SwiftGD @testable import PayPal -final class InvoicesTests: XCTestCase { +public final class InvoicesTests: XCTestCase { var app: Application! var id: String? - override func setUp() { + override public func setUp() { super.setUp() setPaypalVars() @@ -33,14 +33,14 @@ final class InvoicesTests: XCTestCase { let invoice = try Invoice( number: nil, merchant: MerchantInfo( - email: "dispute@skelpo.com", - business: "Qutheory LLC.", - firstName: "Tanner", - lastName: "Nelson", + email: .init("dispute@skelpo.com"), + business: .init("Qutheory LLC."), + firstName: .init("Tanner"), + lastName: .init("Nelson"), address: nil, phone: nil, fax: nil, - website: "https://vapor.codes/", + website: .init("https://vapor.codes/"), taxID: nil, info: nil ), @@ -109,14 +109,14 @@ final class InvoicesTests: XCTestCase { let invoice = try Invoice( number: nil, merchant: MerchantInfo( - email: "hello@vapor.codes", - business: "Qutheory LLC.", - firstName: "Tanner", - lastName: "Nelson", + email: .init("hello@vapor.codes"), + business: .init("Qutheory LLC."), + firstName: .init("Tanner"), + lastName: .init("Nelson"), address: nil, phone: nil, fax: nil, - website: "https://vapor.codes/", + website: .init("https://vapor.codes/"), taxID: nil, info: nil ), @@ -145,7 +145,7 @@ final class InvoicesTests: XCTestCase { let updated = try invoices.update(invoice: id, with: invoice).wait() XCTAssertEqual(invoice.date?.date, now) - XCTAssertEqual(invoice.payment?.due, now) + XCTAssertEqual(invoice.payment?.due, TimelessDate(now)) XCTAssertEqual(updated.cc?.last?.email, "dont.ater@example.com") } @@ -296,7 +296,7 @@ final class InvoicesTests: XCTestCase { XCTAssertEqual(empty.invoices?.count, 0) } - static var allTests: [(String, (InvoicesTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (InvoicesTests) -> ()throws -> ())] = [ ("testServiceExists", testServiceExists), ("testCreateEndpoint", testCreateEndpoint), ("testListEndpoint", testListEndpoint), diff --git a/Tests/ControllerTests/ManagedAccountsTests.swift b/Tests/ControllerTests/ManagedAccountsTests.swift index a895f714..73ef1beb 100644 --- a/Tests/ControllerTests/ManagedAccountsTests.swift +++ b/Tests/ControllerTests/ManagedAccountsTests.swift @@ -2,12 +2,12 @@ import XCTest import Vapor @testable import PayPal -final class ManagedAccountsTests: XCTestCase { +public final class ManagedAccountsTests: XCTestCase { var app: Application! var id: String? - override func setUp() { + override public func setUp() { super.setUp() setPaypalVars() @@ -28,11 +28,7 @@ final class ManagedAccountsTests: XCTestCase { _ = try app.make(ManagedAccounts.self) } - func testCreateEndpoint()throws { - guard let id = self.id else { - throw Abort(.internalServerError, reason: "ID is nil") - } - + func testCreateEndpoint()throws { let paymentPref = PaymentReceivingPreferences( blockUnconfirmedUSAddress: true, blockNonUS: false, @@ -46,7 +42,7 @@ final class ManagedAccountsTests: XCTestCase { ) let business = try Business( type: .individual, - subType: .unselected, + subType: .assoIncorporated, government: GovernmentBody(name: ""), establishment: Establishment(state: .ks, country: .unitedStates), names: [], @@ -56,8 +52,8 @@ final class ManagedAccountsTests: XCTestCase { subCategory: .init("5972"), merchantCategory: .init("4653"), establishedDate: TimelessDate(date: "1882-05-13"), - registrationDate: TimelessDate(date: "1975-04-22"), - disputeEmail: EmailAddress(email: "disputable@exmaple.com"), + registrationDate: TimelessDate(date: "2000-04-22"), + disputeEmail: .init("disputable@exmaple.com"), sales: .init( price: MoneyRange(50...60, currency: .usd), volume: MoneyRange(50...60, currency: .usd), @@ -78,8 +74,7 @@ final class ManagedAccountsTests: XCTestCase { let owner = try BusinessOwner( email: "business@example.com", name: Name( - prefix: .init("Sir"), given: .init("Walter"), surname: .init("Scott"), middle: nil, suffix: .init("Bart."), - full: .init("Sir Walter Scott") + prefix: .init("Sir"), given: .init("Walter"), surname: .init("Scott"), middle: nil, suffix: .init("Bart."), full: nil ), relationships: [], country: .unitedKingdom, @@ -106,7 +101,7 @@ final class ManagedAccountsTests: XCTestCase { partnerTaxReporting: false, signupOptions: nil, errors: nil, - financialInstruments: FinancialInstruments(instruments: [FinancialInstrument(accountType: .checking)]) + financialInstruments: nil ) let accounts = try self.app.make(ManagedAccounts.self) @@ -157,7 +152,7 @@ final class ManagedAccountsTests: XCTestCase { merchantCategory: .init("4653"), establishedDate: TimelessDate(date: "1882-05-13"), registrationDate: TimelessDate(date: "1975-04-22"), - disputeEmail: EmailAddress(email: "disputable@exmaple.com"), + disputeEmail: .init("disputable@exmaple.com"), sales: .init( price: MoneyRange(50...60, currency: .usd), volume: MoneyRange(50...60, currency: .usd), @@ -248,7 +243,7 @@ final class ManagedAccountsTests: XCTestCase { XCTAssertGreaterThan(instruments.instruments?.count ?? 0, 0) } - static var allTests: [(String, (ManagedAccountsTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ManagedAccountsTests) -> ()throws -> ())] = [ ("testServiceExists", testServiceExists), ("testCreateEndpoint", testCreateEndpoint), ("testPatchEndpoint", testPatchEndpoint), diff --git a/Tests/ControllerTests/OrdersTests.swift b/Tests/ControllerTests/OrdersTests.swift index 084eddd7..e80f754f 100644 --- a/Tests/ControllerTests/OrdersTests.swift +++ b/Tests/ControllerTests/OrdersTests.swift @@ -2,12 +2,12 @@ import XCTest import Vapor @testable import PayPal -final class OrdersTests: XCTestCase { +public final class OrdersTests: XCTestCase { var app: Application! var id: String? - override func setUp() { + override public func setUp() { super.setUp() setPaypalVars() @@ -140,7 +140,7 @@ final class OrdersTests: XCTestCase { XCTAssertEqual(order.id, id) } - static var allTests: [(String, (OrdersTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OrdersTests) -> ()throws -> ())] = [ ("testServiceExists", testServiceExists), ("testCreateEndpoints", testCreateEndpoints), ("testCancelEndpoints", testCancelEndpoints), diff --git a/Tests/ControllerTests/PaymentsTests.swift b/Tests/ControllerTests/PaymentsTests.swift index 4850d9c4..b685c5ef 100644 --- a/Tests/ControllerTests/PaymentsTests.swift +++ b/Tests/ControllerTests/PaymentsTests.swift @@ -2,13 +2,13 @@ import XCTest import Vapor @testable import PayPal -final class PaymentsTests: XCTestCase { +public final class PaymentsTests: XCTestCase { var id: String! var app: Application! var context: PaymentTestsContext! - override func setUp() { + override public func setUp() { super.setUp() setPaypalVars() @@ -259,7 +259,7 @@ final class PaymentsTests: XCTestCase { XCTAssertEqual(refund.id, id) } - static var allTests: [(String, (PaymentsTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentsTests) -> ()throws -> ())] = [ ("testServiceExists", testServiceExists), ("testCreateEndpoint", testCreateEndpoint), ("testListEndpoint", testListEndpoint), diff --git a/Tests/ControllerTests/TemplatesTests.swift b/Tests/ControllerTests/TemplatesTests.swift index 331c4f4e..7db9c459 100644 --- a/Tests/ControllerTests/TemplatesTests.swift +++ b/Tests/ControllerTests/TemplatesTests.swift @@ -2,12 +2,12 @@ import XCTest import Vapor @testable import PayPal -final class TemplatesTests: XCTestCase { +public final class TemplatesTests: XCTestCase { var app: Application! var id: String? - override func setUp() { + override public func setUp() { super.setUp() setPaypalVars() @@ -33,14 +33,14 @@ final class TemplatesTests: XCTestCase { default: true, data: .init( merchant: MerchantInfo( - email: "hello@vapor.codes", - business: "Qutheory LLC.", - firstName: "Tanner", - lastName: "Nelson", + email: .init("hello@vapor.codes"), + business: .init("Qutheory LLC."), + firstName: .init("Tanner"), + lastName: .init("Nelson"), address: nil, phone: nil, fax: nil, - website: "https://vapor.codes/", + website: .init("https://vapor.codes/"), taxID: nil, info: nil ), @@ -96,14 +96,14 @@ final class TemplatesTests: XCTestCase { default: true, data: .init( merchant: MerchantInfo( - email: "hello@vapor.codes", - business: "Qutheory LLC.", - firstName: "Tanner", - lastName: "Nelson", + email: .init("hello@vapor.codes"), + business: .init("Qutheory LLC."), + firstName: .init("Tanner"), + lastName: .init("Nelson"), address: nil, phone: nil, fax: nil, - website: "https://vapor.codes/", + website: .init("https://vapor.codes/"), taxID: nil, info: nil ), @@ -161,7 +161,7 @@ final class TemplatesTests: XCTestCase { XCTAssertEqual(details.id, id) } - static var allTests: [(String, (TemplatesTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (TemplatesTests) -> ()throws -> ())] = [ ("testServiceExists", testServiceExists), ("testCreateEndpoint", testCreateEndpoint), ("testListEndpoint", testListEndpoint), diff --git a/Tests/ModelTests/AccountErrorDetailTests.swift b/Tests/ModelTests/AccountTests/AccountErrorDetailTests.swift similarity index 92% rename from Tests/ModelTests/AccountErrorDetailTests.swift rename to Tests/ModelTests/AccountTests/AccountErrorDetailTests.swift index 2fa51be2..c541be7a 100644 --- a/Tests/ModelTests/AccountErrorDetailTests.swift +++ b/Tests/ModelTests/AccountTests/AccountErrorDetailTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class AccountErrorDetailTests: XCTestCase { +public final class AccountErrorDetailTests: XCTestCase { func testInit()throws { let details = AccountError.Details(issue: "1028", field: "property", value: "value", description: "Oops") @@ -44,7 +44,7 @@ final class AccountErrorDetailTests: XCTestCase { try XCTAssertEqual(details, decoder.decode(AccountError.Details.self, from: json)) } - static var allTests: [(String, (AccountErrorDetailTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AccountErrorDetailTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/AccountErrorTests.swift b/Tests/ModelTests/AccountTests/AccountErrorTests.swift similarity index 93% rename from Tests/ModelTests/AccountErrorTests.swift rename to Tests/ModelTests/AccountTests/AccountErrorTests.swift index 7b7e3958..d900b32f 100644 --- a/Tests/ModelTests/AccountErrorTests.swift +++ b/Tests/ModelTests/AccountTests/AccountErrorTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class AccountErrorTests: XCTestCase { +public final class AccountErrorTests: XCTestCase { func testInit()throws { let error = AccountError(name: "invalidTimezone", message: "Chosen timezone does not appear to exist", debug: "5698", details: []) @@ -41,7 +41,7 @@ final class AccountErrorTests: XCTestCase { XCTAssertEqual(error.information, "https://example.com/errors/5698") } - static var allTests: [(String, (AccountErrorTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AccountErrorTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/AccountOwnerRelationshipTests.swift b/Tests/ModelTests/AccountTests/AccountOwnerRelationshipTests.swift similarity index 94% rename from Tests/ModelTests/AccountOwnerRelationshipTests.swift rename to Tests/ModelTests/AccountTests/AccountOwnerRelationshipTests.swift index 430d81c0..20353878 100644 --- a/Tests/ModelTests/AccountOwnerRelationshipTests.swift +++ b/Tests/ModelTests/AccountTests/AccountOwnerRelationshipTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class AccountOwnerRelationshipTests: XCTestCase { +public final class AccountOwnerRelationshipTests: XCTestCase { func testInit()throws { let relationship = try AccountOwnerRelationship( name: Name(prefix: nil, given: .init("Abe"), surname: .init("Lincon"), middle: nil, suffix: nil, full: .init("Abe Lincon")), @@ -68,7 +68,7 @@ final class AccountOwnerRelationshipTests: XCTestCase { try XCTAssertEqual(relationship, decoder.decode(AccountOwnerRelationship.self, from: json)) } - static var allTests: [(String, (AccountOwnerRelationshipTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AccountOwnerRelationshipTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/AccountPermissionEnumTests.swift b/Tests/ModelTests/AccountTests/AccountPermissionEnumTests.swift similarity index 95% rename from Tests/ModelTests/AccountPermissionEnumTests.swift rename to Tests/ModelTests/AccountTests/AccountPermissionEnumTests.swift index f83b762a..d7134a37 100644 --- a/Tests/ModelTests/AccountPermissionEnumTests.swift +++ b/Tests/ModelTests/AccountTests/AccountPermissionEnumTests.swift @@ -3,7 +3,7 @@ import XCTest private typealias Permission = AccountPermission.Permission -final class AccountPermissionEnumTests: XCTestCase { +public final class AccountPermissionEnumTests: XCTestCase { private struct Account: Codable { let permission: Permission } @@ -60,7 +60,7 @@ final class AccountPermissionEnumTests: XCTestCase { try XCTAssertEqual(decoder.decode(Account.self, from: extendedProProcessing).permission, .extendedProProcessing) } - static var allTests: [(String, (AccountPermissionEnumTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AccountPermissionEnumTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/AccountPermissionTests.swift b/Tests/ModelTests/AccountTests/AccountPermissionTests.swift similarity index 90% rename from Tests/ModelTests/AccountPermissionTests.swift rename to Tests/ModelTests/AccountTests/AccountPermissionTests.swift index b6b487be..c4b69071 100644 --- a/Tests/ModelTests/AccountPermissionTests.swift +++ b/Tests/ModelTests/AccountTests/AccountPermissionTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class AccountPermissionTests: XCTestCase { +public final class AccountPermissionTests: XCTestCase { func testInit()throws { let permission = AccountPermission(thirdParty: "FDF4D16C-11C0-4792-A956-6A3A9D8B49C2", permissions: [.directPayment]) @@ -32,7 +32,7 @@ final class AccountPermissionTests: XCTestCase { try XCTAssertEqual(permission, decoder.decode(AccountPermission.self, from: json)) } - static var allTests: [(String, (AccountPermissionTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AccountPermissionTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/AccountRelationTests.swift b/Tests/ModelTests/AccountTests/AccountRelationTests.swift similarity index 89% rename from Tests/ModelTests/AccountRelationTests.swift rename to Tests/ModelTests/AccountTests/AccountRelationTests.swift index 2752db3f..c02c3a0d 100644 --- a/Tests/ModelTests/AccountRelationTests.swift +++ b/Tests/ModelTests/AccountTests/AccountRelationTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class AccountRelationTests: XCTestCase { +public final class AccountRelationTests: XCTestCase { func testInit()throws { let relation = AccountRelation(type: .partner, payer: "0F1B22C3-C58C-4CC8-AF83-85659455F85F") @@ -30,7 +30,7 @@ final class AccountRelationTests: XCTestCase { try XCTAssertEqual(relation, decoder.decode(AccountRelation.self, from: json)) } - static var allTests: [(String, (AccountRelationTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AccountRelationTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/AccountRelationTypeTests.swift b/Tests/ModelTests/AccountTests/AccountRelationTypeTests.swift similarity index 91% rename from Tests/ModelTests/AccountRelationTypeTests.swift rename to Tests/ModelTests/AccountTests/AccountRelationTypeTests.swift index 5a0fba8d..d7030a9c 100644 --- a/Tests/ModelTests/AccountRelationTypeTests.swift +++ b/Tests/ModelTests/AccountTests/AccountRelationTypeTests.swift @@ -3,7 +3,7 @@ import XCTest typealias RelationType = AccountRelation.RelationType -final class AccountRelationTypeTests: XCTestCase { +public final class AccountRelationTypeTests: XCTestCase { struct Relation: Codable { let type: RelationType } @@ -44,7 +44,7 @@ final class AccountRelationTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Relation.self, from: same).type, .same) } - static var allTests: [(String, (AccountRelationTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AccountRelationTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/AccountStatusTests.swift b/Tests/ModelTests/AccountTests/AccountStatusTests.swift similarity index 91% rename from Tests/ModelTests/AccountStatusTests.swift rename to Tests/ModelTests/AccountTests/AccountStatusTests.swift index b9d08680..69c7371b 100644 --- a/Tests/ModelTests/AccountStatusTests.swift +++ b/Tests/ModelTests/AccountTests/AccountStatusTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class AccountStatusTests: XCTestCase { +public final class AccountStatusTests: XCTestCase { struct Account: Codable { let status: AccountStatus } @@ -43,7 +43,7 @@ final class AccountStatusTests: XCTestCase { try XCTAssertEqual(decoder.decode(Account.self, from: pua).status, .pua) } - static var allTests: [(String, (AccountStatusTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AccountStatusTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/AccountTypeTests.swift b/Tests/ModelTests/AccountTests/AccountTypeTests.swift similarity index 92% rename from Tests/ModelTests/AccountTypeTests.swift rename to Tests/ModelTests/AccountTests/AccountTypeTests.swift index 13a172f2..6d029514 100644 --- a/Tests/ModelTests/AccountTypeTests.swift +++ b/Tests/ModelTests/AccountTests/AccountTypeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class AccountTypeTests: XCTestCase { +public final class AccountTypeTests: XCTestCase { struct Account: Codable { let type: UserInfo.AccountType } @@ -43,7 +43,7 @@ final class AccountTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Account.self, from: personal).type, .personal) } - static var allTests: [(String, (AccountTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AccountTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/ActivityResponseTests.swift b/Tests/ModelTests/ActivityTests/ActivityResponseTests.swift similarity index 86% rename from Tests/ModelTests/ActivityResponseTests.swift rename to Tests/ModelTests/ActivityTests/ActivityResponseTests.swift index 4acf1145..521ba52c 100644 --- a/Tests/ModelTests/ActivityResponseTests.swift +++ b/Tests/ModelTests/ActivityTests/ActivityResponseTests.swift @@ -2,18 +2,21 @@ import XCTest @testable import PayPal @available(OSX 10.12, *) -final class ActivityResponseTests: XCTestCase { +public final class ActivityResponseTests: XCTestCase { let response = Activity.Response(items: [ Activity( id: "94C67654-A41B-4421-B0D0-81E6CD587CDB", - timeCreated: Date(iso8601: "2018-07-12T14:14:56Z")!, + timeCreated: Date(iso8601: "2018-07-12T14:14:56.000Z")!, type: .payment, subtype: nil, status: .pending, counterparty: CounterParty( email: "54north@exmaple.com", phoneNumber: "314-159-2653", - name: "Jonathan Futher" + firstName: nil, + lastName: nil, + name: "Jonathan Futher", + payment: nil ), fee: nil, gross: CurrencyCodeAmount(currency: .usd, value: 19.45), @@ -31,14 +34,17 @@ final class ActivityResponseTests: XCTestCase { XCTAssertEqual(response.items, [ Activity( id: "94C67654-A41B-4421-B0D0-81E6CD587CDB", - timeCreated: Date(iso8601: "2018-07-12T14:14:56Z")!, + timeCreated: Date(iso8601: "2018-07-12T14:14:56.000Z")!, type: .payment, subtype: nil, status: .pending, counterparty: CounterParty( email: "54north@exmaple.com", phoneNumber: "314-159-2653", - name: "Jonathan Futher" + firstName: nil, + lastName: nil, + name: "Jonathan Futher", + payment: nil ), fee: nil, gross: CurrencyCodeAmount(currency: .usd, value: 19.45), @@ -57,7 +63,7 @@ final class ActivityResponseTests: XCTestCase { let generated = try String(data: encoder.encode(self.response), encoding: .utf8)! let json = - "{\"items\":[{\"status\":\"PENDING\",\"id\":\"94C67654-A41B-4421-B0D0-81E6CD587CDB\",\"time_created\":\"2018-07-12T14:14:56Z\"," + + "{\"items\":[{\"status\":\"PENDING\",\"id\":\"94C67654-A41B-4421-B0D0-81E6CD587CDB\",\"time_created\":\"2018-07-12T14:14:56.000Z\"," + "\"activity_type\":\"PAYMENT\",\"gross\":{\"value\":\"19.45\",\"currency_code\":\"USD\"}," + "\"counterparty\":{\"email\":\"54north@exmaple.com\",\"name\":\"Jonathan Futher\",\"phone_number\":\"314-159-2653\"}," + "\"net\":{\"value\":\"19.45\",\"currency_code\":\"USD\"}}],\"links\":" + @@ -84,7 +90,7 @@ final class ActivityResponseTests: XCTestCase { "items": [ { "id": "94C67654-A41B-4421-B0D0-81E6CD587CDB", - "time_created": "2018-07-12T14:14:56Z", + "time_created": "2018-07-12T14:14:56.000Z", "activity_type": "PAYMENT", "status": "PENDING", "counterparty": { @@ -117,7 +123,7 @@ final class ActivityResponseTests: XCTestCase { XCTAssertEqual(self.response, decoded) } - static var allTests: [(String, (ActivityResponseTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ActivityResponseTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/ActivityTests.swift b/Tests/ModelTests/ActivityTests/ActivityTests.swift similarity index 84% rename from Tests/ModelTests/ActivityTests.swift rename to Tests/ModelTests/ActivityTests/ActivityTests.swift index 12630372..39d371be 100644 --- a/Tests/ModelTests/ActivityTests.swift +++ b/Tests/ModelTests/ActivityTests/ActivityTests.swift @@ -1,17 +1,20 @@ import XCTest @testable import PayPal -final class ActivityTests: XCTestCase { +public final class ActivityTests: XCTestCase { let activity = Activity( id: "94C67654-A41B-4421-B0D0-81E6CD587CDB", - timeCreated: Date(iso8601: "2018-07-12T14:14:56Z")!, + timeCreated: Date(iso8601: "2018-07-12T14:14:56.000Z")!, type: .payment, subtype: nil, status: .pending, counterparty: CounterParty( email: "54north@exmaple.com", phoneNumber: "314-159-2653", - name: "Jonathan Futher" + firstName: nil, + lastName: nil, + name: "Jonathan Futher", + payment: nil ), fee: nil, gross: CurrencyCodeAmount(currency: .usd, value: 19.45), @@ -29,7 +32,7 @@ final class ActivityTests: XCTestCase { let generated = try String(data: encoder.encode(self.activity), encoding: .utf8)! let json = - "{\"status\":\"PENDING\",\"id\":\"94C67654-A41B-4421-B0D0-81E6CD587CDB\",\"time_created\":\"2018-07-12T14:14:56Z\"," + + "{\"status\":\"PENDING\",\"id\":\"94C67654-A41B-4421-B0D0-81E6CD587CDB\",\"time_created\":\"2018-07-12T14:14:56.000Z\"," + "\"activity_type\":\"PAYMENT\",\"gross\":{\"value\":\"19.45\",\"currency_code\":\"USD\"}," + "\"counterparty\":{\"email\":\"54north@exmaple.com\",\"name\":\"Jonathan Futher\",\"phone_number\":\"314-159-2653\"}," + "\"net\":{\"value\":\"19.45\",\"currency_code\":\"USD\"}}" @@ -48,7 +51,7 @@ final class ActivityTests: XCTestCase { let ext = """ { "id": "94C67654-A41B-4421-B0D0-81E6CD587CDB", - "time_created": "2018-07-12T14:14:56Z", + "time_created": "2018-07-12T14:14:56.000Z", "activity_type": "PAYMENT", "status": "PENDING", "counterparty": { @@ -72,7 +75,7 @@ final class ActivityTests: XCTestCase { XCTAssertEqual(self.activity, decoded) } - static var allTests: [(String, (ActivityTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ActivityTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/AddressNormalizationTests.swift b/Tests/ModelTests/AddressTests/AddressNormalizationTests.swift similarity index 92% rename from Tests/ModelTests/AddressNormalizationTests.swift rename to Tests/ModelTests/AddressTests/AddressNormalizationTests.swift index 567a21b0..96908ae9 100644 --- a/Tests/ModelTests/AddressNormalizationTests.swift +++ b/Tests/ModelTests/AddressTests/AddressNormalizationTests.swift @@ -3,7 +3,7 @@ import XCTest typealias Normalization = Address.Normalization -final class AddressNormalizationTests: XCTestCase { +public final class AddressNormalizationTests: XCTestCase { struct Add: Codable { let norm: Normalization } @@ -46,7 +46,7 @@ final class AddressNormalizationTests: XCTestCase { try XCTAssertEqual(decoder.decode(Add.self, from: unnormalized).norm, .unnormalized) } - static var allTests: [(String, (AddressNormalizationTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AddressNormalizationTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/AddressTests.swift b/Tests/ModelTests/AddressTests/AddressTests.swift similarity index 96% rename from Tests/ModelTests/AddressTests.swift rename to Tests/ModelTests/AddressTests/AddressTests.swift index 50a93aa8..43dc2115 100644 --- a/Tests/ModelTests/AddressTests.swift +++ b/Tests/ModelTests/AddressTests/AddressTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class AddressTests: XCTestCase { +public final class AddressTests: XCTestCase { func testInit()throws { let address = Address( recipientName: "Puffin Billy", @@ -113,7 +113,7 @@ final class AddressTests: XCTestCase { ) } - static var allTests: [(String, (AddressTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AddressTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/AdjudicationOutcomeTests.swift b/Tests/ModelTests/AdjudicationOutcomeTests.swift index 15fa5449..2d35f399 100644 --- a/Tests/ModelTests/AdjudicationOutcomeTests.swift +++ b/Tests/ModelTests/AdjudicationOutcomeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class AdjudicationOutcomeTests: XCTestCase { +public final class AdjudicationOutcomeTests: XCTestCase { struct Adjudication: Codable { let outcome: AdjudicationOutcome } @@ -42,7 +42,7 @@ final class AdjudicationOutcomeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Adjudication.self, from: seller).outcome, .seller) } - static var allTests: [(String, (AdjudicationOutcomeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AdjudicationOutcomeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/AgreementStateTests.swift b/Tests/ModelTests/AgreementStateTests.swift index ee310a39..63fe5ea1 100644 --- a/Tests/ModelTests/AgreementStateTests.swift +++ b/Tests/ModelTests/AgreementStateTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class AgreementStateTests: XCTestCase { +public final class AgreementStateTests: XCTestCase { struct Agree: Codable { let state: AgreementState } @@ -45,7 +45,7 @@ final class AgreementStateTests: XCTestCase { try XCTAssertEqual(decoder.decode(Agree.self, from: expired).state, .expired) } - static var allTests: [(String, (AgreementStateTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AgreementStateTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/AppContextShippingTests.swift b/Tests/ModelTests/AppContextTests/AppContextShippingTests.swift similarity index 91% rename from Tests/ModelTests/AppContextShippingTests.swift rename to Tests/ModelTests/AppContextTests/AppContextShippingTests.swift index 807706cf..5a8321e4 100644 --- a/Tests/ModelTests/AppContextShippingTests.swift +++ b/Tests/ModelTests/AppContextTests/AppContextShippingTests.swift @@ -3,7 +3,7 @@ import XCTest typealias AppShipping = AppContext.Shipping -final class AppContextShippingTests: XCTestCase { +public final class AppContextShippingTests: XCTestCase { struct App: Codable { let shipping: AppShipping } @@ -45,7 +45,7 @@ final class AppContextShippingTests: XCTestCase { try XCTAssertEqual(decoder.decode(App.self, from: none).shipping, .none) } - static var allTests: [(String, (AppContextShippingTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AppContextShippingTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/AppContextTests.swift b/Tests/ModelTests/AppContextTests/AppContextTests.swift similarity index 96% rename from Tests/ModelTests/AppContextTests.swift rename to Tests/ModelTests/AppContextTests/AppContextTests.swift index 251c227a..8f979253 100644 --- a/Tests/ModelTests/AppContextTests.swift +++ b/Tests/ModelTests/AppContextTests/AppContextTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class AppContextTests: XCTestCase { +public final class AppContextTests: XCTestCase { func testInit()throws { let context = try AppContext( brand: .init("Example Inc."), @@ -94,7 +94,7 @@ final class AppContextTests: XCTestCase { )) } - static var allTests: [(String, (AppContextTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AppContextTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/AutoBillTests.swift b/Tests/ModelTests/AutoBillTests.swift index 3aaee23a..eb705b31 100644 --- a/Tests/ModelTests/AutoBillTests.swift +++ b/Tests/ModelTests/AutoBillTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class AutoBillTests: XCTestCase { +public final class AutoBillTests: XCTestCase { struct Agreement: Codable { let auto: AutoBill } @@ -42,7 +42,7 @@ final class AutoBillTests: XCTestCase { try XCTAssertEqual(decoder.decode(Agreement.self, from: no).auto, .no) } - static var allTests: [(String, (AutoBillTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AutoBillTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/BalanceResponseTests.swift b/Tests/ModelTests/BalanceResponseTests.swift index 8b71c88d..a4de59ad 100644 --- a/Tests/ModelTests/BalanceResponseTests.swift +++ b/Tests/ModelTests/BalanceResponseTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class BalanceResponseTests: XCTestCase { +public final class BalanceResponseTests: XCTestCase { func testDecoding()throws { let json = """ { @@ -9,13 +9,13 @@ final class BalanceResponseTests: XCTestCase { "available_balances": [ { "currency_code": "USD", - "value": "1000000.00" + "value": "1000000" } ], "pending_balances": [ { "currency_code": "USD", - "value": "5000.00" + "value": "5000" } ] } @@ -27,7 +27,7 @@ final class BalanceResponseTests: XCTestCase { XCTAssertEqual(response.pending, [CurrencyCodeAmount(currency: .usd, value: 5000.00)]) } - static var allTests: [(String, (BalanceResponseTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BalanceResponseTests) -> ()throws -> ())] = [ ("testDecoding", testDecoding) ] } diff --git a/Tests/ModelTests/BillingAgreementTests.swift b/Tests/ModelTests/BillingTests/BillingAgreementTests.swift similarity index 98% rename from Tests/ModelTests/BillingAgreementTests.swift rename to Tests/ModelTests/BillingTests/BillingAgreementTests.swift index 80e9a27f..6f4ce860 100644 --- a/Tests/ModelTests/BillingAgreementTests.swift +++ b/Tests/ModelTests/BillingTests/BillingAgreementTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class BillingAgreementTests: XCTestCase { +public final class BillingAgreementTests: XCTestCase { let now = Date() func testInit()throws { @@ -176,7 +176,7 @@ final class BillingAgreementTests: XCTestCase { try XCTAssertEqual(agreement, decoder.decode(BillingAgreement.self, from: json)) } - static var allTests: [(String, (BillingAgreementTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BillingAgreementTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/BillingInfoTests.swift b/Tests/ModelTests/BillingTests/BillingInfoTests.swift similarity index 98% rename from Tests/ModelTests/BillingInfoTests.swift rename to Tests/ModelTests/BillingTests/BillingInfoTests.swift index 73c28ff8..20b32d84 100644 --- a/Tests/ModelTests/BillingInfoTests.swift +++ b/Tests/ModelTests/BillingTests/BillingInfoTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class BillingInfoTests: XCTestCase { +public final class BillingInfoTests: XCTestCase { func testInit()throws { let info = try BillingInfo( email: .init("ratigan@thirdceller.com"), @@ -230,7 +230,7 @@ final class BillingInfoTests: XCTestCase { try XCTAssertEqual(info.phone, PhoneNumber(country: .init(1), number: .init(4586901518))) } - static var allTests: [(String, (BillingInfoTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BillingInfoTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/BillingPaymentTests.swift b/Tests/ModelTests/BillingTests/BillingPaymentTests.swift similarity index 95% rename from Tests/ModelTests/BillingPaymentTests.swift rename to Tests/ModelTests/BillingTests/BillingPaymentTests.swift index 38c16189..c5704f36 100644 --- a/Tests/ModelTests/BillingPaymentTests.swift +++ b/Tests/ModelTests/BillingTests/BillingPaymentTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class BillingPaymentTests: XCTestCase { +public final class BillingPaymentTests: XCTestCase { func testInit()throws { let payment = try BillingPayment( name: .init("Service Membership"), @@ -92,7 +92,7 @@ final class BillingPaymentTests: XCTestCase { try XCTAssertThrowsError(decoder.decode(BillingPayment.self, from: cyclesError)) } - static var allTests: [(String, (BillingPaymentTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BillingPaymentTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/BillingPlanListTests.swift b/Tests/ModelTests/BillingTests/BillingPlanListTests.swift similarity index 95% rename from Tests/ModelTests/BillingPlanListTests.swift rename to Tests/ModelTests/BillingTests/BillingPlanListTests.swift index d675a259..cded2c21 100644 --- a/Tests/ModelTests/BillingPlanListTests.swift +++ b/Tests/ModelTests/BillingTests/BillingPlanListTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class BillingPlanListTests: XCTestCase { +public final class BillingPlanListTests: XCTestCase { func testInit()throws { let list = try BillingPlan.List(plans: [ BillingPlan( @@ -67,7 +67,7 @@ final class BillingPlanListTests: XCTestCase { ]) let generated = try String(data: encoder.encode(list), encoding: .utf8)! let json = - "{\"plans\":[{\"payment_definitions\":[{\"frequency\":\"MONTH\",\"amount\":{\"currency\":\"USD\",\"value\":\"10.00\"}," + + "{\"plans\":[{\"payment_definitions\":[{\"frequency\":\"MONTH\",\"amount\":{\"currency\":\"USD\",\"value\":\"10\"}," + "\"frequency_interval\":\"1\",\"cycles\":\"0\",\"name\":\"Water Charge\",\"type\":\"REGULAR\"}],\"name\":\"Monthly Water\"," + "\"type\":\"INFINITE\",\"description\":\"Your water payment\"}],\"total_items\":\"1\"}" @@ -94,7 +94,7 @@ final class BillingPlanListTests: XCTestCase { { "cycles": "0", "amount": { - "value": "10.00", + "value": "10", "currency": "USD" }, "frequency_interval": "1", @@ -135,7 +135,7 @@ final class BillingPlanListTests: XCTestCase { )) } - static var allTests: [(String, (BillingPlanListTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BillingPlanListTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/BillingPlanStateTests.swift b/Tests/ModelTests/BillingTests/BillingPlanStateTests.swift similarity index 91% rename from Tests/ModelTests/BillingPlanStateTests.swift rename to Tests/ModelTests/BillingTests/BillingPlanStateTests.swift index e3db247c..d7d8e916 100644 --- a/Tests/ModelTests/BillingPlanStateTests.swift +++ b/Tests/ModelTests/BillingTests/BillingPlanStateTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class BillingPlanStateTests: XCTestCase { +public final class BillingPlanStateTests: XCTestCase { struct Test: Codable { let state: BillingPlan.State } @@ -44,7 +44,7 @@ final class BillingPlanStateTests: XCTestCase { try XCTAssertEqual(decoder.decode(Test.self, from: deleted).state, .deleted) } - static var allTests: [(String, (BillingPlanStateTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BillingPlanStateTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/BillingPlanTests.swift b/Tests/ModelTests/BillingTests/BillingPlanTests.swift similarity index 93% rename from Tests/ModelTests/BillingPlanTests.swift rename to Tests/ModelTests/BillingTests/BillingPlanTests.swift index 886e4907..68a35f57 100644 --- a/Tests/ModelTests/BillingPlanTests.swift +++ b/Tests/ModelTests/BillingTests/BillingPlanTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class BillingPlanTests: XCTestCase { +public final class BillingPlanTests: XCTestCase { func testInit()throws { let plan = try BillingPlan( name: .init("Monthly Water"), @@ -95,9 +95,9 @@ final class BillingPlanTests: XCTestCase { ) let generated = try String(data: encoder.encode(plan), encoding: .utf8)! let json = - "{\"payment_definitions\":[{\"frequency\":\"MONTH\",\"amount\":{\"currency\":\"USD\",\"value\":\"10.00\"},\"frequency_interval\":\"1\"," + - "\"cycles\":\"0\",\"name\":\"Water Charge\",\"type\":\"REGULAR\"}],\"name\":\"Monthly Water\",\"type\":\"INFINITE\"," + - "\"description\":\"Your water payment\"}" + "{\"payment_definitions\":[{\"frequency\":\"MONTH\",\"amount\":{\"currency\":\"USD\",\"value\":\"10\"}," + + "\"frequency_interval\":\"1\",\"cycles\":\"0\",\"name\":\"Water Charge\",\"type\":\"REGULAR\"}]," + + "\"name\":\"Monthly Water\",\"type\":\"INFINITE\",\"description\":\"Your water payment\"}" var index = 0 for (jsonChar, genChar) in zip(json, generated) { @@ -158,7 +158,7 @@ final class BillingPlanTests: XCTestCase { ) } - static var allTests: [(String, (BillingPlanTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BillingPlanTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValueValidation", testValueValidation), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/BillingPlanTypeTests.swift b/Tests/ModelTests/BillingTests/BillingPlanTypeTests.swift similarity index 91% rename from Tests/ModelTests/BillingPlanTypeTests.swift rename to Tests/ModelTests/BillingTests/BillingPlanTypeTests.swift index d605b6cb..a6b2e830 100644 --- a/Tests/ModelTests/BillingPlanTypeTests.swift +++ b/Tests/ModelTests/BillingTests/BillingPlanTypeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class BillingPlanTypeTests: XCTestCase { +public final class BillingPlanTypeTests: XCTestCase { struct Plan: Codable { let type: BillingPlan.PlanType } @@ -42,7 +42,7 @@ final class BillingPlanTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Plan.self, from: infinate).type, .infinite) } - static var allTests: [(String, (BillingPlanTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BillingPlanTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/BusinessNameTest.swift b/Tests/ModelTests/BusinessTests/BusinessNameTest.swift similarity index 92% rename from Tests/ModelTests/BusinessNameTest.swift rename to Tests/ModelTests/BusinessTests/BusinessNameTest.swift index 20a322e6..1a61e683 100644 --- a/Tests/ModelTests/BusinessNameTest.swift +++ b/Tests/ModelTests/BusinessTests/BusinessNameTest.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class BusinessNameTests: XCTestCase { +public final class BusinessNameTests: XCTestCase { func testInit()throws { let name = try Business.Name(type: .legal, name: .init("Stuff and Nonsense Inc.")) @@ -42,7 +42,7 @@ final class BusinessNameTests: XCTestCase { try XCTAssertEqual(name, decoder.decode(Business.Name.self, from: json)) } - static var allTests: [(String, (BusinessNameTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BusinessNameTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValueValidation", testValueValidation), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/BusinessNameTypeTests.swift b/Tests/ModelTests/BusinessTests/BusinessNameTypeTests.swift similarity index 92% rename from Tests/ModelTests/BusinessNameTypeTests.swift rename to Tests/ModelTests/BusinessTests/BusinessNameTypeTests.swift index dfa08520..c746fac7 100644 --- a/Tests/ModelTests/BusinessNameTypeTests.swift +++ b/Tests/ModelTests/BusinessTests/BusinessNameTypeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class BusinessNameTypeTests: XCTestCase { +public final class BusinessNameTypeTests: XCTestCase { struct BusiName: Codable { let type: Business.Name.NameType } @@ -43,7 +43,7 @@ final class BusinessNameTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(BusiName.self, from: stockTrading).type, .stockTrading) } - static var allTests: [(String, (BusinessNameTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BusinessNameTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/BusinessOwnerAddress.swift b/Tests/ModelTests/BusinessTests/BusinessOwnerAddress.swift similarity index 97% rename from Tests/ModelTests/BusinessOwnerAddress.swift rename to Tests/ModelTests/BusinessTests/BusinessOwnerAddress.swift index 9ac089f8..dd177dea 100644 --- a/Tests/ModelTests/BusinessOwnerAddress.swift +++ b/Tests/ModelTests/BusinessTests/BusinessOwnerAddress.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class BusinessOwnerAddressTests: XCTestCase { +public final class BusinessOwnerAddressTests: XCTestCase { func testInit()throws { let address = try BusinessOwner.Address( type: .home, @@ -158,7 +158,7 @@ final class BusinessOwnerAddressTests: XCTestCase { try XCTAssertThrowsError(decoder.decode(BusinessOwner.Address.self, from: state)) } - static var allTests: [(String, (BusinessOwnerAddressTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BusinessOwnerAddressTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValueValidation", testValueValidation), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/BusinessOwnerAddressTypeTests.swift b/Tests/ModelTests/BusinessTests/BusinessOwnerAddressTypeTests.swift similarity index 92% rename from Tests/ModelTests/BusinessOwnerAddressTypeTests.swift rename to Tests/ModelTests/BusinessTests/BusinessOwnerAddressTypeTests.swift index 08f4e228..b0bb5f3e 100644 --- a/Tests/ModelTests/BusinessOwnerAddressTypeTests.swift +++ b/Tests/ModelTests/BusinessTests/BusinessOwnerAddressTypeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class BusinessOwnerAddressTypeTests: XCTestCase { +public final class BusinessOwnerAddressTypeTests: XCTestCase { struct BOA: Codable { let type: BusinessOwner.Address.AddressType } @@ -45,7 +45,7 @@ final class BusinessOwnerAddressTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(BOA.self, from: home).type, .home) } - static var allTests: [(String, (BusinessOwnerAddressTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BusinessOwnerAddressTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/BusinessOwnerIDTests.swift b/Tests/ModelTests/BusinessTests/BusinessOwnerIDTests.swift similarity index 95% rename from Tests/ModelTests/BusinessOwnerIDTests.swift rename to Tests/ModelTests/BusinessTests/BusinessOwnerIDTests.swift index b7c2b9f7..308209d0 100644 --- a/Tests/ModelTests/BusinessOwnerIDTests.swift +++ b/Tests/ModelTests/BusinessTests/BusinessOwnerIDTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class IdentificationTests: XCTestCase { +public final class IdentificationTests: XCTestCase { func testInit()throws { let id = Identification( type: .driversLicense, @@ -92,7 +92,7 @@ final class IdentificationTests: XCTestCase { try XCTAssertThrowsError(decoder.decode(Identification.self, from: country)) } - static var allTests: [(String, (IdentificationTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (IdentificationTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/BusinessOwnerIDType.swift b/Tests/ModelTests/BusinessTests/BusinessOwnerIDType.swift similarity index 95% rename from Tests/ModelTests/BusinessOwnerIDType.swift rename to Tests/ModelTests/BusinessTests/BusinessOwnerIDType.swift index 5470105c..bccc582d 100644 --- a/Tests/ModelTests/BusinessOwnerIDType.swift +++ b/Tests/ModelTests/BusinessTests/BusinessOwnerIDType.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class BusinessOwnerIDTypeTests: XCTestCase { +public final class BusinessOwnerIDTypeTests: XCTestCase { struct ID: Codable { let type: Identification.IDType } @@ -61,7 +61,7 @@ final class BusinessOwnerIDTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(ID.self, from: valueAddedTaxID).type, .valueAddedTaxID) } - static var allTests: [(String, (BusinessOwnerIDTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BusinessOwnerIDTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/BusinessOwnerTests.swift b/Tests/ModelTests/BusinessTests/BusinessOwnerTests.swift similarity index 96% rename from Tests/ModelTests/BusinessOwnerTests.swift rename to Tests/ModelTests/BusinessTests/BusinessOwnerTests.swift index 5c87445e..eab32a94 100644 --- a/Tests/ModelTests/BusinessOwnerTests.swift +++ b/Tests/ModelTests/BusinessTests/BusinessOwnerTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class BusinessOwnerTests: XCTestCase { +public final class BusinessOwnerTests: XCTestCase { let (date, dateStr): (Date, String) = { let now = Date() let str = TimelessDate.formatter.string(from: now) @@ -29,7 +29,7 @@ final class BusinessOwnerTests: XCTestCase { XCTAssertEqual(owner.relationships, []) XCTAssertEqual(owner.country, .unitedKingdom) XCTAssertEqual(owner.addresses, []) - XCTAssertEqual(owner.birthdate, self.date) + XCTAssertEqual(owner.birthdate, TimelessDate(self.date)) XCTAssertEqual(owner.language, .en_GB) XCTAssertEqual(owner.phones, []) XCTAssertEqual(owner.ids, []) @@ -166,7 +166,7 @@ final class BusinessOwnerTests: XCTestCase { try XCTAssertThrowsError(decoder.decode(BusinessOwner.self, from: birthdate)) } - static var allTests: [(String, (BusinessOwnerTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BusinessOwnerTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValueValidation", testValueValidation), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/BusinessTests/BusinessSalesTests.swift b/Tests/ModelTests/BusinessTests/BusinessSalesTests.swift new file mode 100644 index 00000000..d16f5e57 --- /dev/null +++ b/Tests/ModelTests/BusinessTests/BusinessSalesTests.swift @@ -0,0 +1,117 @@ +import XCTest +import Failable +@testable import PayPal + +public final class BusinessSalesTests: XCTestCase { + func testInit()throws { + let sales = try Business.Sales( + price: MoneyRange(50...60, currency: .usd), + volume: MoneyRange(50...60, currency: .usd), + venues: [], + website: .init("https://nameless.io"), + online: PercentRange(0...1) + ) + + XCTAssertEqual(sales.price, MoneyRange(50...60, currency: .usd)) + XCTAssertEqual(sales.volume, MoneyRange(50...60, currency: .usd)) + XCTAssertEqual(sales.venues, []) + XCTAssertEqual(sales.website.value, "https://nameless.io") + try XCTAssertEqual(sales.online, PercentRange(0...1)) + } + + func testValueValidation()throws { + var sales = try Business.Sales( + price: MoneyRange(50...60, currency: .usd), + volume: MoneyRange(50...60, currency: .usd), + venues: [], + website: .init("https://nameless.io"), + online: PercentRange(0...1) + ) + + try XCTAssertThrowsError(sales.website <~ String(repeating: "w", count: 256)) + try sales.website <~ String(repeating: "w", count: 255) + + XCTAssertEqual(sales.website.value, String(repeating: "w", count: 255)) + } + + func testEncoding()throws { + let encoder = JSONEncoder() + let sales = try Business.Sales( + price: MoneyRange(50...60, currency: .usd), + volume: MoneyRange(50...60, currency: .usd), + venues: [], + website: .init("https://nameless.io"), + online: PercentRange(0...1) + ) + + let generated = try String(data: encoder.encode(sales), encoding: .utf8)! + let json = + "{\"sales_venues\":[],\"revenue_from_online_sales\":{\"maximum_percent\":1,\"minimum_percent\":0}," + + "\"average_price\":{\"minimum_amount\":{\"value\":\"50\",\"currency_code\":\"USD\"}," + + "\"maximum_amount\":{\"value\":\"60\",\"currency_code\":\"USD\"}},\"website\":\"https:\\/\\/nameless.io\"," + + "\"average_monthly_volume\":{\"minimum_amount\":{\"value\":\"50\",\"currency_code\":\"USD\"}," + + "\"maximum_amount\":{\"value\":\"60\",\"currency_code\":\"USD\"}}}" + + var index = 0 + for (jsonChar, genChar) in zip(json, generated) { + if jsonChar == genChar { index += 1; continue } + XCTAssertEqual(jsonChar, genChar, "values don't match. Failure starts at index \(index)") + break + } + + XCTAssertEqual(generated, json) + } + + func testDecoding()throws { + let decoder = JSONDecoder() + let json = """ + { + "sales_venues": [], + "revenue_from_online_sales": { + "maximum_percent": 1, + "minimum_percent": 0 + }, + "average_price": { + "minimum_amount": { + "value": "50", + "currency_code": "USD" + }, + "maximum_amount": { + "value": "60", + "currency_code": "USD" + } + }, + "website": "https://nameless.io", + "average_monthly_volume": { + "minimum_amount": { + "value": "50", + "currency_code": "USD" + }, + "maximum_amount": { + "value": "60", + "currency_code": "USD" + } + } + } + """.data(using: .utf8)! + + + let sales = try Business.Sales( + price: MoneyRange(50...60, currency: .usd), + volume: MoneyRange(50...60, currency: .usd), + venues: [], + website: .init("https://nameless.io"), + online: PercentRange(0...1) + ) + try XCTAssertEqual(sales, decoder.decode(Business.Sales.self, from: json)) + } + + public static var allTests: [(String, (BusinessSalesTests) -> ()throws -> ())] = [ + ("testInit", testInit), + ("testValueValidation", testValueValidation), + ("testEncoding", testEncoding), + ("testDecoding", testDecoding) + ] +} + + diff --git a/Tests/ModelTests/BusinessSubTypeTests.swift b/Tests/ModelTests/BusinessTests/BusinessSubTypeTests.swift similarity index 94% rename from Tests/ModelTests/BusinessSubTypeTests.swift rename to Tests/ModelTests/BusinessTests/BusinessSubTypeTests.swift index 04802222..4d4d2e0c 100644 --- a/Tests/ModelTests/BusinessSubTypeTests.swift +++ b/Tests/ModelTests/BusinessTests/BusinessSubTypeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class BusinessSubTypeTests: XCTestCase { +public final class BusinessSubTypeTests: XCTestCase { struct Busi: Codable { let type: Business.SubType } @@ -52,7 +52,7 @@ final class BusinessSubTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Busi.self, from: govtEstdStTr).type, .govtEstdStTr) } - static var allTests: [(String, (BusinessSubTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BusinessSubTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/BusinessTests.swift b/Tests/ModelTests/BusinessTests/BusinessTests.swift similarity index 96% rename from Tests/ModelTests/BusinessTests.swift rename to Tests/ModelTests/BusinessTests/BusinessTests.swift index c3efc77b..87510086 100644 --- a/Tests/ModelTests/BusinessTests.swift +++ b/Tests/ModelTests/BusinessTests/BusinessTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class BusinessTests: XCTestCase { +public final class BusinessTests: XCTestCase { func testInit()throws { let business = try Business( type: .individual, @@ -17,7 +17,7 @@ final class BusinessTests: XCTestCase { merchantCategory: .init("4653"), establishedDate: TimelessDate(date: "1882-05-13"), registrationDate: TimelessDate(date: "1975-04-22"), - disputeEmail: EmailAddress(email: "disputable@exmaple.com"), + disputeEmail: .init("disputable@exmaple.com"), sales: .init( price: MoneyRange(50...60, currency: .usd), volume: MoneyRange(50...60, currency: .usd), @@ -53,7 +53,7 @@ final class BusinessTests: XCTestCase { XCTAssertEqual(business.establishment, Establishment(state: .ks, country: .unitedStates)) XCTAssertEqual(business.establishedDate, TimelessDate(date: "1882-05-13")) XCTAssertEqual(business.registrationDate, TimelessDate(date: "1975-04-22")) - try XCTAssertEqual(business.disputeEmail, EmailAddress(email: .init("disputable@exmaple.com"))) + XCTAssertEqual(business.disputeEmail.value, .init("disputable@exmaple.com")) try XCTAssertEqual(business.sales, Business.Sales.init( price: MoneyRange(50...60, currency: .usd), volume: MoneyRange(50...60, currency: .usd), @@ -211,7 +211,7 @@ final class BusinessTests: XCTestCase { ) } - static var allTests: [(String, (BusinessTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BusinessTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValueValidation", testValueValidation), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/BusinessTypeTests.swift b/Tests/ModelTests/BusinessTests/BusinessTypeTests.swift similarity index 96% rename from Tests/ModelTests/BusinessTypeTests.swift rename to Tests/ModelTests/BusinessTests/BusinessTypeTests.swift index 52ec930b..f74c8434 100644 --- a/Tests/ModelTests/BusinessTypeTests.swift +++ b/Tests/ModelTests/BusinessTests/BusinessTypeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class BusinessTypeTests: XCTestCase { +public final class BusinessTypeTests: XCTestCase { struct Busi: Codable { let type: Business.BusinessType } @@ -63,7 +63,7 @@ final class BusinessTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Busi.self, from: otherCorporate).type, .otherCorporate) } - static var allTests: [(String, (BusinessTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BusinessTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/BuyerTests.swift b/Tests/ModelTests/BuyerTests.swift index ae4f060e..f3a0f081 100644 --- a/Tests/ModelTests/BuyerTests.swift +++ b/Tests/ModelTests/BuyerTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class BuyerTests: XCTestCase { +public final class BuyerTests: XCTestCase { func testInit()throws { let buyer = try Buyer(email: .init("witheringheights@exmaple.com"), name: "Leeli Wingfeather") @@ -46,7 +46,7 @@ final class BuyerTests: XCTestCase { try XCTAssertEqual(Buyer(email: .init("witheringheights@exmaple.com"), name: "Leeli Wingfeather"), decoder.decode(Buyer.self, from: json)) } - static var allTests: [(String, (BuyerTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (BuyerTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/CaptureReasonTests.swift b/Tests/ModelTests/CaptureTests/CaptureReasonTests.swift similarity index 95% rename from Tests/ModelTests/CaptureReasonTests.swift rename to Tests/ModelTests/CaptureTests/CaptureReasonTests.swift index 2d39b7d1..65e426de 100644 --- a/Tests/ModelTests/CaptureReasonTests.swift +++ b/Tests/ModelTests/CaptureTests/CaptureReasonTests.swift @@ -3,7 +3,7 @@ import XCTest typealias CapReas = Capture.Reason -final class CaptureReasonTests: XCTestCase { +public final class CaptureReasonTests: XCTestCase { struct Cap: Codable { let reason: CapReas } @@ -58,7 +58,7 @@ final class CaptureReasonTests: XCTestCase { try XCTAssertEqual(decoder.decode(Cap.self, from: unconfirmedAddress).reason, .unconfirmedAddress) } - static var allTests: [(String, (CaptureReasonTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (CaptureReasonTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/CaptureStatusTests.swift b/Tests/ModelTests/CaptureTests/CaptureStatusTests.swift similarity index 92% rename from Tests/ModelTests/CaptureStatusTests.swift rename to Tests/ModelTests/CaptureTests/CaptureStatusTests.swift index 1f5c1d47..8f67d75f 100644 --- a/Tests/ModelTests/CaptureStatusTests.swift +++ b/Tests/ModelTests/CaptureTests/CaptureStatusTests.swift @@ -3,7 +3,7 @@ import XCTest typealias CapStat = Capture.Status -final class CaptureStatusTests: XCTestCase { +public final class CaptureStatusTests: XCTestCase { struct Cap: Codable { let status: CapStat } @@ -48,7 +48,7 @@ final class CaptureStatusTests: XCTestCase { try XCTAssertEqual(decoder.decode(Cap.self, from: partiallyRefunded).status, .partiallyRefunded) } - static var allTests: [(String, (CaptureStatusTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (CaptureStatusTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/CaptureTests.swift b/Tests/ModelTests/CaptureTests/CaptureTests.swift similarity index 93% rename from Tests/ModelTests/CaptureTests.swift rename to Tests/ModelTests/CaptureTests/CaptureTests.swift index 42df564c..f761cfa2 100644 --- a/Tests/ModelTests/CaptureTests.swift +++ b/Tests/ModelTests/CaptureTests/CaptureTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class CaptureTests: XCTestCase { +public final class CaptureTests: XCTestCase { func testInit()throws { let capture = Capture( amount: DetailedAmount(currency: .usd, total: 10.00, details: nil), @@ -23,7 +23,7 @@ final class CaptureTests: XCTestCase { transaction: CurrencyAmount(currency: .usd, value: 1.00) ) let generated = try String(data: encoder.encode(capture), encoding: .utf8) - let json = "{\"amount\":{\"currency\":\"USD\",\"total\":\"10.00\"},\"transaction_fee\":{\"currency\":\"USD\",\"value\":\"1.00\"}}" + let json = "{\"amount\":{\"currency\":\"USD\",\"total\":\"10.00\"},\"transaction_fee\":{\"currency\":\"USD\",\"value\":\"1\"}}" XCTAssertEqual(generated, json) } @@ -42,7 +42,7 @@ final class CaptureTests: XCTestCase { "currency": "USD" }, "transaction_fee": { - "value": "1.00", + "value": "1", "currency": "USD" } } @@ -57,7 +57,7 @@ final class CaptureTests: XCTestCase { XCTAssertEqual(capture.transaction, CurrencyAmount(currency: .usd, value: 1.00)) } - static var allTests: [(String, (CaptureTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (CaptureTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/CreditCardStateTests.swift b/Tests/ModelTests/CardTests/CreditCardStateTests.swift similarity index 90% rename from Tests/ModelTests/CreditCardStateTests.swift rename to Tests/ModelTests/CardTests/CreditCardStateTests.swift index 47087e7b..34418d99 100644 --- a/Tests/ModelTests/CreditCardStateTests.swift +++ b/Tests/ModelTests/CardTests/CreditCardStateTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias CCStaate = CreditCard.State -final class CreditCardStateTests: XCTestCase { +public final class CreditCardStateTests: XCTestCase { private struct CC: Codable { let state: CCStaate } @@ -44,7 +44,7 @@ final class CreditCardStateTests: XCTestCase { try XCTAssertEqual(decoder.decode(CC.self, from: expired).state, .expired) } - static var allTests: [(String, (CreditCardStateTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (CreditCardStateTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/CreditCardTests.swift b/Tests/ModelTests/CardTests/CreditCardTests.swift similarity index 98% rename from Tests/ModelTests/CreditCardTests.swift rename to Tests/ModelTests/CardTests/CreditCardTests.swift index 998990b2..5beefd88 100644 --- a/Tests/ModelTests/CreditCardTests.swift +++ b/Tests/ModelTests/CardTests/CreditCardTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class CreditCardTests: XCTestCase { +public final class CreditCardTests: XCTestCase { func testInit()throws { let cc = try CreditCard( number: "4953912847443848", @@ -191,7 +191,7 @@ final class CreditCardTests: XCTestCase { try XCTAssertEqual(cc, decoder.decode(CreditCard.self, from: valid)) } - static var allTests: [(String, (CreditCardTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (CreditCardTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/CreditCardTokenTests.swift b/Tests/ModelTests/CardTests/CreditCardTokenTests.swift similarity index 93% rename from Tests/ModelTests/CreditCardTokenTests.swift rename to Tests/ModelTests/CardTests/CreditCardTokenTests.swift index 0970ee8a..1fdbd506 100644 --- a/Tests/ModelTests/CreditCardTokenTests.swift +++ b/Tests/ModelTests/CardTests/CreditCardTokenTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class CreditCardTokenTests: XCTestCase { +public final class CreditCardTokenTests: XCTestCase { func testInit()throws { let token = CreditCard.Token(creditCard: "94935F7A-395B-4CAF-AC29-DD6728C55FE6", payer: "93A20FF4-D73D-4F76-B591-932D4B6CA3E1") @@ -51,7 +51,7 @@ final class CreditCardTokenTests: XCTestCase { XCTAssertEqual(token.expireYear, 2022) } - static var allTests: [(String, (CreditCardTokenTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (CreditCardTokenTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/CreditDebitCodeTests.swift b/Tests/ModelTests/CardTests/CreditDebitCodeTests.swift similarity index 91% rename from Tests/ModelTests/CreditDebitCodeTests.swift rename to Tests/ModelTests/CardTests/CreditDebitCodeTests.swift index 857eba8b..b0114f42 100644 --- a/Tests/ModelTests/CreditDebitCodeTests.swift +++ b/Tests/ModelTests/CardTests/CreditDebitCodeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class CreditDebitCodeTests: XCTestCase { +public final class CreditDebitCodeTests: XCTestCase { struct Card: Codable { let code: CreditDebitCode } @@ -43,7 +43,7 @@ final class CreditDebitCodeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Card.self, from: all).code, .all) } - static var allTests: [(String, (CreditDebitCodeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (CreditDebitCodeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/CarrierTests.swift b/Tests/ModelTests/CarrierTests.swift index 5a23e73a..6c4864a5 100644 --- a/Tests/ModelTests/CarrierTests.swift +++ b/Tests/ModelTests/CarrierTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class CarrierTests: XCTestCase { +public final class CarrierTests: XCTestCase { struct Shippment: Codable { let carrier: Carrier } @@ -175,7 +175,7 @@ final class CarrierTests: XCTestCase { try XCTAssertEqual(decoder.decode(Shippment.self, from: usps).carrier, .usps) } - static var allTests: [(String, (CarrierTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (CarrierTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/ChargeTests.swift b/Tests/ModelTests/ChargeTests/ChargeTests.swift similarity index 91% rename from Tests/ModelTests/ChargeTests.swift rename to Tests/ModelTests/ChargeTests/ChargeTests.swift index 92cc9e66..d5c3b0eb 100644 --- a/Tests/ModelTests/ChargeTests.swift +++ b/Tests/ModelTests/ChargeTests/ChargeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class ChargeTests: XCTestCase { +public final class ChargeTests: XCTestCase { func testInit()throws { let charge = Charge(type: .shipping, amount: CurrencyCodeAmount(currency: .usd, value: 314.15)) @@ -34,7 +34,7 @@ final class ChargeTests: XCTestCase { try XCTAssertEqual(Charge(type: .tax, amount: CurrencyCodeAmount(currency: .eur, value: value)), decoder.decode(Charge.self, from: json)) } - static var allTests: [(String, (ChargeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ChargeTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/ChargeTypeTests.swift b/Tests/ModelTests/ChargeTests/ChargeTypeTests.swift similarity index 91% rename from Tests/ModelTests/ChargeTypeTests.swift rename to Tests/ModelTests/ChargeTests/ChargeTypeTests.swift index 1202075f..d378c985 100644 --- a/Tests/ModelTests/ChargeTypeTests.swift +++ b/Tests/ModelTests/ChargeTests/ChargeTypeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class ChargeTypeTests: XCTestCase { +public final class ChargeTypeTests: XCTestCase { struct Model: Codable { let type: ChargeType } @@ -42,7 +42,7 @@ final class ChargeTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Model.self, from: ship).type, .shipping) } - static var allTests: [(String, (ChargeTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ChargeTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/CounterPartyTests.swift b/Tests/ModelTests/CounterPartyTests.swift index 052bd67a..9b766539 100644 --- a/Tests/ModelTests/CounterPartyTests.swift +++ b/Tests/ModelTests/CounterPartyTests.swift @@ -1,52 +1,69 @@ import XCTest @testable import PayPal -final class CounterPartyTests: XCTestCase { +public final class CounterPartyTests: XCTestCase { func testInit()throws { - let party = CounterParty(email: "54north@exmaple.com", phoneNumber: "314-159-2653", name: "Jonathan Futher") + let party = CounterParty( + email: "54north@exmaple.com", + phoneNumber: "314-159-2653", + firstName: "Jonathan", + lastName: "Further", + name: "Jonathan Futher", + payment: "8KK76419U6099791A" + ) XCTAssertEqual(party.email, "54north@exmaple.com") XCTAssertEqual(party.phoneNumber, "314-159-2653") + XCTAssertEqual(party.firstName, "Jonathan") + XCTAssertEqual(party.lastName, "Further") XCTAssertEqual(party.name, "Jonathan Futher") + XCTAssertEqual(party.payment, "8KK76419U6099791A") } func testEncoding()throws { let encoder = JSONEncoder() - let license = try String(data: encoder.encode( - CounterParty(email: "54north@exmaple.com", phoneNumber: "314-159-2653", name: "Jonathan Futher") - ), encoding: .utf8) + let party = CounterParty( + email: "54north@exmaple.com", + phoneNumber: "314-159-2653", + firstName: "Jonathan", + lastName: "Further", + name: "Jonathan Futher", + payment: "8KK76419U6099791A" + ) + + let license = try String(data: encoder.encode(party), encoding: .utf8) + let json = + "{\"email\":\"54north@exmaple.com\",\"payment_id\":\"8KK76419U6099791A\",\"last_name\":\"Further\"," + + "\"name\":\"Jonathan Futher\",\"phone_number\":\"314-159-2653\",\"first_name\":\"Jonathan\"}" - XCTAssertEqual(license, "{\"email\":\"54north@exmaple.com\",\"name\":\"Jonathan Futher\",\"phone_number\":\"314-159-2653\"}") + XCTAssertEqual(license, json) } func testDecoding()throws { let decoder = JSONDecoder() - let valid = """ + let json = """ { + "first_name": "Jonathan", + "last_name": "Further", "name": "Jonathan Futher", "email": "54north@exmaple.com", - "phone_number": "314-159-2653" - } - """.data(using: .utf8)! - let keyFail = """ - { - "name": "Jonathan Futher", - "email": "54north@exmaple.com", - "phoneNumber": "314-159-2653" + "phone_number": "314-159-2653", + "payment_id": "8KK76419U6099791A" } """.data(using: .utf8)! - try XCTAssertEqual( - CounterParty(email: "54north@exmaple.com", phoneNumber: nil, name: "Jonathan Futher"), - decoder.decode(CounterParty.self, from: keyFail) - ) - try XCTAssertEqual( - CounterParty(email: "54north@exmaple.com", phoneNumber: "314-159-2653", name: "Jonathan Futher"), - decoder.decode(CounterParty.self, from: valid) + let party = CounterParty( + email: "54north@exmaple.com", + phoneNumber: "314-159-2653", + firstName: "Jonathan", + lastName: "Further", + name: "Jonathan Futher", + payment: "8KK76419U6099791A" ) + try XCTAssertEqual(party, decoder.decode(CounterParty.self, from: json)) } - static var allTests: [(String, (CounterPartyTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (CounterPartyTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/CreatedMerchantResponseTests.swift b/Tests/ModelTests/CreatedMerchantResponseTests.swift index 32f8ba97..f9a57ee5 100644 --- a/Tests/ModelTests/CreatedMerchantResponseTests.swift +++ b/Tests/ModelTests/CreatedMerchantResponseTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class CreatedMerchantResponseTests: XCTestCase { +public final class CreatedMerchantResponseTests: XCTestCase { func testDecoding()throws { let json = """ { @@ -23,7 +23,7 @@ final class CreatedMerchantResponseTests: XCTestCase { try XCTAssertEqual(response.authCode, .init("6C0AB2D4-5668-42E6-B943-9FF9956D860B")) } - static var allTests: [(String, (CreatedMerchantResponseTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (CreatedMerchantResponseTests) -> ()throws -> ())] = [ ("testDecoding", testDecoding) ] } diff --git a/Tests/ModelTests/CurrencyTests.swift b/Tests/ModelTests/CurrencyTests.swift index 04ecbb95..12e6720a 100644 --- a/Tests/ModelTests/CurrencyTests.swift +++ b/Tests/ModelTests/CurrencyTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class CurrencyTests: XCTestCase { +public final class CurrencyTests: XCTestCase { struct Model: Codable, Equatable { var cur: Currency } @@ -56,7 +56,7 @@ final class CurrencyTests: XCTestCase { try XCTAssertEqual(decoder.decode(Model.self, from: existing), Model(cur: .zwl)) } - static var allTests: [(String, (CurrencyTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (CurrencyTests) -> ()throws -> ())] = [ ("testFindByCode", testFindByCode), ("testAllCasesSpeed", testAllCasesSpeed), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/CustomerDisputeListTests.swift b/Tests/ModelTests/CustomerTests/CustomerDisputeListTests.swift similarity index 96% rename from Tests/ModelTests/CustomerDisputeListTests.swift rename to Tests/ModelTests/CustomerTests/CustomerDisputeListTests.swift index f5baa8cf..de4c8ea0 100644 --- a/Tests/ModelTests/CustomerDisputeListTests.swift +++ b/Tests/ModelTests/CustomerTests/CustomerDisputeListTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class CustomerDisputeListTests: XCTestCase { +public final class CustomerDisputeListTests: XCTestCase { let date = Date() let due = Date(timeIntervalSinceNow: 60 * 60 * 24) @@ -102,7 +102,7 @@ final class CustomerDisputeListTests: XCTestCase { ) } - static var allTests: [(String, (CustomerDisputeListTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (CustomerDisputeListTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/CustomerDisputeTests.swift b/Tests/ModelTests/CustomerTests/CustomerDisputeTests.swift similarity index 97% rename from Tests/ModelTests/CustomerDisputeTests.swift rename to Tests/ModelTests/CustomerTests/CustomerDisputeTests.swift index 68c92442..235b1605 100644 --- a/Tests/ModelTests/CustomerDisputeTests.swift +++ b/Tests/ModelTests/CustomerTests/CustomerDisputeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class CustomerDisputeTests: XCTestCase { +public final class CustomerDisputeTests: XCTestCase { let created = Date() let due = Date(timeIntervalSinceNow: 60 * 60 * 24) @@ -139,7 +139,7 @@ final class CustomerDisputeTests: XCTestCase { XCTAssertEqual(dispute.channel, .internal) } - static var allTests: [(String, (CustomerDisputeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (CustomerDisputeTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/CustomerServiceMessageTests.swift b/Tests/ModelTests/CustomerTests/CustomerServiceMessageTests.swift similarity index 96% rename from Tests/ModelTests/CustomerServiceMessageTests.swift rename to Tests/ModelTests/CustomerTests/CustomerServiceMessageTests.swift index 99cbbf94..f39d9860 100644 --- a/Tests/ModelTests/CustomerServiceMessageTests.swift +++ b/Tests/ModelTests/CustomerTests/CustomerServiceMessageTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class CustomerServiceMessageTests: XCTestCase { +public final class CustomerServiceMessageTests: XCTestCase { func testInit()throws { let message = try CustomerService.Message( type: .online, @@ -100,7 +100,7 @@ final class CustomerServiceMessageTests: XCTestCase { try XCTAssertEqual(message, decoder.decode(CustomerService.Message.self, from: json)) } - static var allTests: [(String, (CustomerServiceMessageTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (CustomerServiceMessageTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/CustomerServiceMessageTypeTests.swift b/Tests/ModelTests/CustomerTests/CustomerServiceMessageTypeTests.swift similarity index 90% rename from Tests/ModelTests/CustomerServiceMessageTypeTests.swift rename to Tests/ModelTests/CustomerTests/CustomerServiceMessageTypeTests.swift index a36c248c..4eacd10c 100644 --- a/Tests/ModelTests/CustomerServiceMessageTypeTests.swift +++ b/Tests/ModelTests/CustomerTests/CustomerServiceMessageTypeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class CustomerServiceMessageTypeTests: XCTestCase { +public final class CustomerServiceMessageTypeTests: XCTestCase { struct CSM: Codable { var type: CustomerService.Message.MessageType } @@ -42,7 +42,7 @@ final class CustomerServiceMessageTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(CSM.self, from: retail).type, .retail) } - static var allTests: [(String, (CustomerServiceMessageTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (CustomerServiceMessageTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/CustomerServiceTests.swift b/Tests/ModelTests/CustomerTests/CustomerServiceTests.swift similarity index 93% rename from Tests/ModelTests/CustomerServiceTests.swift rename to Tests/ModelTests/CustomerTests/CustomerServiceTests.swift index e5618bd4..6ab9aba3 100644 --- a/Tests/ModelTests/CustomerServiceTests.swift +++ b/Tests/ModelTests/CustomerTests/CustomerServiceTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class CustomerServiceTests: XCTestCase { +public final class CustomerServiceTests: XCTestCase { func testInit()throws { let service = try CustomerService( email: .init("address@email.com"), @@ -56,7 +56,7 @@ final class CustomerServiceTests: XCTestCase { try XCTAssertEqual(service, decoder.decode(CustomerService.self, from: json)) } - static var allTests: [(String, (CustomerServiceTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (CustomerServiceTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/DesignationTests.swift b/Tests/ModelTests/DesignationTests.swift index b0ad9548..805a5b0c 100644 --- a/Tests/ModelTests/DesignationTests.swift +++ b/Tests/ModelTests/DesignationTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class DesignationTests: XCTestCase { +public final class DesignationTests: XCTestCase { func testInit()throws { let designation = Business.Designation(title: "CTO", area: "Software Engineering") @@ -38,7 +38,7 @@ final class DesignationTests: XCTestCase { try XCTAssertEqual(designation, decoder.decode(Business.Designation.self, from: json)) } - static var allTests: [(String, (DesignationTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (DesignationTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/DetailTests.swift b/Tests/ModelTests/DetailedTests/DetailTests.swift similarity index 93% rename from Tests/ModelTests/DetailTests.swift rename to Tests/ModelTests/DetailedTests/DetailTests.swift index 1d777923..5fd953bc 100644 --- a/Tests/ModelTests/DetailTests.swift +++ b/Tests/ModelTests/DetailedTests/DetailTests.swift @@ -2,7 +2,7 @@ import XCTest @testable import PayPal @available(OSX 10.12, *) -final class DetailTests: XCTestCase { +public final class DetailTests: XCTestCase { let now = Date().iso8601 let later = Date.distantFuture.iso8601 let oneYear = (Date() + (60 * 60 * 24 * 365)).iso8601 @@ -48,7 +48,7 @@ final class DetailTests: XCTestCase { let json = "{\"final_payment_date\":\"\(later)\",\"last_payment_date\":\"\(now)\",\"failed_payment_count\":\"5\"," + "\"cycles_remaining\":\"30\",\"cycles_completed\":\"45\",\"last_payment_amount\":{\"value\":\"19.97\",\"currency_code\":\"USD\"}," + - "\"outstanding_balance\":{\"value\":\"599.00\",\"currency_code\":\"USD\"},\"next_billing_date\":\"\(oneYear)\"}" + "\"outstanding_balance\":{\"value\":\"599\",\"currency_code\":\"USD\"},\"next_billing_date\":\"\(oneYear)\"}" var index = 0 for (jsonChar, genChar) in zip(json, generated) { @@ -68,7 +68,7 @@ final class DetailTests: XCTestCase { { "outstanding_balance": { "currency_code": "USD", - "value": "599.00" + "value": "599" }, "cycles_remaining": "30", "cycles_completed": "45", @@ -101,7 +101,7 @@ final class DetailTests: XCTestCase { XCTAssertEqual(details, decoded) } - static var allTests: [(String, (DetailTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (DetailTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/DetailedAmountDetailTests.swift b/Tests/ModelTests/DetailedTests/DetailedAmountDetailTests.swift similarity index 96% rename from Tests/ModelTests/DetailedAmountDetailTests.swift rename to Tests/ModelTests/DetailedTests/DetailedAmountDetailTests.swift index b46896e6..7d4ca0ae 100644 --- a/Tests/ModelTests/DetailedAmountDetailTests.swift +++ b/Tests/ModelTests/DetailedTests/DetailedAmountDetailTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class DetailedAmountDetailTests: XCTestCase { +public final class DetailedAmountDetailTests: XCTestCase { func testInit()throws { let details = DetailedAmount.Detail( subtotal: 134.56, @@ -122,7 +122,7 @@ final class DetailedAmountDetailTests: XCTestCase { )) } - static var allTests: [(String, (DetailedAmountDetailTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (DetailedAmountDetailTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/DetailedAmountTests.swift b/Tests/ModelTests/DetailedTests/DetailedAmountTests.swift similarity index 91% rename from Tests/ModelTests/DetailedAmountTests.swift rename to Tests/ModelTests/DetailedTests/DetailedAmountTests.swift index 6f93fd77..549f5997 100644 --- a/Tests/ModelTests/DetailedAmountTests.swift +++ b/Tests/ModelTests/DetailedTests/DetailedAmountTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class DetailedAmountTests: XCTestCase { +public final class DetailedAmountTests: XCTestCase { func testInit()throws { let details = DetailedAmount.Detail( subtotal: 134.56, @@ -45,7 +45,7 @@ final class DetailedAmountTests: XCTestCase { try XCTAssertEqual(decoder.decode(DetailedAmount.self, from: json), amount) } - static var allTests: [(String, (DetailedAmountTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (DetailedAmountTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/DiscountTests.swift b/Tests/ModelTests/DiscountTests.swift index dfaec66a..43935e5c 100644 --- a/Tests/ModelTests/DiscountTests.swift +++ b/Tests/ModelTests/DiscountTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class DiscountTests: XCTestCase { +public final class DiscountTests: XCTestCase { func testInit()throws { let discount = Discount(percent: 15, amount: CurrencyAmount(currency: .usd, value: 1.25)) @@ -33,7 +33,7 @@ final class DiscountTests: XCTestCase { try XCTAssertEqual(discount, decoder.decode(Discount.self, from: json)) } - static var allTests: [(String, (DiscountTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (DiscountTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/DisplayPhoneTests.swift b/Tests/ModelTests/DisplayPhoneTests.swift index e3a8431f..bb718d0f 100644 --- a/Tests/ModelTests/DisplayPhoneTests.swift +++ b/Tests/ModelTests/DisplayPhoneTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class DisplayPhoneTests: XCTestCase { +public final class DisplayPhoneTests: XCTestCase { func testInit()throws { let phone = DisplayPhone(country: .unitedStates, number: "245364984688834") @@ -44,7 +44,7 @@ final class DisplayPhoneTests: XCTestCase { try XCTAssertEqual(decoder.decode(DisplayPhone.self, from: json), DisplayPhone(country: .unitedStates, number: "245364984688834")) } - static var allTests: [(String, (DisplayPhoneTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (DisplayPhoneTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/AcceptDisputeReasonTests.swift b/Tests/ModelTests/DisputeTests/AcceptDisputeReasonTests.swift similarity index 93% rename from Tests/ModelTests/AcceptDisputeReasonTests.swift rename to Tests/ModelTests/DisputeTests/AcceptDisputeReasonTests.swift index 98e27ea1..ebd795fb 100644 --- a/Tests/ModelTests/AcceptDisputeReasonTests.swift +++ b/Tests/ModelTests/DisputeTests/AcceptDisputeReasonTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class AcceptDisputeReasonTests: XCTestCase { +public final class AcceptDisputeReasonTests: XCTestCase { struct Accept: Codable { let reason: AcceptDisputeBody.Reason } @@ -46,7 +46,7 @@ final class AcceptDisputeReasonTests: XCTestCase { try XCTAssertEqual(decoder.decode(Accept.self, from: none).reason, .none) } - static var allTests: [(String, (AcceptDisputeReasonTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AcceptDisputeReasonTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/AcceptDisputeTests.swift b/Tests/ModelTests/DisputeTests/AcceptDisputeTests.swift similarity index 94% rename from Tests/ModelTests/AcceptDisputeTests.swift rename to Tests/ModelTests/DisputeTests/AcceptDisputeTests.swift index 6228b743..9b614a05 100644 --- a/Tests/ModelTests/AcceptDisputeTests.swift +++ b/Tests/ModelTests/DisputeTests/AcceptDisputeTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class AcceptDisputeTests: XCTestCase { +public final class AcceptDisputeTests: XCTestCase { func testInit()throws { let body = try AcceptDisputeBody( note: .init("Refund to customer"), @@ -53,7 +53,7 @@ final class AcceptDisputeTests: XCTestCase { let generated = try String(data: encoder.encode(body), encoding: .utf8)! let json = "{\"accept_claim_reason\":\"COMPANY_POLICY\",\"invoice_id\":\"3EC9D031-0DBF-446F-ABC0-31B4A6E0D2B5\"," + - "\"note\":\"Refund to customer\",\"refund_amount\":{\"value\":\"55.50\",\"currency_code\":\"USD\"}}" + "\"note\":\"Refund to customer\",\"refund_amount\":{\"value\":\"55.5\",\"currency_code\":\"USD\"}}" var index = 0 for (jsonChar, genChar) in zip(json, generated) { @@ -77,7 +77,7 @@ final class AcceptDisputeTests: XCTestCase { let valid = """ { "refund_amount": { - "value": "55.50", + "value": "55.5", "currency_code": "USD" }, "invoice_id": "3EC9D031-0DBF-446F-ABC0-31B4A6E0D2B5", @@ -88,7 +88,7 @@ final class AcceptDisputeTests: XCTestCase { let noteFail = """ { "refund_amount": { - "value": "55.50", + "value": "55.5", "currency_code": "USD" }, "invoice_id": "3EC9D031-0DBF-446F-ABC0-31B4A6E0D2B5", @@ -101,7 +101,7 @@ final class AcceptDisputeTests: XCTestCase { try XCTAssertEqual(body, decoder.decode(AcceptDisputeBody.self, from: valid)) } - static var allTests: [(String, (AcceptDisputeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (AcceptDisputeTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/DisputeChannelTests.swift b/Tests/ModelTests/DisputeTests/DisputeChannelTests.swift similarity index 91% rename from Tests/ModelTests/DisputeChannelTests.swift rename to Tests/ModelTests/DisputeTests/DisputeChannelTests.swift index 3a7133e7..474a5d5d 100644 --- a/Tests/ModelTests/DisputeChannelTests.swift +++ b/Tests/ModelTests/DisputeTests/DisputeChannelTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class DisputeChannelTests: XCTestCase { +public final class DisputeChannelTests: XCTestCase { struct Dispute: Codable { let channel: CustomerDispute.Channel } @@ -42,7 +42,7 @@ final class DisputeChannelTests: XCTestCase { try XCTAssertEqual(decoder.decode(Dispute.self, from: external).channel, .external) } - static var allTests: [(String, (DisputeChannelTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (DisputeChannelTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/DisputeLifCycleStageTests.swift b/Tests/ModelTests/DisputeTests/DisputeLifCycleStageTests.swift similarity index 92% rename from Tests/ModelTests/DisputeLifCycleStageTests.swift rename to Tests/ModelTests/DisputeTests/DisputeLifCycleStageTests.swift index 7432f3d0..575bee61 100644 --- a/Tests/ModelTests/DisputeLifCycleStageTests.swift +++ b/Tests/ModelTests/DisputeTests/DisputeLifCycleStageTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class DisputeLifeCycleTests: XCTestCase { +public final class DisputeLifeCycleTests: XCTestCase { struct Dispute: Codable { let stage: CustomerDispute.LifeCycleStage } @@ -44,7 +44,7 @@ final class DisputeLifeCycleTests: XCTestCase { try XCTAssertEqual(decoder.decode(Dispute.self, from: arbitration).stage, .arbitration) } - static var allTests: [(String, (DisputeLifeCycleTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (DisputeLifeCycleTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/DisputeOutcomeTests.swift b/Tests/ModelTests/DisputeTests/DisputeOutcomeTests.swift similarity index 91% rename from Tests/ModelTests/DisputeOutcomeTests.swift rename to Tests/ModelTests/DisputeTests/DisputeOutcomeTests.swift index b24e27dd..90a13197 100644 --- a/Tests/ModelTests/DisputeOutcomeTests.swift +++ b/Tests/ModelTests/DisputeTests/DisputeOutcomeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class DisputeOutcomeTests: XCTestCase { +public final class DisputeOutcomeTests: XCTestCase { func testInit()throws { let outcome = CustomerDispute.Outcome(code: .buyer, refunded: CurrencyCodeAmount(currency: .usd, value: 56.72)) @@ -33,7 +33,7 @@ final class DisputeOutcomeTests: XCTestCase { try XCTAssertEqual(outcome, decoder.decode(CustomerDispute.Outcome.self, from: json)) } - static var allTests: [(String, (DisputeOutcomeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (DisputeOutcomeTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/DisputeResolutionOffer.swift b/Tests/ModelTests/DisputeTests/DisputeResolutionOffer.swift similarity index 94% rename from Tests/ModelTests/DisputeResolutionOffer.swift rename to Tests/ModelTests/DisputeTests/DisputeResolutionOffer.swift index 82de85ce..700cbb41 100644 --- a/Tests/ModelTests/DisputeResolutionOffer.swift +++ b/Tests/ModelTests/DisputeTests/DisputeResolutionOffer.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class DisputeResolutionOfferTests: XCTestCase { +public final class DisputeResolutionOfferTests: XCTestCase { func testInit()throws { let offer = try CustomerDispute.ResolutionOffer( note: .init("Offer refund with replacement item."), @@ -60,7 +60,7 @@ final class DisputeResolutionOfferTests: XCTestCase { ) let generated = try String(data: encoder.encode(offer), encoding: .utf8)! let json = - "{\"offer_type\":\"REFUND_WITH_REPLACEMENT\",\"offer_amount\":{\"value\":\"23.00\",\"currency_code\":\"USD\"},\"note\":\"Notable note.\"}" + "{\"offer_type\":\"REFUND_WITH_REPLACEMENT\",\"offer_amount\":{\"value\":\"23\",\"currency_code\":\"USD\"},\"note\":\"Notable note.\"}" var index = 0 for (jsonChar, genChar) in zip(json, generated) { @@ -116,7 +116,7 @@ final class DisputeResolutionOfferTests: XCTestCase { )) } - static var allTests: [(String, (DisputeResolutionOfferTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (DisputeResolutionOfferTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/DisputeStatusTests.swift b/Tests/ModelTests/DisputeTests/DisputeStatusTests.swift similarity index 93% rename from Tests/ModelTests/DisputeStatusTests.swift rename to Tests/ModelTests/DisputeTests/DisputeStatusTests.swift index a6712de5..104e4d80 100644 --- a/Tests/ModelTests/DisputeStatusTests.swift +++ b/Tests/ModelTests/DisputeTests/DisputeStatusTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class DisputeStatusTests: XCTestCase { +public final class DisputeStatusTests: XCTestCase { struct Request: Codable { let method: PayPal.Method } @@ -50,7 +50,7 @@ final class DisputeStatusTests: XCTestCase { try XCTAssertEqual(decoder.decode(Dispute.self, from: other).status, .other) } - static var allTests: [(String, (DisputeStatusTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (DisputeStatusTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/DocumentTests.swift b/Tests/ModelTests/DocumentTests.swift index 814b0aec..f14b18c7 100644 --- a/Tests/ModelTests/DocumentTests.swift +++ b/Tests/ModelTests/DocumentTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class DocumentTests: XCTestCase { +public final class DocumentTests: XCTestCase { func testInit()throws { let document = Document(name: "README.md", size: "65kb") @@ -29,7 +29,7 @@ final class DocumentTests: XCTestCase { try XCTAssertEqual(Document(name: "README.md", size: "65kb"), decoder.decode(Document.self, from: json)) } - static var allTests: [(String, (DocumentTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (DocumentTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/CCEmailTests.swift b/Tests/ModelTests/EmailTests/CCEmailTests.swift similarity index 93% rename from Tests/ModelTests/CCEmailTests.swift rename to Tests/ModelTests/EmailTests/CCEmailTests.swift index 1a372531..a921b278 100644 --- a/Tests/ModelTests/CCEmailTests.swift +++ b/Tests/ModelTests/EmailTests/CCEmailTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class CCEmailTests: XCTestCase { +public final class CCEmailTests: XCTestCase { func testInit()throws { let email = try CCEmail(email: .init("witheringheights@exmaple.com")) @@ -43,7 +43,7 @@ final class CCEmailTests: XCTestCase { try XCTAssertEqual(CCEmail(email: .init("witheringheights@exmaple.com")), decoder.decode(CCEmail.self, from: json)) } - static var allTests: [(String, (CCEmailTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (CCEmailTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/EmailFrequencyTests.swift b/Tests/ModelTests/EmailTests/EmailFrequencyTests.swift similarity index 91% rename from Tests/ModelTests/EmailFrequencyTests.swift rename to Tests/ModelTests/EmailTests/EmailFrequencyTests.swift index 0bd2f3ab..e1d45c96 100644 --- a/Tests/ModelTests/EmailFrequencyTests.swift +++ b/Tests/ModelTests/EmailTests/EmailFrequencyTests.swift @@ -3,7 +3,7 @@ import XCTest typealias EmailFrequency = NotificationOptions.EmailFrequency -final class EmailFrequencyTests: XCTestCase { +public final class EmailFrequencyTests: XCTestCase { struct Email: Codable { let frequency: NotificationOptions.EmailFrequency } @@ -44,7 +44,7 @@ final class EmailFrequencyTests: XCTestCase { try XCTAssertEqual(decoder.decode(Email.self, from: `default`).frequency, .default) } - static var allTests: [(String, (EmailFrequencyTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (EmailFrequencyTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PayPalAPIErrorTests.swift b/Tests/ModelTests/ErrorTests/PayPalAPIErrorTests.swift similarity index 93% rename from Tests/ModelTests/PayPalAPIErrorTests.swift rename to Tests/ModelTests/ErrorTests/PayPalAPIErrorTests.swift index b15a2cb5..495eccf1 100644 --- a/Tests/ModelTests/PayPalAPIErrorTests.swift +++ b/Tests/ModelTests/ErrorTests/PayPalAPIErrorTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class PayPalAPIErrorTests: XCTestCase { +public final class PayPalAPIErrorTests: XCTestCase { let error = PayPalAPIError( identifier: "INVALID_REQUEST", reason: "Validation for request data failed", @@ -45,7 +45,7 @@ final class PayPalAPIErrorTests: XCTestCase { try XCTAssertEqual(self.error, decoder.decode(PayPalAPIError.self, from: valid)) } - static var allTests: [(String, (PayPalAPIErrorTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PayPalAPIErrorTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/PayPalAPIIdentityErrorTests.swift b/Tests/ModelTests/ErrorTests/PayPalAPIIdentityErrorTests.swift similarity index 89% rename from Tests/ModelTests/PayPalAPIIdentityErrorTests.swift rename to Tests/ModelTests/ErrorTests/PayPalAPIIdentityErrorTests.swift index ed588cbe..b5aac518 100644 --- a/Tests/ModelTests/PayPalAPIIdentityErrorTests.swift +++ b/Tests/ModelTests/ErrorTests/PayPalAPIIdentityErrorTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class PayPalAPIIdentityErrorTests: XCTestCase { +public final class PayPalAPIIdentityErrorTests: XCTestCase { let error = PayPalAPIIdentityError(identifier: "invalid_client", reason: "Client Authentication failed") func testInit()throws { @@ -36,7 +36,7 @@ final class PayPalAPIIdentityErrorTests: XCTestCase { try XCTAssertEqual(self.error, decoder.decode(PayPalAPIIdentityError.self, from: valid)) } - static var allTests: [(String, (PayPalAPIIdentityErrorTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PayPalAPIIdentityErrorTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/EstablishmentTests.swift b/Tests/ModelTests/EstablishmentTests.swift index 5e327994..4963f317 100644 --- a/Tests/ModelTests/EstablishmentTests.swift +++ b/Tests/ModelTests/EstablishmentTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class EstablishmentTests: XCTestCase { +public final class EstablishmentTests: XCTestCase { func testInit()throws { let bank = Establishment(state: .or, country: .unitedStates) @@ -36,7 +36,7 @@ final class EstablishmentTests: XCTestCase { try XCTAssertEqual(decoder.decode(Establishment.self, from: json), Establishment(state: .or, country: .unitedStates)) } - static var allTests: [(String, (EstablishmentTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (EstablishmentTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/EvidenceInfoTests.swift b/Tests/ModelTests/EvidenceTests/EvidenceInfoTests.swift similarity index 95% rename from Tests/ModelTests/EvidenceInfoTests.swift rename to Tests/ModelTests/EvidenceTests/EvidenceInfoTests.swift index 6b038858..8133e336 100644 --- a/Tests/ModelTests/EvidenceInfoTests.swift +++ b/Tests/ModelTests/EvidenceTests/EvidenceInfoTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class EvidenceInfoTests: XCTestCase { +public final class EvidenceInfoTests: XCTestCase { func testInit()throws { let evidence = Evidence.Info( tracking: [ @@ -67,7 +67,7 @@ final class EvidenceInfoTests: XCTestCase { try XCTAssertEqual(evidence, decoder.decode(Evidence.Info.self, from: json)) } - static var allTests: [(String, (EvidenceInfoTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (EvidenceInfoTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/EvidenceTests.swift b/Tests/ModelTests/EvidenceTests/EvidenceTests.swift similarity index 97% rename from Tests/ModelTests/EvidenceTests.swift rename to Tests/ModelTests/EvidenceTests/EvidenceTests.swift index 67436ac7..34364e66 100644 --- a/Tests/ModelTests/EvidenceTests.swift +++ b/Tests/ModelTests/EvidenceTests/EvidenceTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class EvidenceTests: XCTestCase { +public final class EvidenceTests: XCTestCase { func testInit()throws { let evidence = try Evidence( type: .proofOfFulfillment, @@ -121,7 +121,7 @@ final class EvidenceTests: XCTestCase { try XCTAssertEqual(evidence, decoder.decode(Evidence.self, from: json)) } - static var allTests: [(String, (EvidenceTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (EvidenceTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/EvidenceTypeTests.swift b/Tests/ModelTests/EvidenceTests/EvidenceTypeTests.swift similarity index 96% rename from Tests/ModelTests/EvidenceTypeTests.swift rename to Tests/ModelTests/EvidenceTests/EvidenceTypeTests.swift index ec10b22f..4bcf2273 100644 --- a/Tests/ModelTests/EvidenceTypeTests.swift +++ b/Tests/ModelTests/EvidenceTests/EvidenceTypeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class EvidenceTypeTests: XCTestCase { +public final class EvidenceTypeTests: XCTestCase { struct Evid: Codable { let type: Evidence.EvidenceType } @@ -66,7 +66,7 @@ final class EvidenceTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Evid.self, from: proofOfDeliverySignature).type, .proofOfDeliverySignature) } - static var allTests: [(String, (EvidenceTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (EvidenceTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/ExtensionsTests.swift b/Tests/ModelTests/ExtensionsTests.swift index 083e5391..5735edad 100644 --- a/Tests/ModelTests/ExtensionsTests.swift +++ b/Tests/ModelTests/ExtensionsTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class ExtensionsTests: XCTestCase { +public final class ExtensionsTests: XCTestCase { let extensions = Extensions( paymentProperties: PaymentProperties( creditDebitCode: .credit, @@ -86,7 +86,7 @@ final class ExtensionsTests: XCTestCase { try XCTAssertEqual(self.extensions, decoder.decode(Extensions.self, from: ext)) } - static var allTests: [(String, (ExtensionsTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ExtensionsTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/FileAttachmentTests.swift b/Tests/ModelTests/FileAttachmentTests.swift index a1142b73..9a2468a8 100644 --- a/Tests/ModelTests/FileAttachmentTests.swift +++ b/Tests/ModelTests/FileAttachmentTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class FileAttachmentTests: XCTestCase { +public final class FileAttachmentTests: XCTestCase { func testInit()throws { let file = FileAttachment(name: "photo.jpg", url: "https://avatars3.githubusercontent.com/u/2872298?s=200&v=4") @@ -30,7 +30,7 @@ final class FileAttachmentTests: XCTestCase { try XCTAssertEqual(file, decoder.decode(FileAttachment.self, from: ext)) } - static var allTests: [(String, (FileAttachmentTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (FileAttachmentTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/FinancialInstrumentAccountTypeTests.swift b/Tests/ModelTests/FinancialTests/FinancialInstrumentAccountTypeTests.swift similarity index 90% rename from Tests/ModelTests/FinancialInstrumentAccountTypeTests.swift rename to Tests/ModelTests/FinancialTests/FinancialInstrumentAccountTypeTests.swift index 9dd3ff2f..22340f5b 100644 --- a/Tests/ModelTests/FinancialInstrumentAccountTypeTests.swift +++ b/Tests/ModelTests/FinancialTests/FinancialInstrumentAccountTypeTests.swift @@ -3,7 +3,7 @@ import XCTest typealias AccountType = FinancialInstrument.AccountType -final class FinancialInstrumentAccountTypeTests: XCTestCase { +public final class FinancialInstrumentAccountTypeTests: XCTestCase { struct Instrument: Codable { let account: AccountType } @@ -44,7 +44,7 @@ final class FinancialInstrumentAccountTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Instrument.self, from: checking).account, .checking) } - static var allTests: [(String, (FinancialInstrumentAccountTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (FinancialInstrumentAccountTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/FinancialInstrumentTests.swift b/Tests/ModelTests/FinancialTests/FinancialInstrumentTests.swift similarity index 92% rename from Tests/ModelTests/FinancialInstrumentTests.swift rename to Tests/ModelTests/FinancialTests/FinancialInstrumentTests.swift index 7c20b42a..8d3f5c4b 100644 --- a/Tests/ModelTests/FinancialInstrumentTests.swift +++ b/Tests/ModelTests/FinancialTests/FinancialInstrumentTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class FinancialInstrumentTests: XCTestCase { +public final class FinancialInstrumentTests: XCTestCase { func testInit()throws { let instrument = FinancialInstrument() @@ -51,7 +51,7 @@ final class FinancialInstrumentTests: XCTestCase { try XCTAssertEqual(FinancialInstruments(instruments: [FinancialInstrument()]), decoder.decode(FinancialInstruments.self, from: array)) } - static var allTests: [(String, (FinancialInstrumentTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (FinancialInstrumentTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/FinancialInstrumentTypeTests.swift b/Tests/ModelTests/FinancialTests/FinancialInstrumentTypeTests.swift similarity index 87% rename from Tests/ModelTests/FinancialInstrumentTypeTests.swift rename to Tests/ModelTests/FinancialTests/FinancialInstrumentTypeTests.swift index f9378c7c..043d8108 100644 --- a/Tests/ModelTests/FinancialInstrumentTypeTests.swift +++ b/Tests/ModelTests/FinancialTests/FinancialInstrumentTypeTests.swift @@ -3,7 +3,7 @@ import XCTest typealias InstrumentType = FinancialInstrument.InstrumentType -final class FinancialInstrumentTypeTests: XCTestCase { +public final class FinancialInstrumentTypeTests: XCTestCase { struct Instrument: Codable { let type: InstrumentType } @@ -35,7 +35,7 @@ final class FinancialInstrumentTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Instrument.self, from: bank).type, .bank) } - static var allTests: [(String, (FinancialInstrumentTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (FinancialInstrumentTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/FraudManagementFilterIDTests.swift b/Tests/ModelTests/FraudTests/FraudManagementFilterIDTests.swift similarity index 95% rename from Tests/ModelTests/FraudManagementFilterIDTests.swift rename to Tests/ModelTests/FraudTests/FraudManagementFilterIDTests.swift index 142ac988..c11b81ed 100644 --- a/Tests/ModelTests/FraudManagementFilterIDTests.swift +++ b/Tests/ModelTests/FraudTests/FraudManagementFilterIDTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias ID = FraudManagementFilter.ID -final class FraudManagementFilterIDTests: XCTestCase { +public final class FraudManagementFilterIDTests: XCTestCase { private struct Filter: Codable { let id: ID } @@ -62,7 +62,7 @@ final class FraudManagementFilterIDTests: XCTestCase { try XCTAssertEqual(decoder.decode(Filter.self, from: securityCodeMismatch).id, .securityCodeMismatch) } - static var allTests: [(String, (FraudManagementFilterIDTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (FraudManagementFilterIDTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/FraudManagementFilterTests.swift b/Tests/ModelTests/FraudTests/FraudManagementFilterTests.swift similarity index 81% rename from Tests/ModelTests/FraudManagementFilterTests.swift rename to Tests/ModelTests/FraudTests/FraudManagementFilterTests.swift index 2c366885..60475d2a 100644 --- a/Tests/ModelTests/FraudManagementFilterTests.swift +++ b/Tests/ModelTests/FraudTests/FraudManagementFilterTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class FraudManagementFilterTests: XCTestCase { +public final class FraudManagementFilterTests: XCTestCase { func testDecoding()throws { let json = """ { @@ -20,7 +20,7 @@ final class FraudManagementFilterTests: XCTestCase { XCTAssertEqual(filter.description, "Descripted") } - static var allTests: [(String, (FraudManagementFilterTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (FraudManagementFilterTests) -> ()throws -> ())] = [ ("testDecoding", testDecoding) ] } diff --git a/Tests/ModelTests/FraudManagementFilterTypeTests.swift b/Tests/ModelTests/FraudTests/FraudManagementFilterTypeTests.swift similarity index 90% rename from Tests/ModelTests/FraudManagementFilterTypeTests.swift rename to Tests/ModelTests/FraudTests/FraudManagementFilterTypeTests.swift index 020ce14b..90a12e5f 100644 --- a/Tests/ModelTests/FraudManagementFilterTypeTests.swift +++ b/Tests/ModelTests/FraudTests/FraudManagementFilterTypeTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Type = FraudManagementFilter.FilterType -final class FraudManagementFilterTypeTests: XCTestCase { +public final class FraudManagementFilterTypeTests: XCTestCase { private struct Instrument: Codable { let type: Type } @@ -46,7 +46,7 @@ final class FraudManagementFilterTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Instrument.self, from: report).type, .report) } - static var allTests: [(String, (FraudManagementFilterTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (FraudManagementFilterTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/FrequencyTests.swift b/Tests/ModelTests/FrequencyTests.swift index 32d004b3..c5648131 100644 --- a/Tests/ModelTests/FrequencyTests.swift +++ b/Tests/ModelTests/FrequencyTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class FrequencyTests: XCTestCase { +public final class FrequencyTests: XCTestCase { struct Action: Codable { let frequency: Frequency } @@ -44,7 +44,7 @@ final class FrequencyTests: XCTestCase { try XCTAssertEqual(decoder.decode(Action.self, from: year).frequency, .year) } - static var allTests: [(String, (FrequencyTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (FrequencyTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/FundingInstrumentTests.swift b/Tests/ModelTests/FundingTests/FundingInstrumentTests.swift similarity index 90% rename from Tests/ModelTests/FundingInstrumentTests.swift rename to Tests/ModelTests/FundingTests/FundingInstrumentTests.swift index a4f4a005..a2e8c8e8 100644 --- a/Tests/ModelTests/FundingInstrumentTests.swift +++ b/Tests/ModelTests/FundingTests/FundingInstrumentTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class FundingInstrumentTests: XCTestCase { +public final class FundingInstrumentTests: XCTestCase { func testInit()throws { let instrument = FundingInstrument(token: .init(creditCard: "0F874884-66E4-4D45-9906-C3E9957BC1FF", payer: nil)) @@ -30,7 +30,7 @@ final class FundingInstrumentTests: XCTestCase { try XCTAssertEqual(instrument, decoder.decode(FundingInstrument.self, from: json)) } - static var allTests: [(String, (FundingInstrumentTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (FundingInstrumentTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/FundingOptionTests.swift b/Tests/ModelTests/FundingTests/FundingOptionTests.swift similarity index 91% rename from Tests/ModelTests/FundingOptionTests.swift rename to Tests/ModelTests/FundingTests/FundingOptionTests.swift index 677b86ee..ba0c77e6 100644 --- a/Tests/ModelTests/FundingOptionTests.swift +++ b/Tests/ModelTests/FundingTests/FundingOptionTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class FundingOptionTests: XCTestCase { +public final class FundingOptionTests: XCTestCase { struct Funding: Codable { let option: FundingOption } @@ -42,7 +42,7 @@ final class FundingOptionTests: XCTestCase { try XCTAssertEqual(decoder.decode(Funding.self, from: instruments).option, .instruments) } - static var allTests: [(String, (FundingOptionTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (FundingOptionTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/GovernmentBodyTests.swift b/Tests/ModelTests/GovernmentBodyTests.swift index 342abd7d..fb47445a 100644 --- a/Tests/ModelTests/GovernmentBodyTests.swift +++ b/Tests/ModelTests/GovernmentBodyTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class GovernmentBodyTests: XCTestCase { +public final class GovernmentBodyTests: XCTestCase { func testInit()throws { let govt = GovernmentBody(name: "value") @@ -26,7 +26,7 @@ final class GovernmentBodyTests: XCTestCase { try XCTAssertEqual(GovernmentBody(name: "value"), decoder.decode(GovernmentBody.self, from: json)) } - static var allTests: [(String, (GovernmentBodyTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (GovernmentBodyTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/IDTests.swift b/Tests/ModelTests/IDTests.swift index 4fa5988a..d165dd88 100644 --- a/Tests/ModelTests/IDTests.swift +++ b/Tests/ModelTests/IDTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class IDTests: XCTestCase { +public final class IDTests: XCTestCase { func testInit()throws { let null = ID() let id = ID("P-52603F876DFD4C61") @@ -30,7 +30,7 @@ final class IDTests: XCTestCase { try XCTAssertEqual("P-52603F876DFD4C61", decoder.decode(ID.self, from: mit)) } - static var allTests: [(String, (IDTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (IDTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/InitialFailActionTests.swift b/Tests/ModelTests/InitialFailActionTests.swift index 0cf8d437..6a28da90 100644 --- a/Tests/ModelTests/InitialFailActionTests.swift +++ b/Tests/ModelTests/InitialFailActionTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class InitialFailActionTests: XCTestCase { +public final class InitialFailActionTests: XCTestCase { struct Agreement: Codable { let action: InitialFailAction } @@ -42,7 +42,7 @@ final class InitialFailActionTests: XCTestCase { try XCTAssertEqual(decoder.decode(Agreement.self, from: cont).action, .continue) } - static var allTests: [(String, (InitialFailActionTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (InitialFailActionTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/InvoiceItemTests.swift b/Tests/ModelTests/InvoiceTests/InvoiceItemTests.swift similarity index 97% rename from Tests/ModelTests/InvoiceItemTests.swift rename to Tests/ModelTests/InvoiceTests/InvoiceItemTests.swift index aeec384f..b8097cd4 100644 --- a/Tests/ModelTests/InvoiceItemTests.swift +++ b/Tests/ModelTests/InvoiceTests/InvoiceItemTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class InvoiceItemTests: XCTestCase { +public final class InvoiceItemTests: XCTestCase { let now = Date() func testInit()throws { @@ -109,7 +109,7 @@ final class InvoiceItemTests: XCTestCase { ) let generated = try String(data: encoder.encode(item), encoding: .utf8)! let json = - "{\"quantity\":3,\"unit_price\":{\"currency\":\"USD\",\"value\":\"50.00\"},\"unit_of_measure\":\"QUANTITY\",\"name\":\"Widget\"," + + "{\"quantity\":3,\"unit_price\":{\"currency\":\"USD\",\"value\":\"50\"},\"unit_of_measure\":\"QUANTITY\",\"name\":\"Widget\"," + "\"description\":\"Round and white, like a ping-pong ball\",\"date\":\"\(self.now.iso8601)\"}" var index = 0 @@ -208,7 +208,7 @@ final class InvoiceItemTests: XCTestCase { try XCTAssertEqual(item, decoder.decode(Invoice.Item.self, from: json)) } - static var allTests: [(String, (InvoiceItemTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (InvoiceItemTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/InvoiceListTests.swift b/Tests/ModelTests/InvoiceTests/InvoiceListTests.swift similarity index 85% rename from Tests/ModelTests/InvoiceListTests.swift rename to Tests/ModelTests/InvoiceTests/InvoiceListTests.swift index beff55f8..d2f14cd8 100644 --- a/Tests/ModelTests/InvoiceListTests.swift +++ b/Tests/ModelTests/InvoiceTests/InvoiceListTests.swift @@ -1,21 +1,21 @@ import XCTest @testable import PayPal -final class InvoiceListTests: XCTestCase { +public final class InvoiceListTests: XCTestCase { let now = Date() func testInit()throws { let invoice = try Invoice( number: nil, merchant: MerchantInfo( - email: "hello@vapor.codes", - business: "Qutheory LLC.", - firstName: "Tanner", - lastName: "Nelson", + email: .init("hello@vapor.codes"), + business: .init("Qutheory LLC."), + firstName: .init("Tanner"), + lastName: .init("Nelson"), address: nil, phone: nil, fax: nil, - website: "https://vapor.codes/", + website: .init("https://vapor.codes/"), taxID: nil, info: nil ), @@ -48,14 +48,14 @@ final class InvoiceListTests: XCTestCase { try XCTAssertEqual(list.invoices?.first, Invoice( number: nil, merchant: MerchantInfo( - email: "hello@vapor.codes", - business: "Qutheory LLC.", - firstName: "Tanner", - lastName: "Nelson", + email: .init("hello@vapor.codes"), + business: .init("Qutheory LLC."), + firstName: .init("Tanner"), + lastName: .init("Nelson"), address: nil, phone: nil, fax: nil, - website: "https://vapor.codes/", + website: .init("https://vapor.codes/"), taxID: nil, info: nil ), @@ -105,7 +105,7 @@ final class InvoiceListTests: XCTestCase { try XCTAssertEqual(list, decoder.decode(InvoiceList.self, from: json)) } - static var allTests: [(String, (InvoiceListTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (InvoiceListTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/InvoiceMeasureTests.swift b/Tests/ModelTests/InvoiceTests/InvoiceMeasureTests.swift similarity index 91% rename from Tests/ModelTests/InvoiceMeasureTests.swift rename to Tests/ModelTests/InvoiceTests/InvoiceMeasureTests.swift index 016873ae..1b28a1cf 100644 --- a/Tests/ModelTests/InvoiceMeasureTests.swift +++ b/Tests/ModelTests/InvoiceTests/InvoiceMeasureTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class InvoiceMeasureTests: XCTestCase { +public final class InvoiceMeasureTests: XCTestCase { struct Inv: Codable { let measure: Invoice.Measure } @@ -43,7 +43,7 @@ final class InvoiceMeasureTests: XCTestCase { try XCTAssertEqual(decoder.decode(Inv.self, from: quantity).measure, .quantity) } - static var allTests: [(String, (InvoiceMeasureTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (InvoiceMeasureTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/InvoicePaymentTests.swift b/Tests/ModelTests/InvoiceTests/InvoicePaymentTests.swift similarity index 86% rename from Tests/ModelTests/InvoicePaymentTests.swift rename to Tests/ModelTests/InvoiceTests/InvoicePaymentTests.swift index df6a2af0..ce6a47bf 100644 --- a/Tests/ModelTests/InvoicePaymentTests.swift +++ b/Tests/ModelTests/InvoiceTests/InvoicePaymentTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class InvoicePaymentTests: XCTestCase { +public final class InvoicePaymentTests: XCTestCase { let now = Date() func testInit()throws { @@ -18,7 +18,7 @@ final class InvoicePaymentTests: XCTestCase { let payment = Invoice.Payment(method: .cash, amount: CurrencyAmount(currency: .usd, value: 20.00), date: self.now, note: "I got the payment by cash!") let generated = try String(data: encoder.encode(payment), encoding: .utf8)! let json = - "{\"amount\":{\"currency\":\"USD\",\"value\":\"20.00\"},\"method\":\"CASH\",\"note\":\"I got the payment by cash!\"," + + "{\"amount\":{\"currency\":\"USD\",\"value\":\"20\"},\"method\":\"CASH\",\"note\":\"I got the payment by cash!\"," + "\"date\":\"\(self.now.iso8601)\"}" var index = 0 @@ -40,7 +40,7 @@ final class InvoicePaymentTests: XCTestCase { "method": "CASH", "amount": { "currency": "USD", - "value": "20.00" + "value": "20" }, "date": "\(self.now.iso8601)", "note": "I got the payment by cash!" @@ -50,7 +50,7 @@ final class InvoicePaymentTests: XCTestCase { try XCTAssertEqual(payment, decoder.decode(Invoice.Payment.self, from: json)) } - static var allTests: [(String, (InvoicePaymentTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (InvoicePaymentTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/InvoiceReminderTests.swift b/Tests/ModelTests/InvoiceTests/InvoiceReminderTests.swift similarity index 93% rename from Tests/ModelTests/InvoiceReminderTests.swift rename to Tests/ModelTests/InvoiceTests/InvoiceReminderTests.swift index a4d6581e..0df7317c 100644 --- a/Tests/ModelTests/InvoiceReminderTests.swift +++ b/Tests/ModelTests/InvoiceTests/InvoiceReminderTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class InvoiceReminderTests: XCTestCase { +public final class InvoiceReminderTests: XCTestCase { func testInit()throws { let reminder = Invoice.Reminder(subject: "Invoice Not Sent", note: "Please send the money", emails: [.init(email: "payer@example.com")]) @@ -47,7 +47,7 @@ final class InvoiceReminderTests: XCTestCase { try XCTAssertEqual(reminder, decoder.decode(Invoice.Reminder.self, from: json)) } - static var allTests: [(String, (InvoiceReminderTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (InvoiceReminderTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/InvoiceSearchTests.swift b/Tests/ModelTests/InvoiceTests/InvoiceSearchTests.swift similarity index 95% rename from Tests/ModelTests/InvoiceSearchTests.swift rename to Tests/ModelTests/InvoiceTests/InvoiceSearchTests.swift index 3851dcb3..a1a0ab7e 100644 --- a/Tests/ModelTests/InvoiceSearchTests.swift +++ b/Tests/ModelTests/InvoiceTests/InvoiceSearchTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class InvoiceSearchTests: XCTestCase { +public final class InvoiceSearchTests: XCTestCase { let now = Date() let later = (Date() + 60 * 60 * 24 * 60) @@ -82,7 +82,7 @@ final class InvoiceSearchTests: XCTestCase { try XCTAssertEqual(search, decoder.decode(Invoice.Search.self, from: json)) } - static var allTests: [(String, (InvoiceSearchTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (InvoiceSearchTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/InvoiceStatusTests.swift b/Tests/ModelTests/InvoiceTests/InvoiceStatusTests.swift similarity index 94% rename from Tests/ModelTests/InvoiceStatusTests.swift rename to Tests/ModelTests/InvoiceTests/InvoiceStatusTests.swift index 12ff53d7..f9965efc 100644 --- a/Tests/ModelTests/InvoiceStatusTests.swift +++ b/Tests/ModelTests/InvoiceTests/InvoiceStatusTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class InvoiceStatusTests: XCTestCase { +public final class InvoiceStatusTests: XCTestCase { struct Inv: Codable { let status: Invoice.Status @@ -55,7 +55,7 @@ final class InvoiceStatusTests: XCTestCase { try XCTAssertEqual(decoder.decode(Inv.self, from: scheduled).status, .scheduled) } - static var allTests: [(String, (InvoiceStatusTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (InvoiceStatusTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/InvoiceTests.swift b/Tests/ModelTests/InvoiceTests/InvoiceTests.swift similarity index 92% rename from Tests/ModelTests/InvoiceTests.swift rename to Tests/ModelTests/InvoiceTests/InvoiceTests.swift index 8f1d0631..cdafa108 100644 --- a/Tests/ModelTests/InvoiceTests.swift +++ b/Tests/ModelTests/InvoiceTests/InvoiceTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class InvoiceTests: XCTestCase { +public final class InvoiceTests: XCTestCase { let now = Date() var dueStr: String { @@ -15,14 +15,14 @@ final class InvoiceTests: XCTestCase { let invoice = try Invoice( number: nil, merchant: MerchantInfo( - email: "hello@vapor.codes", - business: "Qutheory LLC.", - firstName: "Tanner", - lastName: "Nelson", + email: .init("hello@vapor.codes"), + business: .init("Qutheory LLC."), + firstName: .init("Tanner"), + lastName: .init("Nelson"), address: nil, phone: nil, fax: nil, - website: "https://vapor.codes/", + website: .init("https://vapor.codes/"), taxID: nil, info: nil ), @@ -79,14 +79,14 @@ final class InvoiceTests: XCTestCase { try XCTAssertEqual(invoice.custom, CustomAmount(label: nil, amount: .init(CurrencyAmount(currency: .usd, value: 10.00)))) try XCTAssertEqual(invoice.merchant, MerchantInfo( - email: "hello@vapor.codes", - business: "Qutheory LLC.", - firstName: "Tanner", - lastName: "Nelson", + email: .init("hello@vapor.codes"), + business: .init("Qutheory LLC."), + firstName: .init("Tanner"), + lastName: .init("Nelson"), address: nil, phone: nil, fax: nil, - website: "https://vapor.codes/", + website: .init("https://vapor.codes/"), taxID: nil, info: nil )) @@ -155,14 +155,14 @@ final class InvoiceTests: XCTestCase { let invoice = try Invoice( number: nil, merchant: MerchantInfo( - email: "hello@vapor.codes", - business: "Qutheory LLC.", - firstName: "Tanner", - lastName: "Nelson", + email: .init("hello@vapor.codes"), + business: .init("Qutheory LLC."), + firstName: .init("Tanner"), + lastName: .init("Nelson"), address: nil, phone: nil, fax: nil, - website: "https://vapor.codes/", + website: .init("https://vapor.codes/"), taxID: nil, info: nil ), @@ -192,10 +192,10 @@ final class InvoiceTests: XCTestCase { "{\"tax_calculated_after_discount\":true,\"invoice_date\":\"\(now.iso8601)\"," + "\"logo_url\":\"https:\\/\\/vapor.codes\\/dist\\/e032390c38279fbdf18ebf0e763eb44f.png\"," + "\"note\":\"Thanks for your donation!\",\"billing_info\":[],\"allow_partial_payment\":false,\"template_id\":\"PayPal system template\"," + - "\"minimum_amount_due\":{\"currency\":\"USD\",\"value\":\"1.00\"},\"merchant_info\":{\"email\":\"hello@vapor.codes\"" + + "\"minimum_amount_due\":{\"currency\":\"USD\",\"value\":\"1\"},\"merchant_info\":{\"email\":\"hello@vapor.codes\"" + ",\"last_name\":\"Nelson\",\"website\":\"https:\\/\\/vapor.codes\\/\",\"business_name\":\"Qutheory LLC.\",\"first_name\":\"Tanner\"}," + "\"cc_info\":[{\"email\":\"collective@vapor.codes\"},{\"email\":\"donator@example.com\"}],\"payment_term\":{" + - "\"due_date\":\"\(self.dueStr)\",\"term_type\":\"DUE_ON_RECEIPT\"},\"custom\":{\"amount\":{\"currency\":\"USD\",\"value\":\"10.00\"}}," + + "\"due_date\":\"\(self.dueStr)\",\"term_type\":\"DUE_ON_RECEIPT\"},\"custom\":{\"amount\":{\"currency\":\"USD\",\"value\":\"10\"}}," + "\"allow_tip\":true,\"reference\":\"PO number\",\"tax_inclusive\":true,\"merchant_memo\":\"Open Collective donation\"}" print(json.count) var index = 0 @@ -221,7 +221,7 @@ final class InvoiceTests: XCTestCase { "allow_partial_payment": false, "template_id": "PayPal system template", "minimum_amount_due": { - "value": "1.00", + "value": "1", "currency": "USD" }, "merchant_info": { @@ -245,7 +245,7 @@ final class InvoiceTests: XCTestCase { }, "custom": { "amount": { - "value": "10.00", + "value": "10", "currency": "USD" } }, @@ -328,14 +328,14 @@ final class InvoiceTests: XCTestCase { try XCTAssertEqual(invoice, Invoice( number: nil, merchant: MerchantInfo( - email: "hello@vapor.codes", - business: "Qutheory LLC.", - firstName: "Tanner", - lastName: "Nelson", + email: .init("hello@vapor.codes"), + business: .init("Qutheory LLC."), + firstName: .init("Tanner"), + lastName: .init("Nelson"), address: nil, phone: nil, fax: nil, - website: "https://vapor.codes/", + website: .init("https://vapor.codes/"), taxID: nil, info: nil ), @@ -362,7 +362,7 @@ final class InvoiceTests: XCTestCase { )) } - static var allTests: [(String, (InvoiceTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (InvoiceTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/ItemReason.swift b/Tests/ModelTests/ItemReason.swift index 8dba7cd6..7a36e71e 100644 --- a/Tests/ModelTests/ItemReason.swift +++ b/Tests/ModelTests/ItemReason.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class ItemReasonTests: XCTestCase { +public final class ItemReasonTests: XCTestCase { struct IT: Codable { let reason: Item.Reason } @@ -53,7 +53,7 @@ final class ItemReasonTests: XCTestCase { try XCTAssertEqual(decoder.decode(IT.self, from: reacurringCancelled).reason, .reacurringCancelled) } - static var allTests: [(String, (ItemReasonTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ItemReasonTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/KeyValueTests.swift b/Tests/ModelTests/KeyValueTests.swift index 70685c8c..217ce2d4 100644 --- a/Tests/ModelTests/KeyValueTests.swift +++ b/Tests/ModelTests/KeyValueTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class KeyValueTests: XCTestCase { +public final class KeyValueTests: XCTestCase { func testInit()throws { let strd = KeyValue(key: "key0", value: "value0") XCTAssertEqual(strd.key, "key0") @@ -60,7 +60,7 @@ final class KeyValueTests: XCTestCase { try XCTAssertEqual(nv, decoder.decode(NameValue.self, from: njson)) } - static var allTests: [(String, (KeyValueTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (KeyValueTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/LegalAgreementTests.swift b/Tests/ModelTests/LegalAgreementTests/LegalAgreementTests.swift similarity index 88% rename from Tests/ModelTests/LegalAgreementTests.swift rename to Tests/ModelTests/LegalAgreementTests/LegalAgreementTests.swift index fbd87fea..ee0021bc 100644 --- a/Tests/ModelTests/LegalAgreementTests.swift +++ b/Tests/ModelTests/LegalAgreementTests/LegalAgreementTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class LegalAgreementTests: XCTestCase { +public final class LegalAgreementTests: XCTestCase { func testInit()throws { let agreement = LegalAgreement(accepted: false, type: .userAgreement) @@ -31,7 +31,7 @@ final class LegalAgreementTests: XCTestCase { ) } - static var allTests: [(String, (LegalAgreementTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (LegalAgreementTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/LegalAgreementTypeTests.swift b/Tests/ModelTests/LegalAgreementTests/LegalAgreementTypeTests.swift similarity index 92% rename from Tests/ModelTests/LegalAgreementTypeTests.swift rename to Tests/ModelTests/LegalAgreementTests/LegalAgreementTypeTests.swift index 529b3957..0a9b1521 100644 --- a/Tests/ModelTests/LegalAgreementTypeTests.swift +++ b/Tests/ModelTests/LegalAgreementTests/LegalAgreementTypeTests.swift @@ -3,7 +3,7 @@ import XCTest typealias AgreementType = LegalAgreement.AgreementType -final class LegalAgreementTypeTests: XCTestCase { +public final class LegalAgreementTypeTests: XCTestCase { struct Agreement: Codable { let type: AgreementType } @@ -44,7 +44,7 @@ final class LegalAgreementTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Agreement.self, from: financialAuthority).type, .financialAuthority) } - static var allTests: [(String, (LegalAgreementTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (LegalAgreementTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/LinkDescriptionTests.swift b/Tests/ModelTests/LinkDescriptionTests.swift index b4755df3..b06d0926 100644 --- a/Tests/ModelTests/LinkDescriptionTests.swift +++ b/Tests/ModelTests/LinkDescriptionTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class LinkDescriptionTests: XCTestCase { +public final class LinkDescriptionTests: XCTestCase { func testInit()throws { let link = LinkDescription(href: "https://choosealicense.com/licenses/mit/", rel: "license", method: .GET) @@ -35,7 +35,7 @@ final class LinkDescriptionTests: XCTestCase { ) } - static var allTests: [(String, (LinkDescriptionTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (LinkDescriptionTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/MerchantAccountTests.swift b/Tests/ModelTests/MerchantTests/MerchantAccountTests.swift similarity index 97% rename from Tests/ModelTests/MerchantAccountTests.swift rename to Tests/ModelTests/MerchantTests/MerchantAccountTests.swift index 7f733773..fe70dff7 100644 --- a/Tests/ModelTests/MerchantAccountTests.swift +++ b/Tests/ModelTests/MerchantTests/MerchantAccountTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class MerchantAccountTests: XCTestCase { +public final class MerchantAccountTests: XCTestCase { func testInit()throws { let account = try MerchantAccount( owner: nil, @@ -140,7 +140,7 @@ final class MerchantAccountTests: XCTestCase { try XCTAssertEqual(account, decoder.decode(MerchantAccount.self, from: json)) } - static var allTests: [(String, (MerchantAccountTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (MerchantAccountTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/MerchantTests/MerchantInfoTests.swift b/Tests/ModelTests/MerchantTests/MerchantInfoTests.swift new file mode 100644 index 00000000..0903b574 --- /dev/null +++ b/Tests/ModelTests/MerchantTests/MerchantInfoTests.swift @@ -0,0 +1,125 @@ +import XCTest +import Failable +@testable import PayPal + +public final class MerchantInfoTests: XCTestCase { + func testInit()throws { + let info = try MerchantInfo( + email: .init("merchant@exmaple.com"), + business: .init("Merchants & Co."), + firstName: .init("Richard"), + lastName: .init("Smith"), + address: nil, + phone: nil, + fax: nil, + website: .init("https://merchantsand.co"), + taxID: .init("9987-425-1698"), + info: .init("Open 24/7") + ) + + XCTAssertNil(info.address) + XCTAssertNil(info.phone) + XCTAssertNil(info.fax) + XCTAssertEqual(info.email.value, "merchant@exmaple.com") + XCTAssertEqual(info.business.value, "Merchants & Co.") + XCTAssertEqual(info.firstName.value, "Richard") + XCTAssertEqual(info.lastName.value, "Smith") + XCTAssertEqual(info.website.value, "https://merchantsand.co") + XCTAssertEqual(info.taxID.value, "9987-425-1698") + XCTAssertEqual(info.info.value, "Open 24/7") + } + + func testValidations()throws { + var info = try MerchantInfo( + email: nil, business: nil, firstName: nil, lastName: nil, address: nil, phone: nil, fax: nil, website: nil, + taxID: nil, info: nil + ) + + try XCTAssertThrowsError(info.email <~ String(repeating: "e", count: 261)) + try XCTAssertThrowsError(info.business <~ String(repeating: "b", count: 101)) + try XCTAssertThrowsError(info.firstName <~ String(repeating: "f", count: 257)) + try XCTAssertThrowsError(info.lastName <~ String(repeating: "l", count: 257)) + try XCTAssertThrowsError(info.website <~ String(repeating: "w", count: 2049)) + try XCTAssertThrowsError(info.taxID <~ String(repeating: "t", count: 101)) + try XCTAssertThrowsError(info.info <~ String(repeating: "i", count: 41)) + + try info.email <~ String(repeating: "e", count: 260) + try info.business <~ String(repeating: "b", count: 100) + try info.firstName <~ String(repeating: "f", count: 256) + try info.lastName <~ String(repeating: "l", count: 256) + try info.website <~ String(repeating: "w", count: 2048) + try info.taxID <~ String(repeating: "t", count: 100) + try info.info <~ String(repeating: "i", count: 40) + } + + func testEncoding()throws { + let encoder = JSONEncoder() + let info = try MerchantInfo( + email: .init("merchant@exmaple.com"), + business: .init("Merchants & Co."), + firstName: .init("Richard"), + lastName: .init("Smith"), + address: nil, + phone: nil, + fax: nil, + website: .init("https://merchantsand.co"), + taxID: .init("9987-425-1698"), + info: .init("Open 24/7") + ) + let generated = try String(data: encoder.encode(info), encoding: .utf8)! + let json = + "{\"tax_id\":\"9987-425-1698\",\"website\":\"https:\\/\\/merchantsand.co\",\"business_name\":\"Merchants & Co.\"," + + "\"last_name\":\"Smith\",\"email\":\"merchant@exmaple.com\",\"additional_info\":\"Open 24\\/7\",\"first_name\":\"Richard\"}" + + var index = 0 + for (jsonChar, genChar) in zip(json, generated) { + if jsonChar == genChar { index += 1; continue } + XCTAssertEqual(jsonChar, genChar, "values don't match. Failure starts at index \(index)") + break + } + + XCTAssertEqual(generated, json) + } + + func testDecoding()throws { + let decoder = JSONDecoder() + + let json = """ + { + "email": "merchant@exmaple.com", + "business_name": "Merchants & Co.", + "first_name": "Richard", + "last_name": "Smith", + "website": "https://merchantsand.co", + "tax_id": "9987-425-1698", + "additional_info": "Open 24/7" + } + """.data(using: .utf8)! + let info = try MerchantInfo( + email: .init("merchant@exmaple.com"), + business: .init("Merchants & Co."), + firstName: .init("Richard"), + lastName: .init("Smith"), + address: nil, + phone: nil, + fax: nil, + website: .init("https://merchantsand.co"), + taxID: .init("9987-425-1698"), + info: .init("Open 24/7") + ) + + try XCTAssertEqual(info, decoder.decode(MerchantInfo.self, from: json)) + } + + public static var allTests: [(String, (MerchantInfoTests) -> ()throws -> ())] = [ + ("testInit", testInit), + ("testValidations", testValidations), + ("testEncoding", testEncoding), + ("testDecoding", testDecoding) + ] +} + + + + + diff --git a/Tests/ModelTests/MerchantPreferancesTests.swift b/Tests/ModelTests/MerchantTests/MerchantPreferancesTests.swift similarity index 93% rename from Tests/ModelTests/MerchantPreferancesTests.swift rename to Tests/ModelTests/MerchantTests/MerchantPreferancesTests.swift index 0b8fdb25..36c2ac09 100644 --- a/Tests/ModelTests/MerchantPreferancesTests.swift +++ b/Tests/ModelTests/MerchantTests/MerchantPreferancesTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class MerchantPreferancesTests: XCTestCase { +public final class MerchantPreferancesTests: XCTestCase { func testInit()throws { let preferances = MerchantPreferances( setupFee: CurrencyCodeAmount(currency: .usd, value: 0), @@ -40,7 +40,7 @@ final class MerchantPreferancesTests: XCTestCase { let json = "{\"max_fail_attempts\":\"0\",\"char_set\":\"UTF-8\",\"initial_fail_amount_action\":\"CONTINUE\"," + "\"cancel_url\":\"https:\\/\\/example.com\\/agreements\",\"return_url\":\"https:\\/\\/example.com\\/agreements\\/latest\"," + - "\"setup_fee\":{\"value\":\"0.00\",\"currency_code\":\"USD\"},\"auto_bill_amount\":\"YES\"}" + "\"setup_fee\":{\"value\":\"0\",\"currency_code\":\"USD\"},\"auto_bill_amount\":\"YES\"}" // JSON is 434 characters long. var index = 0 @@ -82,7 +82,7 @@ final class MerchantPreferancesTests: XCTestCase { try XCTAssertEqual(preferances, decoder.decode(MerchantPreferances.self, from: json)) } - static var allTests: [(String, (MerchantPreferancesTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (MerchantPreferancesTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/MessagePosterTests.swift b/Tests/ModelTests/MessageTests/MessagePosterTests.swift similarity index 91% rename from Tests/ModelTests/MessagePosterTests.swift rename to Tests/ModelTests/MessageTests/MessagePosterTests.swift index 8d2819d7..9e45205a 100644 --- a/Tests/ModelTests/MessagePosterTests.swift +++ b/Tests/ModelTests/MessageTests/MessagePosterTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class MessagePosterTests: XCTestCase { +public final class MessagePosterTests: XCTestCase { struct Wall: Codable { let poster: Message.Poster } @@ -42,7 +42,7 @@ final class MessagePosterTests: XCTestCase { try XCTAssertEqual(decoder.decode(Wall.self, from: seller).poster, .seller) } - static var allTests: [(String, (MessagePosterTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (MessagePosterTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/MessageTests.swift b/Tests/ModelTests/MessageTests/MessageTests.swift similarity index 95% rename from Tests/ModelTests/MessageTests.swift rename to Tests/ModelTests/MessageTests/MessageTests.swift index d733aa3a..8fa549b1 100644 --- a/Tests/ModelTests/MessageTests.swift +++ b/Tests/ModelTests/MessageTests/MessageTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class MessageTests: XCTestCase { +public final class MessageTests: XCTestCase { func testInit()throws { let message = try Message(content: .init("A developer walks into a foo bar and orders a fizz buzz")) @@ -61,7 +61,7 @@ final class MessageTests: XCTestCase { XCTAssertEqual(message.content, "🦄") } - static var allTests: [(String, (MessageTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (MessageTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidation", testValidation), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/MetadataTests.swift b/Tests/ModelTests/MetadataTests.swift index ea463c9c..eccdb13e 100644 --- a/Tests/ModelTests/MetadataTests.swift +++ b/Tests/ModelTests/MetadataTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class MetadataTests: XCTestCase { +public final class MetadataTests: XCTestCase { func testDecoding()throws { let decoder = JSONDecoder() @@ -38,7 +38,7 @@ final class MetadataTests: XCTestCase { XCTAssertEqual(metadata.payerView, "https://vapor.com/invoices/2620EF1C-4F5D-4479-8657-4DA21B56D023") } - static var allTests: [(String, (MetadataTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (MetadataTests) -> ()throws -> ())] = [ ("testDecoding", testDecoding) ] } diff --git a/Tests/ModelTests/MethodTests.swift b/Tests/ModelTests/MethodTests.swift index 3e1b5bc8..e1a9f8df 100644 --- a/Tests/ModelTests/MethodTests.swift +++ b/Tests/ModelTests/MethodTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class MethodTests: XCTestCase { +public final class MethodTests: XCTestCase { struct Request: Codable { let method: PayPal.Method } @@ -49,7 +49,7 @@ final class MethodTests: XCTestCase { try XCTAssertEqual(decoder.decode(Request.self, from: delete).method, .DELETE) } - static var allTests: [(String, (MethodTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (MethodTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/MoneyRangeTests.swift b/Tests/ModelTests/MoneyTests/MoneyRangeTests.swift similarity index 87% rename from Tests/ModelTests/MoneyRangeTests.swift rename to Tests/ModelTests/MoneyTests/MoneyRangeTests.swift index 5446ea24..eb51b81c 100644 --- a/Tests/ModelTests/MoneyRangeTests.swift +++ b/Tests/ModelTests/MoneyTests/MoneyRangeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class MoneyRangeTests: XCTestCase { +public final class MoneyRangeTests: XCTestCase { func testInit()throws { let range0 = MoneyRange(min: CurrencyCodeAmount(currency: .usd, value: 12.25), max: CurrencyCodeAmount(currency: .usd, value: 50.00)) XCTAssertEqual(range0.minimum, CurrencyCodeAmount(currency: .usd, value: 12.25)) @@ -17,7 +17,7 @@ final class MoneyRangeTests: XCTestCase { let range = MoneyRange(min: CurrencyCodeAmount(currency: .usd, value: 12.25), max: CurrencyCodeAmount(currency: .usd, value: 50.00)) let generated = try String(data: encoder.encode(range), encoding: .utf8) let json = - "{\"minimum_amount\":{\"value\":\"12.25\",\"currency_code\":\"USD\"},\"maximum_amount\":{\"value\":\"50.00\",\"currency_code\":\"USD\"}}" + "{\"minimum_amount\":{\"value\":\"12.25\",\"currency_code\":\"USD\"},\"maximum_amount\":{\"value\":\"50\",\"currency_code\":\"USD\"}}" XCTAssertEqual(json, generated) } @@ -27,7 +27,7 @@ final class MoneyRangeTests: XCTestCase { let json = """ { "maximum_amount": { - "value": "50.00", + "value": "50", "currency_code": "USD" }, "minimum_amount": { @@ -41,7 +41,7 @@ final class MoneyRangeTests: XCTestCase { try XCTAssertEqual(range, decoder.decode(MoneyRange.self, from: json)) } - static var allTests: [(String, (MoneyRangeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (MoneyRangeTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/MoneyTests.swift b/Tests/ModelTests/MoneyTests/MoneyTests.swift similarity index 87% rename from Tests/ModelTests/MoneyTests.swift rename to Tests/ModelTests/MoneyTests/MoneyTests.swift index 444f4f75..a259cfca 100644 --- a/Tests/ModelTests/MoneyTests.swift +++ b/Tests/ModelTests/MoneyTests/MoneyTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class MoneyTests: XCTestCase { +public final class MoneyTests: XCTestCase { func testInit()throws { let amount = CurrencyAmount(currency: .aud, value: 10.25) @@ -19,9 +19,9 @@ final class MoneyTests: XCTestCase { XCTAssertEqual(usd, "{\"value\":\"12.25\",\"currency_code\":\"USD\"}") XCTAssertEqual(xxx, "{\"value\":\"0\",\"currency_code\":\"XXX\"}") - XCTAssertEqual(eur, "{\"value\":\"4.50\",\"currency_code\":\"EUR\"}") + XCTAssertEqual(eur, "{\"value\":\"4.5\",\"currency_code\":\"EUR\"}") - XCTAssertEqual(usdO, "{\"value\":\"0.00\",\"currency_code\":\"USD\"}") + XCTAssertEqual(usdO, "{\"value\":\"0\",\"currency_code\":\"USD\"}") } func testDecoding()throws { @@ -50,7 +50,7 @@ final class MoneyTests: XCTestCase { try XCTAssertEqual(CurrencyCodeAmount(currency: .usd, value: 33), decoder.decode(CurrencyCodeAmount.self, from: valueParse)) } - static var allTests: [(String, (MoneyTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (MoneyTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/NameTests.swift b/Tests/ModelTests/NameTests.swift index afee9d83..df64f3e9 100644 --- a/Tests/ModelTests/NameTests.swift +++ b/Tests/ModelTests/NameTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class NameTests: XCTestCase { +public final class NameTests: XCTestCase { func testInit()throws { let name = try Name( prefix: .init("Sir"), given: .init("Walter"), surname: .init("Scott"), middle: nil, suffix: .init("auth."), @@ -103,7 +103,7 @@ final class NameTests: XCTestCase { try XCTAssertThrowsError(decoder.decode(Name.self, from: prefix)) } - static var allTests: [(String, (NameTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (NameTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/NewAgreementTests.swift b/Tests/ModelTests/NewAgreementTests.swift index 2061a288..a5d5705d 100644 --- a/Tests/ModelTests/NewAgreementTests.swift +++ b/Tests/ModelTests/NewAgreementTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class NewAgreementTests: XCTestCase { +public final class NewAgreementTests: XCTestCase { let now = Date() func testInit()throws { @@ -136,7 +136,7 @@ final class NewAgreementTests: XCTestCase { try XCTAssertEqual(agreement, decoder.decode(NewAgreement.self, from: json)) } - static var allTests: [(String, (NewAgreementTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (NewAgreementTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/NotificationOptionTests.swift b/Tests/ModelTests/NotificationOptionTests.swift index f2bb962a..d5643c42 100644 --- a/Tests/ModelTests/NotificationOptionTests.swift +++ b/Tests/ModelTests/NotificationOptionTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class NotificationOptionTests: XCTestCase { +public final class NotificationOptionTests: XCTestCase { func testInit()throws { let null = NotificationOptions() XCTAssertEqual(null.suppressWelcome, nil) @@ -39,7 +39,7 @@ final class NotificationOptionTests: XCTestCase { try XCTAssertEqual(decoder.decode(NotificationOptions.self, from: json), options) } - static var allTests: [(String, (NotificationOptionTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (NotificationOptionTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/OfferTests.swift b/Tests/ModelTests/OfferTests/OfferTests.swift similarity index 93% rename from Tests/ModelTests/OfferTests.swift rename to Tests/ModelTests/OfferTests/OfferTests.swift index d6339efa..cedbc262 100644 --- a/Tests/ModelTests/OfferTests.swift +++ b/Tests/ModelTests/OfferTests/OfferTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class OfferTests: XCTestCase { +public final class OfferTests: XCTestCase { func testInit()throws { let offer = Offer(buyerAmount: CurrencyCodeAmount(currency: .usd, value: 10.99), sellerAmount: CurrencyCodeAmount(currency: .usd, value: 10.99), type: .refund) @@ -41,7 +41,7 @@ final class OfferTests: XCTestCase { try XCTAssertEqual(decoder.decode(Offer.self, from: json), offer) } - static var allTests: [(String, (OfferTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OfferTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/OfferTypeTests.swift b/Tests/ModelTests/OfferTests/OfferTypeTests.swift similarity index 92% rename from Tests/ModelTests/OfferTypeTests.swift rename to Tests/ModelTests/OfferTests/OfferTypeTests.swift index 9988140d..6ba2a3ab 100644 --- a/Tests/ModelTests/OfferTypeTests.swift +++ b/Tests/ModelTests/OfferTests/OfferTypeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class OfferTypeTests: XCTestCase { +public final class OfferTypeTests: XCTestCase { struct Off: Codable { let type: Offer.OfferType } @@ -43,7 +43,7 @@ final class OfferTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Off.self, from: refund).type, .refund) } - static var allTests: [(String, (OfferTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OfferTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/OperationTests.swift b/Tests/ModelTests/OperationTests.swift index 7bfad6aa..56fd97aa 100644 --- a/Tests/ModelTests/OperationTests.swift +++ b/Tests/ModelTests/OperationTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class OperationTests: XCTestCase { +public final class OperationTests: XCTestCase { struct Patch: Codable { let operation: PayPal.Operation } @@ -46,7 +46,7 @@ final class OperationTests: XCTestCase { try XCTAssertEqual(decoder.decode(Patch.self, from: test).operation, .test) } - static var allTests: [(String, (OperationTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OperationTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/OrderIntentTests.swift b/Tests/ModelTests/OrderTests/OrderIntentTests.swift similarity index 92% rename from Tests/ModelTests/OrderIntentTests.swift rename to Tests/ModelTests/OrderTests/OrderIntentTests.swift index 8b69cda3..cab353f5 100644 --- a/Tests/ModelTests/OrderIntentTests.swift +++ b/Tests/ModelTests/OrderTests/OrderIntentTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Intent = Order.Intent -final class OrderIntentTests: XCTestCase { +public final class OrderIntentTests: XCTestCase { private struct Or: Codable { let intent: Intent } @@ -45,7 +45,7 @@ final class OrderIntentTests: XCTestCase { try XCTAssertEqual(decoder.decode(Or.self, from: authorize).intent, .authorize) } - static var allTests: [(String, (OrderIntentTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OrderIntentTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/OrderItemTests.swift b/Tests/ModelTests/OrderTests/OrderItemTests.swift similarity index 97% rename from Tests/ModelTests/OrderItemTests.swift rename to Tests/ModelTests/OrderTests/OrderItemTests.swift index dde550d7..b93063ce 100644 --- a/Tests/ModelTests/OrderItemTests.swift +++ b/Tests/ModelTests/OrderTests/OrderItemTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class OrderItemTests: XCTestCase { +public final class OrderItemTests: XCTestCase { func testInit()throws { let item = try Order.Item( sku: .init("FAE11644-19BC-4643-8215-004C829B19C1"), @@ -161,7 +161,7 @@ final class OrderItemTests: XCTestCase { )) } - static var allTests: [(String, (OrderItemTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OrderItemTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/OrderMetadataTests.swift b/Tests/ModelTests/OrderTests/OrderMetadataTests.swift similarity index 88% rename from Tests/ModelTests/OrderMetadataTests.swift rename to Tests/ModelTests/OrderTests/OrderMetadataTests.swift index 4c1055b1..193590fb 100644 --- a/Tests/ModelTests/OrderMetadataTests.swift +++ b/Tests/ModelTests/OrderTests/OrderMetadataTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class OrderMetadataTests: XCTestCase { +public final class OrderMetadataTests: XCTestCase { func testInit()throws { let metadata = Order.Metadata(data: ["name": "value"]) XCTAssertEqual(metadata.data, ["name": "value"]) @@ -32,7 +32,7 @@ final class OrderMetadataTests: XCTestCase { try XCTAssertEqual(decoder.decode(Order.Metadata.self, from: json), Order.Metadata(data: ["name": "value"])) } - static var allTests: [(String, (OrderMetadataTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OrderMetadataTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/OrderPayerInfoTests.swift b/Tests/ModelTests/OrderTests/OrderPayerInfoTests.swift similarity index 94% rename from Tests/ModelTests/OrderPayerInfoTests.swift rename to Tests/ModelTests/OrderTests/OrderPayerInfoTests.swift index ec42fdae..fe1c884d 100644 --- a/Tests/ModelTests/OrderPayerInfoTests.swift +++ b/Tests/ModelTests/OrderTests/OrderPayerInfoTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class OrderPayerInfoTests: XCTestCase { +public final class OrderPayerInfoTests: XCTestCase { let birthdate = Date() func testInit()throws { @@ -26,7 +26,7 @@ final class OrderPayerInfoTests: XCTestCase { XCTAssertNil(info.payer) XCTAssertEqual(info.email.value, "email@example.com") - XCTAssertEqual(info.birthdate, self.birthdate) + XCTAssertEqual(info.birthdate, TimelessDate(self.birthdate)) XCTAssertEqual(info.tax.value, "85323EC0-A9114") XCTAssertEqual(info.taxType, .cpf) XCTAssertEqual(info.country, .unitedStates) @@ -121,7 +121,7 @@ final class OrderPayerInfoTests: XCTestCase { XCTAssertEqual(info.country, .unitedStates) XCTAssertEqual(info.taxType, .cpf) XCTAssertEqual(info.tax.value, "85323EC0-A9114") - XCTAssertEqual(info.birthdate, Date(timeIntervalSince1970: 1_536_364_800)) + XCTAssertEqual(info.birthdate, TimelessDate(Date(timeIntervalSince1970: 1_536_364_800))) XCTAssertEqual(info.email.value, "email@example.com") XCTAssertEqual(info.billing, Address( recipientName: nil, defaultAddress: nil, line1: "Plum Fairy Ln.", line2: nil, city: "Ginger Planes", state: .le, @@ -129,7 +129,7 @@ final class OrderPayerInfoTests: XCTestCase { )) } - static var allTests: [(String, (OrderPayerInfoTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OrderPayerInfoTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/OrderPayerMethodTests.swift b/Tests/ModelTests/OrderTests/OrderPayerMethodTests.swift similarity index 92% rename from Tests/ModelTests/OrderPayerMethodTests.swift rename to Tests/ModelTests/OrderTests/OrderPayerMethodTests.swift index 299fdf0b..9673765a 100644 --- a/Tests/ModelTests/OrderPayerMethodTests.swift +++ b/Tests/ModelTests/OrderTests/OrderPayerMethodTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Method = Order.Payer.Method -final class OrderPaymentMethodTests: XCTestCase { +public final class OrderPaymentMethodTests: XCTestCase { private struct Pay: Codable { let method: Method } @@ -48,7 +48,7 @@ final class OrderPaymentMethodTests: XCTestCase { try XCTAssertEqual(decoder.decode(Pay.self, from: carrier).method, .carrier) } - static var allTests: [(String, (OrderPaymentMethodTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OrderPaymentMethodTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/OrderPayerStatusTests.swift b/Tests/ModelTests/OrderTests/OrderPayerStatusTests.swift similarity index 91% rename from Tests/ModelTests/OrderPayerStatusTests.swift rename to Tests/ModelTests/OrderTests/OrderPayerStatusTests.swift index a0f50ee9..643dcfdb 100644 --- a/Tests/ModelTests/OrderPayerStatusTests.swift +++ b/Tests/ModelTests/OrderTests/OrderPayerStatusTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Status = Order.Payer.Status -final class OrderPaymentStatusTests: XCTestCase { +public final class OrderPaymentStatusTests: XCTestCase { private struct Pay: Codable { let status: Status } @@ -44,7 +44,7 @@ final class OrderPaymentStatusTests: XCTestCase { try XCTAssertEqual(decoder.decode(Pay.self, from: unverified).status, .unverified) } - static var allTests: [(String, (OrderPaymentStatusTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OrderPaymentStatusTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/OrderPayerTaxTests.swift b/Tests/ModelTests/OrderTests/OrderPayerTaxTests.swift similarity index 90% rename from Tests/ModelTests/OrderPayerTaxTests.swift rename to Tests/ModelTests/OrderTests/OrderPayerTaxTests.swift index c64274fe..de0b38fe 100644 --- a/Tests/ModelTests/OrderPayerTaxTests.swift +++ b/Tests/ModelTests/OrderTests/OrderPayerTaxTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Tax = Order.Payer.TaxType -final class OrderPayerTaxTests: XCTestCase { +public final class OrderPayerTaxTests: XCTestCase { private struct Pay: Codable { let tax: Tax } @@ -44,7 +44,7 @@ final class OrderPayerTaxTests: XCTestCase { try XCTAssertEqual(decoder.decode(Pay.self, from: cnpj).tax, .cnpj) } - static var allTests: [(String, (OrderPayerTaxTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OrderPayerTaxTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/OrderPayerTests.swift b/Tests/ModelTests/OrderTests/OrderPayerTests.swift similarity index 92% rename from Tests/ModelTests/OrderPayerTests.swift rename to Tests/ModelTests/OrderTests/OrderPayerTests.swift index 973141e6..b2a6d0d8 100644 --- a/Tests/ModelTests/OrderPayerTests.swift +++ b/Tests/ModelTests/OrderTests/OrderPayerTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class OrderPayerTests: XCTestCase { +public final class OrderPayerTests: XCTestCase { func testInit()throws { let payer = Order.Payer(method: .creditCard, funding: [], info: .init(email: nil, birthdate: nil, tax: nil, taxType: nil, country: nil, billing: nil)) @@ -37,7 +37,7 @@ final class OrderPayerTests: XCTestCase { XCTAssertEqual(payer.info, .init(email: nil, birthdate: nil, tax: nil, taxType: nil, country: nil, billing: nil)) } - static var allTests: [(String, (OrderPayerTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OrderPayerTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/OrderPaymentDetailTests.swift b/Tests/ModelTests/OrderTests/OrderPaymentDetailTests.swift similarity index 78% rename from Tests/ModelTests/OrderPaymentDetailTests.swift rename to Tests/ModelTests/OrderTests/OrderPaymentDetailTests.swift index da7bf7a5..137f8686 100644 --- a/Tests/ModelTests/OrderPaymentDetailTests.swift +++ b/Tests/ModelTests/OrderTests/OrderPaymentDetailTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class OrderPaymentDetailTests: XCTestCase { +public final class OrderPaymentDetailTests: XCTestCase { func testDecoding()throws { let json = """ { @@ -15,7 +15,7 @@ final class OrderPaymentDetailTests: XCTestCase { XCTAssertEqual(details.disbursement, .instant) } - static var allTests: [(String, (OrderPaymentDetailTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OrderPaymentDetailTests) -> ()throws -> ())] = [ ("testDecoding", testDecoding) ] } diff --git a/Tests/ModelTests/OrderPaymentDisbursementTests.swift b/Tests/ModelTests/OrderTests/OrderPaymentDisbursementTests.swift similarity index 90% rename from Tests/ModelTests/OrderPaymentDisbursementTests.swift rename to Tests/ModelTests/OrderTests/OrderPaymentDisbursementTests.swift index bf3d3266..bbd60a37 100644 --- a/Tests/ModelTests/OrderPaymentDisbursementTests.swift +++ b/Tests/ModelTests/OrderTests/OrderPaymentDisbursementTests.swift @@ -3,7 +3,7 @@ import XCTest typealias Disbursement = Order.DisbursementMode -final class OrderPaymentDisbursementTests: XCTestCase { +public final class OrderPaymentDisbursementTests: XCTestCase { struct Or: Codable { let disbursement: Disbursement } @@ -44,7 +44,7 @@ final class OrderPaymentDisbursementTests: XCTestCase { try XCTAssertEqual(decoder.decode(Or.self, from: delayed).disbursement, .delayed) } - static var allTests: [(String, (OrderPaymentDisbursementTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OrderPaymentDisbursementTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/OrderPaymentRequestTests.swift b/Tests/ModelTests/OrderTests/OrderPaymentRequestTests.swift similarity index 89% rename from Tests/ModelTests/OrderPaymentRequestTests.swift rename to Tests/ModelTests/OrderTests/OrderPaymentRequestTests.swift index 47520b92..cb262ab6 100644 --- a/Tests/ModelTests/OrderPaymentRequestTests.swift +++ b/Tests/ModelTests/OrderTests/OrderPaymentRequestTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class OrderPaymentRequestTests: XCTestCase { +public final class OrderPaymentRequestTests: XCTestCase { func testInit()throws { let request = Order.PaymentRequest(disbursement: .instant, payer: Order.Payer(method: nil, funding: nil, info: nil)) @@ -31,7 +31,7 @@ final class OrderPaymentRequestTests: XCTestCase { try XCTAssertEqual(request, decoder.decode(Order.PaymentRequest.self, from: json)) } - static var allTests: [(String, (OrderPaymentRequestTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OrderPaymentRequestTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/OrderPaymentTests.swift b/Tests/ModelTests/OrderTests/OrderPaymentTests.swift similarity index 92% rename from Tests/ModelTests/OrderPaymentTests.swift rename to Tests/ModelTests/OrderTests/OrderPaymentTests.swift index 4637e90a..6d97ef4e 100644 --- a/Tests/ModelTests/OrderPaymentTests.swift +++ b/Tests/ModelTests/OrderTests/OrderPaymentTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class OrderPaymentTests: XCTestCase { +public final class OrderPaymentTests: XCTestCase { func testInit()throws { let payment = Order.Payment( captures: [Capture(amount: nil, transaction: nil)], @@ -40,7 +40,7 @@ final class OrderPaymentTests: XCTestCase { try XCTAssertEqual(decoder.decode(Order.Payment.self, from: json), Order.Payment(captures: [], refunds: [], sales: [], authorizations: [])) } - static var allTests: [(String, (OrderPaymentTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OrderPaymentTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/OrderRedirectsTests.swift b/Tests/ModelTests/OrderTests/OrderRedirectsTests.swift similarity index 91% rename from Tests/ModelTests/OrderRedirectsTests.swift rename to Tests/ModelTests/OrderTests/OrderRedirectsTests.swift index b5f92c75..8db2a292 100644 --- a/Tests/ModelTests/OrderRedirectsTests.swift +++ b/Tests/ModelTests/OrderTests/OrderRedirectsTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class RedirectsTests: XCTestCase { +public final class RedirectsTests: XCTestCase { func testInit()throws { let redirects = Redirects(return: "https://example.com/return", cancel: "https://example.com/cancel") @@ -30,7 +30,7 @@ final class RedirectsTests: XCTestCase { try XCTAssertEqual(Redirects(return: "https://example.com/return", cancel: "https://example.com/cancel"), decoder.decode(Redirects.self, from: json)) } - static var allTests: [(String, (RedirectsTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (RedirectsTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/OrderStatusTests.swift b/Tests/ModelTests/OrderTests/OrderStatusTests.swift similarity index 92% rename from Tests/ModelTests/OrderStatusTests.swift rename to Tests/ModelTests/OrderTests/OrderStatusTests.swift index 00b15d4c..35c4ef8e 100644 --- a/Tests/ModelTests/OrderStatusTests.swift +++ b/Tests/ModelTests/OrderTests/OrderStatusTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Status = Order.Status -final class OrderStatusTests: XCTestCase { +public final class OrderStatusTests: XCTestCase { private struct Or: Codable { let status: Status } @@ -46,7 +46,7 @@ final class OrderStatusTests: XCTestCase { try XCTAssertEqual(decoder.decode(Or.self, from: failed).status, .failed) } - static var allTests: [(String, (OrderStatusTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OrderStatusTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/OrderTests.swift b/Tests/ModelTests/OrderTests/OrderTests.swift similarity index 88% rename from Tests/ModelTests/OrderTests.swift rename to Tests/ModelTests/OrderTests/OrderTests.swift index fe9b7201..4455a68d 100644 --- a/Tests/ModelTests/OrderTests.swift +++ b/Tests/ModelTests/OrderTests/OrderTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class OrderTests: XCTestCase { +public final class OrderTests: XCTestCase { func testInit()throws { let order = Order( intent: .sale, @@ -36,7 +36,9 @@ final class OrderTests: XCTestCase { let generated = try String(data: encoder.encode(order), encoding: .utf8)! let json = - "{\"intent\":\"SALE\",\"redirect_urls\":{},\"payment_details\":{},\"purchase_units\":[],\"metadata\":{\"supplementary_data\":[]},\"application_context\":{},\"gross_total_amount\":{\"currency\":\"USD\",\"value\":\"150.78\"}}" + "{\"intent\":\"SALE\",\"redirect_urls\":{},\"payment_details\":{},\"purchase_units\":[]," + + "\"metadata\":{\"supplementary_data\":[]},\"application_context\":{}," + + "\"gross_total_amount\":{\"currency\":\"USD\",\"value\":\"150.78\"}}" var index = 0 for (jsonChar, genChar) in zip(json, generated) { @@ -66,8 +68,8 @@ final class OrderTests: XCTestCase { "purchase_units": [], "intent": "SALE", "status": "CREATED", - "create_time": "2018-09-20T13:17:47+0000", - "update_time": "2018-09-20T13:18:03+0000", + "create_time": "2018-09-20T13:17:47.000Z", + "update_time": "2018-09-20T13:18:03.000Z", "links": [] } """.data(using: .utf8)! @@ -80,14 +82,14 @@ final class OrderTests: XCTestCase { XCTAssertEqual(order.metadata, Order.Metadata(data: [:])) XCTAssertEqual(order.redirects, Redirects(return: nil, cancel: nil)) XCTAssertEqual(order.status, .created) - XCTAssertEqual(order.created, Date(iso8601: "2018-09-20T13:17:47+0000")) - XCTAssertEqual(order.updated, Date(iso8601: "2018-09-20T13:18:03+0000")) + XCTAssertEqual(order.created, Date(iso8601: "2018-09-20T13:17:47.000Z")) + XCTAssertEqual(order.updated, Date(iso8601: "2018-09-20T13:18:03.000Z")) XCTAssertEqual(order.links, []) XCTAssertEqual(order.total, CurrencyAmount(currency: .usd, value: 150.78)) XCTAssertEqual(order.context, AppContext()) } - static var allTests: [(String, (OrderTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OrderTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/OrderUnitReasonTests.swift b/Tests/ModelTests/OrderTests/OrderUnitReasonTests.swift similarity index 93% rename from Tests/ModelTests/OrderUnitReasonTests.swift rename to Tests/ModelTests/OrderTests/OrderUnitReasonTests.swift index 6c06054a..8d37f67c 100644 --- a/Tests/ModelTests/OrderUnitReasonTests.swift +++ b/Tests/ModelTests/OrderTests/OrderUnitReasonTests.swift @@ -3,7 +3,7 @@ import XCTest typealias UnitReason = Order.Unit.Reason -final class OrderUnitReasonTests: XCTestCase { +public final class OrderUnitReasonTests: XCTestCase { struct Unit: Codable { let reason: UnitReason } @@ -50,7 +50,7 @@ final class OrderUnitReasonTests: XCTestCase { try XCTAssertEqual(decoder.decode(Unit.self, from: regulatory).reason, .regulatory) } - static var allTests: [(String, (OrderUnitReasonTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OrderUnitReasonTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/OrderUnitStatusTests.swift b/Tests/ModelTests/OrderTests/OrderUnitStatusTests.swift similarity index 92% rename from Tests/ModelTests/OrderUnitStatusTests.swift rename to Tests/ModelTests/OrderTests/OrderUnitStatusTests.swift index 1fd3d95e..3545b826 100644 --- a/Tests/ModelTests/OrderUnitStatusTests.swift +++ b/Tests/ModelTests/OrderTests/OrderUnitStatusTests.swift @@ -3,7 +3,7 @@ import XCTest typealias UnitStat = Order.Unit.Status -final class OrderUnitStatusTests: XCTestCase { +public final class OrderUnitStatusTests: XCTestCase { struct Unit: Codable { let status: UnitStat } @@ -47,7 +47,7 @@ final class OrderUnitStatusTests: XCTestCase { try XCTAssertEqual(decoder.decode(Unit.self, from: captured).status, .captured) } - static var allTests: [(String, (OrderUnitStatusTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OrderUnitStatusTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/OrderUnitTests.swift b/Tests/ModelTests/OrderTests/OrderUnitTests.swift similarity index 98% rename from Tests/ModelTests/OrderUnitTests.swift rename to Tests/ModelTests/OrderTests/OrderUnitTests.swift index 427eb779..975b5d6f 100644 --- a/Tests/ModelTests/OrderUnitTests.swift +++ b/Tests/ModelTests/OrderTests/OrderUnitTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class OrderUnitTests: XCTestCase { +public final class OrderUnitTests: XCTestCase { func testInit()throws { let payee = Payee(email: "payee@example.com", merchant: "AEDCA9E0-5442-41EF-978A-DEE6DF7DFDA8", metadata: nil) let address = Address( @@ -135,7 +135,7 @@ final class OrderUnitTests: XCTestCase { "\"invoice_number\":\"B5382984-3B90-4BC4-9F7A-6A6AFA61AC25\",\"metadata\":{\"supplementary_data\":[]},\"payee\":{}," + "\"reference_id\":\"C1C099F2-D7E7-4E19-BBBF-98DD11EA911A\",\"payment_linked_group\":1,\"shipping_address\":{\"country_code\":\"US\"," + "\"line1\":\"1 Infinate Loop\",\"city\":\"Cupertino\",\"postal_code\":\"94024\"},\"custom\":\"C2B9FBFB-B97D-46E4-8553-522C6A25A2FC\"," + - "\"items\":[],\"shipping_method\":\"USPSParcel\",\"partner_fee_details\":{\"amount\":{\"currency\":\"USD\",\"value\":\"2.50\"}," + + "\"items\":[],\"shipping_method\":\"USPSParcel\",\"partner_fee_details\":{\"amount\":{\"currency\":\"USD\",\"value\":\"2.5\"}," + "\"receiver\":{}}}" var index = 0 @@ -194,7 +194,7 @@ final class OrderUnitTests: XCTestCase { "shipping_method": "USPSParcel", "partner_fee_details": { "amount": { - "value": "2.50", + "value": "2.5", "currency": "USD" }, "receiver": {} @@ -224,7 +224,7 @@ final class OrderUnitTests: XCTestCase { } - static var allTests: [(String, (OrderUnitTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OrderUnitTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/OutcomeCodeTests.swift b/Tests/ModelTests/OutcomeCodeTests.swift index 64cd661f..17f1eb1d 100644 --- a/Tests/ModelTests/OutcomeCodeTests.swift +++ b/Tests/ModelTests/OutcomeCodeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class OutcomeCodeTests: XCTestCase { +public final class OutcomeCodeTests: XCTestCase { struct Out: Codable { let code: CustomerDispute.Outcome.Code } @@ -46,7 +46,7 @@ final class OutcomeCodeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Out.self, from: cancelled).code, .cancelled) } - static var allTests: [(String, (OutcomeCodeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OutcomeCodeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/OverrideChargeTests.swift b/Tests/ModelTests/OverrideChargeTests.swift index ebd86b8a..a8d79758 100644 --- a/Tests/ModelTests/OverrideChargeTests.swift +++ b/Tests/ModelTests/OverrideChargeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class OverrideChargeTests: XCTestCase { +public final class OverrideChargeTests: XCTestCase { func testInit()throws { let id = UUID().uuidString let charge = OverrideCharge(id: id, amount: CurrencyCodeAmount(currency: .usd, value: 314.15)) @@ -58,7 +58,7 @@ final class OverrideChargeTests: XCTestCase { ) } - static var allTests: [(String, (OverrideChargeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (OverrideChargeTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/ParticipantTests.swift b/Tests/ModelTests/ParticipantTests.swift index 7825829d..1ace508f 100644 --- a/Tests/ModelTests/ParticipantTests.swift +++ b/Tests/ModelTests/ParticipantTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class InvoiceParticipantTests: XCTestCase { +public final class InvoiceParticipantTests: XCTestCase { func testInit()throws { let participant = try Invoice.Participant(email: .init("participant@example.com")) @@ -38,7 +38,7 @@ final class InvoiceParticipantTests: XCTestCase { try XCTAssertEqual(Invoice.Participant(email: .init("participant@example.com")), decoder.decode(Invoice.Participant.self, from: json)) } - static var allTests: [(String, (InvoiceParticipantTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (InvoiceParticipantTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PartnerFeeTests.swift b/Tests/ModelTests/PartnerTests/PartnerFeeTests.swift similarity index 91% rename from Tests/ModelTests/PartnerFeeTests.swift rename to Tests/ModelTests/PartnerTests/PartnerFeeTests.swift index f7026c1a..67385094 100644 --- a/Tests/ModelTests/PartnerFeeTests.swift +++ b/Tests/ModelTests/PartnerTests/PartnerFeeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class PartnerFeeTests: XCTestCase { +public final class PartnerFeeTests: XCTestCase { func testInit()throws { let amount = CurrencyAmount(currency: .usd, value: 54.96) let payee = Payee(email: nil, merchant: nil, metadata: nil) @@ -41,7 +41,7 @@ final class PartnerFeeTests: XCTestCase { try XCTAssertEqual(fee, decoder.decode(PartnerFee.self, from: json)) } - static var allTests: [(String, (PartnerFeeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PartnerFeeTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/PartnerOptionsTests.swift b/Tests/ModelTests/PartnerTests/PartnerOptionsTests.swift similarity index 91% rename from Tests/ModelTests/PartnerOptionsTests.swift rename to Tests/ModelTests/PartnerTests/PartnerOptionsTests.swift index 97cb389a..561c1b5e 100644 --- a/Tests/ModelTests/PartnerOptionsTests.swift +++ b/Tests/ModelTests/PartnerTests/PartnerOptionsTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class PartnerOptionsTests: XCTestCase { +public final class PartnerOptionsTests: XCTestCase { func testInit()throws { let dict: PartnerOptions = ["key": "value", "key1": "value1"] XCTAssertEqual(dict["key"], "value") @@ -42,7 +42,7 @@ final class PartnerOptionsTests: XCTestCase { try XCTAssertEqual(options, decoder.decode(PartnerOptions.self, from: mit)) } - static var allTests: [(String, (PartnerOptionsTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PartnerOptionsTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/PatchTests.swift b/Tests/ModelTests/PatchTests.swift index 0ae0355a..ca2eeeb0 100644 --- a/Tests/ModelTests/PatchTests.swift +++ b/Tests/ModelTests/PatchTests.swift @@ -2,7 +2,7 @@ import XCTest import JSON @testable import PayPal -final class PatchTests: XCTestCase { +public final class PatchTests: XCTestCase { func testInit()throws { let patchStr = try Patch(operation: .move, path: "/name", value: "Oskar Reteep", from: "/full_name") @@ -57,7 +57,7 @@ final class PatchTests: XCTestCase { try XCTAssertEqual(patchArr, decoder.decode(Patch.self, from: arrJson)) } - static var allTests: [(String, (PatchTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PatchTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/PayeeMetadataTests.swift b/Tests/ModelTests/PayTests/PayeeMetadataTests.swift similarity index 95% rename from Tests/ModelTests/PayeeMetadataTests.swift rename to Tests/ModelTests/PayTests/PayeeMetadataTests.swift index 3465f6e9..5c30d335 100644 --- a/Tests/ModelTests/PayeeMetadataTests.swift +++ b/Tests/ModelTests/PayTests/PayeeMetadataTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class PayeeMetadataTests: XCTestCase { +public final class PayeeMetadataTests: XCTestCase { func testInit()throws { let metadata = try Payee.Metadata( email: .init("payee@example.com"), @@ -69,7 +69,7 @@ final class PayeeMetadataTests: XCTestCase { try XCTAssertEqual(metadata, decoder.decode(Payee.Metadata.self, from: json)) } - static var allTests: [(String, (PayeeMetadataTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PayeeMetadataTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PayeeTests.swift b/Tests/ModelTests/PayTests/PayeeTests.swift similarity index 94% rename from Tests/ModelTests/PayeeTests.swift rename to Tests/ModelTests/PayTests/PayeeTests.swift index 043e49fd..48bd85cf 100644 --- a/Tests/ModelTests/PayeeTests.swift +++ b/Tests/ModelTests/PayTests/PayeeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class PayeeTests: XCTestCase { +public final class PayeeTests: XCTestCase { func testInit()throws { let metadata = try Payee.Metadata( email: .init("payee@example.com"), @@ -56,7 +56,7 @@ final class PayeeTests: XCTestCase { try XCTAssertEqual(metadata, decoder.decode(Payee.Metadata.self, from: json)) } - static var allTests: [(String, (PayeeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PayeeTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/PayerInfoTests.swift b/Tests/ModelTests/PayTests/PayerInfoTests.swift similarity index 96% rename from Tests/ModelTests/PayerInfoTests.swift rename to Tests/ModelTests/PayTests/PayerInfoTests.swift index dac9b26e..7dba55e3 100644 --- a/Tests/ModelTests/PayerInfoTests.swift +++ b/Tests/ModelTests/PayTests/PayerInfoTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class PayerInfoTests: XCTestCase { +public final class PayerInfoTests: XCTestCase { func testInit()throws { let info = PayerInfo( email: "payer@exmaple.com", @@ -112,7 +112,7 @@ final class PayerInfoTests: XCTestCase { try XCTAssertEqual(info, decoder.decode(PayerInfo.self, from: json)) } - static var allTests: [(String, (PayerInfoTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PayerInfoTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/PayerTests.swift b/Tests/ModelTests/PayTests/PayerTests.swift similarity index 98% rename from Tests/ModelTests/PayerTests.swift rename to Tests/ModelTests/PayTests/PayerTests.swift index fe7fb5b7..ed97cff8 100644 --- a/Tests/ModelTests/PayerTests.swift +++ b/Tests/ModelTests/PayTests/PayerTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class PayerTests: XCTestCase { +public final class PayerTests: XCTestCase { func testInit()throws { let payer = try Payer( method: .paypal, @@ -193,7 +193,7 @@ final class PayerTests: XCTestCase { try XCTAssertEqual(payer, decoder.decode(Payer.self, from: json)) } - static var allTests: [(String, (PayerTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PayerTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/PaymentDetailMethodTests.swift b/Tests/ModelTests/PaymentTests/PaymentDetailMethodTests.swift similarity index 93% rename from Tests/ModelTests/PaymentDetailMethodTests.swift rename to Tests/ModelTests/PaymentTests/PaymentDetailMethodTests.swift index 5e3382a5..fe0a3e78 100644 --- a/Tests/ModelTests/PaymentDetailMethodTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentDetailMethodTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class PaymentDetailMethodTests: XCTestCase { +public final class PaymentDetailMethodTests: XCTestCase { struct Detail: Codable { let method: PaymentDetail.Method } @@ -48,7 +48,7 @@ final class PaymentDetailMethodTests: XCTestCase { try XCTAssertEqual(decoder.decode(Detail.self, from: debitCard).method, .debitCard) } - static var allTests: [(String, (PaymentDetailMethodTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentDetailMethodTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentDetailTests.swift b/Tests/ModelTests/PaymentTests/PaymentDetailTests.swift similarity index 85% rename from Tests/ModelTests/PaymentDetailTests.swift rename to Tests/ModelTests/PaymentTests/PaymentDetailTests.swift index fc3e879e..fa1f99dd 100644 --- a/Tests/ModelTests/PaymentDetailTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentDetailTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class PaymentDetailTests: XCTestCase { +public final class PaymentDetailTests: XCTestCase { let now = Date() func testInit()throws { @@ -18,7 +18,7 @@ final class PaymentDetailTests: XCTestCase { let detail = PaymentDetail(date: self.now, method: .cash, note: "Hello World", amount: CurrencyAmount(currency: .usd, value: 4.50)) let generated = try String(data: encoder.encode(detail), encoding: .utf8)! let json = - "{\"amount\":{\"currency\":\"USD\",\"value\":\"4.50\"},\"method\":\"CASH\",\"note\":\"Hello World\",\"date\":\"\(self.now.iso8601)\"}" + "{\"amount\":{\"currency\":\"USD\",\"value\":\"4.5\"},\"method\":\"CASH\",\"note\":\"Hello World\",\"date\":\"\(self.now.iso8601)\"}" var index = 0 for (jsonChar, genChar) in zip(json, generated) { @@ -37,7 +37,7 @@ final class PaymentDetailTests: XCTestCase { { "amount": { "currency": "USD", - "value": "4.50" + "value": "4.5" }, "note": "Hello World", "method": "CASH", @@ -48,7 +48,7 @@ final class PaymentDetailTests: XCTestCase { try XCTAssertEqual(detail, decoder.decode(PaymentDetail.self, from: json)) } - static var allTests: [(String, (PaymentDetailTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentDetailTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/PaymentDetailTypeTests.swift b/Tests/ModelTests/PaymentTests/PaymentDetailTypeTests.swift similarity index 91% rename from Tests/ModelTests/PaymentDetailTypeTests.swift rename to Tests/ModelTests/PaymentTests/PaymentDetailTypeTests.swift index f497d651..63f7c86a 100644 --- a/Tests/ModelTests/PaymentDetailTypeTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentDetailTypeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class PaymentDetailTypeTests: XCTestCase { +public final class PaymentDetailTypeTests: XCTestCase { struct Detail: Codable { let type: PaymentDetail.DetailType } @@ -42,7 +42,7 @@ final class PaymentDetailTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Detail.self, from: external).type, .external) } - static var allTests: [(String, (PaymentDetailTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentDetailTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentExecutorTests.swift b/Tests/ModelTests/PaymentTests/PaymentExecutorTests.swift similarity index 91% rename from Tests/ModelTests/PaymentExecutorTests.swift rename to Tests/ModelTests/PaymentTests/PaymentExecutorTests.swift index c360ef44..22ccbc82 100644 --- a/Tests/ModelTests/PaymentExecutorTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentExecutorTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class PaymentExecutorTests: XCTestCase { +public final class PaymentExecutorTests: XCTestCase { func testInit()throws { let executor = Payment.Executor(payer: "payer", amounts: []) @@ -38,7 +38,7 @@ final class PaymentExecutorTests: XCTestCase { try XCTAssertEqual(executor, decoder.decode(Payment.Executor.self, from: json)) } - static var allTests: [(String, (PaymentExecutorTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentExecutorTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/PaymentHoldTests.swift b/Tests/ModelTests/PaymentTests/PaymentHoldTests.swift similarity index 91% rename from Tests/ModelTests/PaymentHoldTests.swift rename to Tests/ModelTests/PaymentTests/PaymentHoldTests.swift index 7364c5f2..f540b085 100644 --- a/Tests/ModelTests/PaymentHoldTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentHoldTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Hold = Payment.HoldReason -final class PaymentHoldTests: XCTestCase { +public final class PaymentHoldTests: XCTestCase { private struct Pay: Codable { let hold: Hold } @@ -44,7 +44,7 @@ final class PaymentHoldTests: XCTestCase { try XCTAssertEqual(decoder.decode(Pay.self, from: shipping).hold, .shipping) } - static var allTests: [(String, (PaymentHoldTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentHoldTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentIntentTests.swift b/Tests/ModelTests/PaymentTests/PaymentIntentTests.swift similarity index 91% rename from Tests/ModelTests/PaymentIntentTests.swift rename to Tests/ModelTests/PaymentTests/PaymentIntentTests.swift index 789f5086..9412c574 100644 --- a/Tests/ModelTests/PaymentIntentTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentIntentTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Intent = Payment.Intent -final class PaymentIntentTests: XCTestCase { +public final class PaymentIntentTests: XCTestCase { private struct Pay: Codable { let intent: Intent } @@ -45,7 +45,7 @@ final class PaymentIntentTests: XCTestCase { try XCTAssertEqual(decoder.decode(Pay.self, from: sale).intent, .sale) } - static var allTests: [(String, (PaymentIntentTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentIntentTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentItemListTests.swift b/Tests/ModelTests/PaymentTests/PaymentItemListTests.swift similarity index 95% rename from Tests/ModelTests/PaymentItemListTests.swift rename to Tests/ModelTests/PaymentTests/PaymentItemListTests.swift index 96876eab..ec9c3ce5 100644 --- a/Tests/ModelTests/PaymentItemListTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentItemListTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class PaymentItemListTests: XCTestCase { +public final class PaymentItemListTests: XCTestCase { let address = Address( recipientName: nil, defaultAddress: nil, @@ -88,7 +88,7 @@ final class PaymentItemListTests: XCTestCase { try XCTAssertThrowsError(decoder.decode(Payment.ItemList.self, from: phone)) } - static var allTests: [(String, (PaymentItemListTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentItemListTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentItemTests.swift b/Tests/ModelTests/PaymentTests/PaymentItemTests.swift similarity index 96% rename from Tests/ModelTests/PaymentItemTests.swift rename to Tests/ModelTests/PaymentTests/PaymentItemTests.swift index 14d5b098..24b1e600 100644 --- a/Tests/ModelTests/PaymentItemTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentItemTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class PaymentItemTests: XCTestCase { +public final class PaymentItemTests: XCTestCase { func testInit()throws { let item = try Payment.Item( quantity: .init(3), price: .init(2.50), currency: .usd, sku: .init("123456"), name: .init("Foo"), @@ -85,7 +85,7 @@ final class PaymentItemTests: XCTestCase { try XCTAssertEqual(item, decoder.decode(Payment.Item.self, from: json)) } - static var allTests: [(String, (PaymentItemTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentItemTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentListTests.swift b/Tests/ModelTests/PaymentTests/PaymentListTests.swift similarity index 84% rename from Tests/ModelTests/PaymentListTests.swift rename to Tests/ModelTests/PaymentTests/PaymentListTests.swift index 86b46edc..7be897a9 100644 --- a/Tests/ModelTests/PaymentListTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentListTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class PaymentListTests: XCTestCase { +public final class PaymentListTests: XCTestCase { func testDecoding()throws { let decoder = JSONDecoder() @@ -25,7 +25,7 @@ final class PaymentListTests: XCTestCase { XCTAssertEqual(list.count.value, 20) } - static var allTests: [(String, (PaymentListTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentListTests) -> ()throws -> ())] = [ ("testDecoding", testDecoding) ] } diff --git a/Tests/ModelTests/PaymentMethodTests.swift b/Tests/ModelTests/PaymentTests/PaymentMethodTests.swift similarity index 91% rename from Tests/ModelTests/PaymentMethodTests.swift rename to Tests/ModelTests/PaymentTests/PaymentMethodTests.swift index e7bb05bd..5d9f4ee2 100644 --- a/Tests/ModelTests/PaymentMethodTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentMethodTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class PaymentMethodTests: XCTestCase { +public final class PaymentMethodTests: XCTestCase { struct Pay: Codable { let method: PaymentMethod } @@ -42,7 +42,7 @@ final class PaymentMethodTests: XCTestCase { try XCTAssertEqual(decoder.decode(Pay.self, from: paypal).method, .paypal) } - static var allTests: [(String, (PaymentMethodTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentMethodTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentOptionsMethodTests.swift b/Tests/ModelTests/PaymentTests/PaymentOptionsMethodTests.swift similarity index 91% rename from Tests/ModelTests/PaymentOptionsMethodTests.swift rename to Tests/ModelTests/PaymentTests/PaymentOptionsMethodTests.swift index cc85cef6..682f8df9 100644 --- a/Tests/ModelTests/PaymentOptionsMethodTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentOptionsMethodTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Method = Payment.Options.Method -final class PaymentOptionsMethodTests: XCTestCase { +public final class PaymentOptionsMethodTests: XCTestCase { private struct Options: Codable { let method: Method } @@ -45,7 +45,7 @@ final class PaymentOptionsMethodTests: XCTestCase { try XCTAssertEqual(decoder.decode(Options.self, from: unrestricted).method, .unrestricted) } - static var allTests: [(String, (PaymentOptionsMethodTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentOptionsMethodTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentProtectionTests.swift b/Tests/ModelTests/PaymentTests/PaymentProtectionTests.swift similarity index 92% rename from Tests/ModelTests/PaymentProtectionTests.swift rename to Tests/ModelTests/PaymentTests/PaymentProtectionTests.swift index f14522b0..c5f0d434 100644 --- a/Tests/ModelTests/PaymentProtectionTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentProtectionTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Protection = RelatedResource.Protection -final class PaymentProtectionTests: XCTestCase { +public final class PaymentProtectionTests: XCTestCase { private struct Sale: Codable { let protection: Protection } @@ -45,7 +45,7 @@ final class PaymentProtectionTests: XCTestCase { try XCTAssertEqual(decoder.decode(Sale.self, from: eligible).protection, .eligible) } - static var allTests: [(String, (PaymentProtectionTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentProtectionTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentProtectionTypeTests.swift b/Tests/ModelTests/PaymentTests/PaymentProtectionTypeTests.swift similarity index 92% rename from Tests/ModelTests/PaymentProtectionTypeTests.swift rename to Tests/ModelTests/PaymentTests/PaymentProtectionTypeTests.swift index 8e624866..9c6d34a3 100644 --- a/Tests/ModelTests/PaymentProtectionTypeTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentProtectionTypeTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Type = RelatedResource.ProtectionType -final class PaymentProtectionTypeTests: XCTestCase { +public final class PaymentProtectionTypeTests: XCTestCase { private struct Protection: Codable { let type: Type } @@ -45,7 +45,7 @@ final class PaymentProtectionTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Protection.self, from: itemNotReceived).type, .itemNotReceived) } - static var allTests: [(String, (PaymentProtectionTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentProtectionTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentReceivingPreferencesTests.swift b/Tests/ModelTests/PaymentTests/PaymentReceivingPreferencesTests.swift similarity index 96% rename from Tests/ModelTests/PaymentReceivingPreferencesTests.swift rename to Tests/ModelTests/PaymentTests/PaymentReceivingPreferencesTests.swift index 9483ca0c..1860b579 100644 --- a/Tests/ModelTests/PaymentReceivingPreferencesTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentReceivingPreferencesTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class PaymentReceivingPreferencesTests: XCTestCase { +public final class PaymentReceivingPreferencesTests: XCTestCase { func testInit()throws { let preference = try PaymentReceivingPreferences( blockUnconfirmedUSAddress: true, @@ -100,7 +100,7 @@ final class PaymentReceivingPreferencesTests: XCTestCase { try XCTAssertEqual(preference, decoder.decode(PaymentReceivingPreferences.self, from: json)) } - static var allTests: [(String, (PaymentReceivingPreferencesTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentReceivingPreferencesTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentRefundResultTests.swift b/Tests/ModelTests/PaymentTests/PaymentRefundResultTests.swift similarity index 90% rename from Tests/ModelTests/PaymentRefundResultTests.swift rename to Tests/ModelTests/PaymentTests/PaymentRefundResultTests.swift index 47e9ab9b..fd3ba225 100644 --- a/Tests/ModelTests/PaymentRefundResultTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentRefundResultTests.swift @@ -2,15 +2,15 @@ import XCTest import Failable @testable import PayPal -final class PaymentRefundResultTests: XCTestCase { +public final class PaymentRefundResultTests: XCTestCase { func testDecoding()throws { let decoder = JSONDecoder() let json = """ { "id": "5CY176817C379973E", - "create_time": "2018-08-15T17:11:32Z", - "update_time": "2018-08-15T17:11:32Z", + "create_time": "2018-08-15T17:11:32.000Z", + "update_time": "2018-08-15T17:11:32.000Z", "state": "completed", "reason": "I don't like it", "amount": { @@ -42,8 +42,8 @@ final class PaymentRefundResultTests: XCTestCase { var refund = try decoder.decode(Payment.RefundResult.self, from: json) XCTAssertEqual(refund.id, "5CY176817C379973E") - XCTAssertEqual(refund.created, Date(iso8601: "2018-08-15T17:11:32Z")) - XCTAssertEqual(refund.updated, Date(iso8601: "2018-08-15T17:11:32Z")) + XCTAssertEqual(refund.created, Date(iso8601: "2018-08-15T17:11:32.000Z")) + XCTAssertEqual(refund.updated, Date(iso8601: "2018-08-15T17:11:32.000Z")) XCTAssertEqual(refund.state, .completed) XCTAssertEqual(refund.reason, "I don't like it") XCTAssertEqual(refund.sale, "2MU78835H4515710F") @@ -69,7 +69,7 @@ final class PaymentRefundResultTests: XCTestCase { XCTAssertEqual(refund.custom.value, String(repeating: "c", count: 127)) } - static var allTests: [(String, (PaymentRefundResultTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentRefundResultTests) -> ()throws -> ())] = [ ("testDecoding", testDecoding) ] } diff --git a/Tests/ModelTests/PaymentRefundStateTests.swift b/Tests/ModelTests/PaymentTests/PaymentRefundStateTests.swift similarity index 91% rename from Tests/ModelTests/PaymentRefundStateTests.swift rename to Tests/ModelTests/PaymentTests/PaymentRefundStateTests.swift index d5dd8bb1..1e1c82b2 100644 --- a/Tests/ModelTests/PaymentRefundStateTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentRefundStateTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias State = Payment.RefundResult.State -final class PaymentRefundStateTests: XCTestCase { +public final class PaymentRefundStateTests: XCTestCase { private struct Result: Codable { let state: State } @@ -46,7 +46,7 @@ final class PaymentRefundStateTests: XCTestCase { try XCTAssertEqual(decoder.decode(Result.self, from: failed).state, .failed) } - static var allTests: [(String, (PaymentRefundStateTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentRefundStateTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentRefundTests.swift b/Tests/ModelTests/PaymentTests/PaymentRefundTests.swift similarity index 96% rename from Tests/ModelTests/PaymentRefundTests.swift rename to Tests/ModelTests/PaymentTests/PaymentRefundTests.swift index e8f03cc2..a85c904f 100644 --- a/Tests/ModelTests/PaymentRefundTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentRefundTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class PaymentRefundTests: XCTestCase { +public final class PaymentRefundTests: XCTestCase { func testInit()throws { let refund = try Payment.Refund( amount: DetailedAmount(currency: .usd, total: 10.00, details: nil), @@ -82,7 +82,7 @@ final class PaymentRefundTests: XCTestCase { try XCTAssertEqual(refund, decoder.decode(Payment.Refund.self, from: json)) } - static var allTests: [(String, (PaymentRefundTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentRefundTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentSaleModeTests.swift b/Tests/ModelTests/PaymentTests/PaymentSaleModeTests.swift similarity index 92% rename from Tests/ModelTests/PaymentSaleModeTests.swift rename to Tests/ModelTests/PaymentTests/PaymentSaleModeTests.swift index 6f202546..3935c420 100644 --- a/Tests/ModelTests/PaymentSaleModeTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentSaleModeTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Mode = RelatedResource.Sale.PaymentMode -final class PaymentSaleModeTests: XCTestCase { +public final class PaymentSaleModeTests: XCTestCase { private struct Sale: Codable { let mode: Mode } @@ -46,7 +46,7 @@ final class PaymentSaleModeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Sale.self, from: echeck).mode, .echeck) } - static var allTests: [(String, (PaymentSaleModeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentSaleModeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentSaleReasonTests.swift b/Tests/ModelTests/PaymentTests/PaymentSaleReasonTests.swift similarity index 94% rename from Tests/ModelTests/PaymentSaleReasonTests.swift rename to Tests/ModelTests/PaymentTests/PaymentSaleReasonTests.swift index e9e85fad..63fd22bb 100644 --- a/Tests/ModelTests/PaymentSaleReasonTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentSaleReasonTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Reason = RelatedResource.Sale.Reason -final class PaymentSaleReasonTests: XCTestCase { +public final class PaymentSaleReasonTests: XCTestCase { private struct Sale: Codable { let reason: Reason } @@ -57,7 +57,7 @@ final class PaymentSaleReasonTests: XCTestCase { try XCTAssertEqual(decoder.decode(Sale.self, from: refund).reason, .refund) } - static var allTests: [(String, (PaymentSaleReasonTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentSaleReasonTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentSaleStateTests.swift b/Tests/ModelTests/PaymentTests/PaymentSaleStateTests.swift similarity index 92% rename from Tests/ModelTests/PaymentSaleStateTests.swift rename to Tests/ModelTests/PaymentTests/PaymentSaleStateTests.swift index 1af667cb..1fed16d6 100644 --- a/Tests/ModelTests/PaymentSaleStateTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentSaleStateTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias State = RelatedResource.Sale.State -final class PaymentSaleStateTests: XCTestCase { +public final class PaymentSaleStateTests: XCTestCase { private struct Sale: Codable { let state: State } @@ -47,7 +47,7 @@ final class PaymentSaleStateTests: XCTestCase { try XCTAssertEqual(decoder.decode(Sale.self, from: refunded).state, .refunded) } - static var allTests: [(String, (PaymentSaleStateTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentSaleStateTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentStateTests.swift b/Tests/ModelTests/PaymentTests/PaymentStateTests.swift similarity index 91% rename from Tests/ModelTests/PaymentStateTests.swift rename to Tests/ModelTests/PaymentTests/PaymentStateTests.swift index dc3782a3..58d0a4a3 100644 --- a/Tests/ModelTests/PaymentStateTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentStateTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias State = Payment.State -final class PaymentStateTests: XCTestCase { +public final class PaymentStateTests: XCTestCase { private struct Pay: Codable { let state: State } @@ -45,7 +45,7 @@ final class PaymentStateTests: XCTestCase { try XCTAssertEqual(decoder.decode(Pay.self, from: created).state, .created) } - static var allTests: [(String, (PaymentStateTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentStateTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentSummaryTests.swift b/Tests/ModelTests/PaymentTests/PaymentSummaryTests.swift similarity index 83% rename from Tests/ModelTests/PaymentSummaryTests.swift rename to Tests/ModelTests/PaymentTests/PaymentSummaryTests.swift index 894edd86..54ca7f26 100644 --- a/Tests/ModelTests/PaymentSummaryTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentSummaryTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class PaymentSummaryTests: XCTestCase { +public final class PaymentSummaryTests: XCTestCase { func testDecoding()throws { let decoder = JSONDecoder() @@ -24,7 +24,7 @@ final class PaymentSummaryTests: XCTestCase { XCTAssertEqual(summary.other, CurrencyAmount(currency: .usd, value: 8.43)) } - static var allTests: [(String, (PaymentSummaryTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentSummaryTests) -> ()throws -> ())] = [ ("testDecoding", testDecoding) ] } diff --git a/Tests/ModelTests/PaymentTermTypeTests.swift b/Tests/ModelTests/PaymentTests/PaymentTermTypeTests.swift similarity index 93% rename from Tests/ModelTests/PaymentTermTypeTests.swift rename to Tests/ModelTests/PaymentTests/PaymentTermTypeTests.swift index df2f6ee0..e3831146 100644 --- a/Tests/ModelTests/PaymentTermTypeTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentTermTypeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class PaymentTermTypeTests: XCTestCase { +public final class PaymentTermTypeTests: XCTestCase { struct User: Codable { let role: Role } @@ -53,7 +53,7 @@ final class PaymentTermTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Term.self, from: noDueDate).type, .noDueDate) } - static var allTests: [(String, (PaymentTermTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentTermTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentTests.swift b/Tests/ModelTests/PaymentTests/PaymentTests.swift similarity index 97% rename from Tests/ModelTests/PaymentTests.swift rename to Tests/ModelTests/PaymentTests/PaymentTests.swift index 66f404f0..365407c7 100644 --- a/Tests/ModelTests/PaymentTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class PaymentTests: XCTestCase { +public final class PaymentTests: XCTestCase { func testInit()throws { let payment = try Payment( intent: .order, @@ -111,7 +111,7 @@ final class PaymentTests: XCTestCase { try XCTAssertThrowsError(decoder.decode(Payment.self, from: note)) } - static var allTests: [(String, (PaymentTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentTransactionTests.swift b/Tests/ModelTests/PaymentTests/PaymentTransactionTests.swift similarity index 97% rename from Tests/ModelTests/PaymentTransactionTests.swift rename to Tests/ModelTests/PaymentTests/PaymentTransactionTests.swift index 7489ef17..20b91dcf 100644 --- a/Tests/ModelTests/PaymentTransactionTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentTransactionTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class PaymentTransactionTests: XCTestCase { +public final class PaymentTransactionTests: XCTestCase { func testInit()throws { let transaction = try Payment.Transaction( amount: DetailedAmount(currency: .usd, total: 54.56, details: nil), @@ -133,7 +133,7 @@ final class PaymentTransactionTests: XCTestCase { XCTAssertEqual(transaction.itemList, .init(items: nil, address: nil, phoneNumber: nil)) } - static var allTests: [(String, (PaymentTransactionTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentTransactionTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentTransactionTypeTests.swift b/Tests/ModelTests/PaymentTests/PaymentTransactionTypeTests.swift similarity index 91% rename from Tests/ModelTests/PaymentTransactionTypeTests.swift rename to Tests/ModelTests/PaymentTests/PaymentTransactionTypeTests.swift index db4a8176..2ea5cae3 100644 --- a/Tests/ModelTests/PaymentTransactionTypeTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentTransactionTypeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class PaymentTransactionTypeTests: XCTestCase { +public final class PaymentTransactionTypeTests: XCTestCase { struct Pay: Codable { let type: PaymentType } @@ -47,7 +47,7 @@ final class PaymentTransactionTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Transaction.self, from: sale).type, .sale) } - static var allTests: [(String, (PaymentTransactionTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentTransactionTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PaymentTypeTests.swift b/Tests/ModelTests/PaymentTests/PaymentTypeTests.swift similarity index 91% rename from Tests/ModelTests/PaymentTypeTests.swift rename to Tests/ModelTests/PaymentTests/PaymentTypeTests.swift index bee24f50..20ada189 100644 --- a/Tests/ModelTests/PaymentTypeTests.swift +++ b/Tests/ModelTests/PaymentTests/PaymentTypeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class PaymentTypeTests: XCTestCase { +public final class PaymentTypeTests: XCTestCase { struct Pay: Codable { let type: PaymentType } @@ -42,7 +42,7 @@ final class PaymentTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Pay.self, from: regular).type, .regular) } - static var allTests: [(String, (PaymentTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PaymentTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PercentRangeTests.swift b/Tests/ModelTests/PercentRangeTests.swift index 37860f29..f147a3da 100644 --- a/Tests/ModelTests/PercentRangeTests.swift +++ b/Tests/ModelTests/PercentRangeTests.swift @@ -8,7 +8,7 @@ extension PercentRange { } } -final class PercentRangeTests: XCTestCase { +public final class PercentRangeTests: XCTestCase { func testInit()throws { let range = try PercentRange(min: .init(25), max: .init(54)) XCTAssertEqual(range.minimum.value, 25) @@ -69,7 +69,7 @@ final class PercentRangeTests: XCTestCase { try XCTAssertEqual(PercentRange(min: .init(25), max: .init(75)), decoder.decode(PercentRange.self, from: json)) } - static var allTests: [(String, (PercentRangeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PercentRangeTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PhoneNumberTests.swift b/Tests/ModelTests/PhoneTests/PhoneNumberTests.swift similarity index 93% rename from Tests/ModelTests/PhoneNumberTests.swift rename to Tests/ModelTests/PhoneTests/PhoneNumberTests.swift index a32bf958..e7979c07 100644 --- a/Tests/ModelTests/PhoneNumberTests.swift +++ b/Tests/ModelTests/PhoneTests/PhoneNumberTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class PhoneNumberTests: XCTestCase { +public final class PhoneNumberTests: XCTestCase { func testInit()throws { let number = try PhoneNumber(country: .init(1), number: .init(9963191901)) @@ -49,7 +49,7 @@ final class PhoneNumberTests: XCTestCase { try XCTAssertEqual(PhoneNumber(country: .init(1), number: .init(9963191901)), decoder.decode(PhoneNumber.self, from: json)) } - static var allTests: [(String, (PhoneNumberTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PhoneNumberTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/PhoneTypeTests.swift b/Tests/ModelTests/PhoneTests/PhoneTypeTests.swift similarity index 93% rename from Tests/ModelTests/PhoneTypeTests.swift rename to Tests/ModelTests/PhoneTests/PhoneTypeTests.swift index 57e76c85..92ccb49c 100644 --- a/Tests/ModelTests/PhoneTypeTests.swift +++ b/Tests/ModelTests/PhoneTests/PhoneTypeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class PhoneTypeTests: XCTestCase { +public final class PhoneTypeTests: XCTestCase { struct Phone: Codable { let type: PhoneType } @@ -48,7 +48,7 @@ final class PhoneTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Phone.self, from: work).type, .work) } - static var allTests: [(String, (PhoneTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (PhoneTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/TypedPhoneNumberTests.swift b/Tests/ModelTests/PhoneTests/TypedPhoneNumberTests.swift similarity index 94% rename from Tests/ModelTests/TypedPhoneNumberTests.swift rename to Tests/ModelTests/PhoneTests/TypedPhoneNumberTests.swift index 7f7ad927..fea651e1 100644 --- a/Tests/ModelTests/TypedPhoneNumberTests.swift +++ b/Tests/ModelTests/PhoneTests/TypedPhoneNumberTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class TypedPhoneNumberTests: XCTestCase { +public final class TypedPhoneNumberTests: XCTestCase { func testInit()throws { let number = try TypedPhoneNumber(type: .home, country: .init(1), nationalNumber: .init(5838954290), extension: .init(777)) @@ -54,7 +54,7 @@ final class TypedPhoneNumberTests: XCTestCase { ) } - static var allTests: [(String, (TypedPhoneNumberTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (TypedPhoneNumberTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/ProductTests/ProductGrantedPermission.swift b/Tests/ModelTests/ProductTests/ProductGrantedPermission.swift index d86f7ce6..6fb16bd5 100644 --- a/Tests/ModelTests/ProductTests/ProductGrantedPermission.swift +++ b/Tests/ModelTests/ProductTests/ProductGrantedPermission.swift @@ -3,7 +3,7 @@ import XCTest private typealias Permission = Product.GrantedPermission -final class ProductGrantedPermissionTests: XCTestCase { +public final class ProductGrantedPermissionTests: XCTestCase { private struct Product: Codable { let permission: Permission } @@ -75,7 +75,7 @@ final class ProductGrantedPermissionTests: XCTestCase { try XCTAssertEqual(decoder.decode(Product.self, from: accountManagementPermission).permission, .accountManagementPermission) } - static var allTests: [(String, (ProductGrantedPermissionTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ProductGrantedPermissionTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/ProductTests/ProductNameTests.swift b/Tests/ModelTests/ProductTests/ProductNameTests.swift index 800aedef..dcb0c6be 100644 --- a/Tests/ModelTests/ProductTests/ProductNameTests.swift +++ b/Tests/ModelTests/ProductTests/ProductNameTests.swift @@ -3,7 +3,7 @@ import XCTest private typealias Name = Product.Name -final class ProductNameTests: XCTestCase { +public final class ProductNameTests: XCTestCase { private struct Product: Codable { let name: Name } @@ -67,7 +67,7 @@ final class ProductNameTests: XCTestCase { try XCTAssertEqual(decoder.decode(Product.self, from: hostedSoleSolution).name, .hostedSoleSolution) } - static var allTests: [(String, (ProductNameTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ProductNameTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/ProductTests/ProductVettingStatusTests.swift b/Tests/ModelTests/ProductTests/ProductVettingStatusTests.swift index 5bcdd19d..1bcd9bd4 100644 --- a/Tests/ModelTests/ProductTests/ProductVettingStatusTests.swift +++ b/Tests/ModelTests/ProductTests/ProductVettingStatusTests.swift @@ -3,7 +3,7 @@ import XCTest private typealias Status = Product.VettingStatus -final class ProductVettingStatusTests: XCTestCase { +public final class ProductVettingStatusTests: XCTestCase { private struct Product: Codable { let status: Status } @@ -45,7 +45,7 @@ final class ProductVettingStatusTests: XCTestCase { try XCTAssertEqual(decoder.decode(Product.self, from: approved).status, .approved) } - static var allTests: [(String, (ProductVettingStatusTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ProductVettingStatusTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/QueryParameterTests.swift b/Tests/ModelTests/QueryParameterTests.swift index a19ee7ef..dd494f50 100644 --- a/Tests/ModelTests/QueryParameterTests.swift +++ b/Tests/ModelTests/QueryParameterTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class QueryParamaterTests: XCTestCase { +public final class QueryParamaterTests: XCTestCase { func testStringContainsCount() { let uno = "unodounotwounothree-fouruno" XCTAssert(uno.contains("uno", times: 4)) @@ -82,7 +82,7 @@ final class QueryParamaterTests: XCTestCase { } } - static var allTests: [(String, (QueryParamaterTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (QueryParamaterTests) -> ()throws -> ())] = [ ("testStringContainsCount", testStringContainsCount), ("testEncoding", testEncoding), ("testEncodingSpeed", testEncodingSpeed) diff --git a/Tests/ModelTests/RefundDetailTests.swift b/Tests/ModelTests/RefundTests/RefundDetailTests.swift similarity index 88% rename from Tests/ModelTests/RefundDetailTests.swift rename to Tests/ModelTests/RefundTests/RefundDetailTests.swift index fa848ffe..f6f05595 100644 --- a/Tests/ModelTests/RefundDetailTests.swift +++ b/Tests/ModelTests/RefundTests/RefundDetailTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class RefundDetailTests: XCTestCase { +public final class RefundDetailTests: XCTestCase { let now = Date() func testInit()throws { @@ -18,7 +18,7 @@ final class RefundDetailTests: XCTestCase { let encoder = JSONEncoder() let detail = RefundDetail(date: self.now, note: "Hello World", amount: CurrencyAmount(currency: .usd, value: 4.50)) let generated = try String(data: encoder.encode(detail), encoding: .utf8)! - let json = "{\"date\":\"\(self.now.iso8601)\",\"amount\":{\"currency\":\"USD\",\"value\":\"4.50\"},\"note\":\"Hello World\"}" + let json = "{\"date\":\"\(self.now.iso8601)\",\"amount\":{\"currency\":\"USD\",\"value\":\"4.5\"},\"note\":\"Hello World\"}" var index = 0 for (jsonChar, genChar) in zip(json, generated) { @@ -37,7 +37,7 @@ final class RefundDetailTests: XCTestCase { { "amount": { "currency": "USD", - "value": "4.50" + "value": "4.5" }, "note": "Hello World", "date": "\(self.now.iso8601)" @@ -47,7 +47,7 @@ final class RefundDetailTests: XCTestCase { try XCTAssertEqual(detail, decoder.decode(RefundDetail.self, from: json)) } - static var allTests: [(String, (RefundDetailTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (RefundDetailTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/RefundStatusTests.swift b/Tests/ModelTests/RefundTests/RefundStatusTests.swift similarity index 91% rename from Tests/ModelTests/RefundStatusTests.swift rename to Tests/ModelTests/RefundTests/RefundStatusTests.swift index 97c0483e..f768be24 100644 --- a/Tests/ModelTests/RefundStatusTests.swift +++ b/Tests/ModelTests/RefundTests/RefundStatusTests.swift @@ -3,7 +3,7 @@ import XCTest typealias RefStat = Refund.Status -final class RefundStatusTests: XCTestCase { +public final class RefundStatusTests: XCTestCase { struct Ref: Codable { let status: RefStat } @@ -45,7 +45,7 @@ final class RefundStatusTests: XCTestCase { try XCTAssertEqual(decoder.decode(Ref.self, from: pending).status, .pending) } - static var allTests: [(String, (RefundStatusTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (RefundStatusTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/RefundTests.swift b/Tests/ModelTests/RefundTests/RefundTests.swift similarity index 94% rename from Tests/ModelTests/RefundTests.swift rename to Tests/ModelTests/RefundTests/RefundTests.swift index 86ce49c0..4ded4219 100644 --- a/Tests/ModelTests/RefundTests.swift +++ b/Tests/ModelTests/RefundTests/RefundTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class RefundTests: XCTestCase { +public final class RefundTests: XCTestCase { func testInit()throws { let refund = Refund(amount: DetailedAmount(currency: .usd, total: 10.00, details: nil)) @@ -51,7 +51,7 @@ final class RefundTests: XCTestCase { XCTAssertEqual(refund.amount, DetailedAmount(currency: .usd, total: 10.00, details: nil)) } - static var allTests: [(String, (RefundTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (RefundTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/RelatedProcessorTests.swift b/Tests/ModelTests/RelatedResourceTests/RelatedProcessorTests.swift similarity index 84% rename from Tests/ModelTests/RelatedProcessorTests.swift rename to Tests/ModelTests/RelatedResourceTests/RelatedProcessorTests.swift index 5abd09c8..af23073e 100644 --- a/Tests/ModelTests/RelatedProcessorTests.swift +++ b/Tests/ModelTests/RelatedResourceTests/RelatedProcessorTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class RelatedProcessorTests: XCTestCase { +public final class RelatedProcessorTests: XCTestCase { func testDecoding()throws { let json = """ { @@ -24,7 +24,7 @@ final class RelatedProcessorTests: XCTestCase { XCTAssertEqual(processor.vpas, "3326") } - static var allTests: [(String, (RelatedProcessorTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (RelatedProcessorTests) -> ()throws -> ())] = [ ("testDecoding", testDecoding) ] } diff --git a/Tests/ModelTests/RelatedResourceAuthorizationTests.swift b/Tests/ModelTests/RelatedResourceTests/RelatedResourceAuthorizationTests.swift similarity index 96% rename from Tests/ModelTests/RelatedResourceAuthorizationTests.swift rename to Tests/ModelTests/RelatedResourceTests/RelatedResourceAuthorizationTests.swift index 13dd9d5d..028d7fbd 100644 --- a/Tests/ModelTests/RelatedResourceAuthorizationTests.swift +++ b/Tests/ModelTests/RelatedResourceTests/RelatedResourceAuthorizationTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class RelatedResourceAuthorizationTests: XCTestCase { +public final class RelatedResourceAuthorizationTests: XCTestCase { let now = Date() func testInit()throws { @@ -117,7 +117,7 @@ final class RelatedResourceAuthorizationTests: XCTestCase { XCTAssertEqual(auth.amount, DetailedAmount(currency: .usd, total: 42.31, details: nil)) } - static var allTests: [(String, (RelatedResourceAuthorizationTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (RelatedResourceAuthorizationTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/RelatedResourceCaptureTests.swift b/Tests/ModelTests/RelatedResourceTests/RelatedResourceCaptureTests.swift similarity index 97% rename from Tests/ModelTests/RelatedResourceCaptureTests.swift rename to Tests/ModelTests/RelatedResourceTests/RelatedResourceCaptureTests.swift index a8f6960a..71cdabd6 100644 --- a/Tests/ModelTests/RelatedResourceCaptureTests.swift +++ b/Tests/ModelTests/RelatedResourceTests/RelatedResourceCaptureTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class RelatedResourceCaptureTests: XCTestCase { +public final class RelatedResourceCaptureTests: XCTestCase { func testInit()throws { let capture = try RelatedResource.Capture( amount: DetailedAmount(currency: .usd, total: 67.23, details: nil), @@ -130,7 +130,7 @@ final class RelatedResourceCaptureTests: XCTestCase { } - static var allTests: [(String, (RelatedResourceCaptureTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (RelatedResourceCaptureTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/RelatedResourceOrderTests.swift b/Tests/ModelTests/RelatedResourceTests/RelatedResourceOrderTests.swift similarity index 96% rename from Tests/ModelTests/RelatedResourceOrderTests.swift rename to Tests/ModelTests/RelatedResourceTests/RelatedResourceOrderTests.swift index b8fc30aa..60a71def 100644 --- a/Tests/ModelTests/RelatedResourceOrderTests.swift +++ b/Tests/ModelTests/RelatedResourceTests/RelatedResourceOrderTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class RelatedResourceOrderTests: XCTestCase { +public final class RelatedResourceOrderTests: XCTestCase { let now = Date() func testInit()throws { @@ -93,7 +93,7 @@ final class RelatedResourceOrderTests: XCTestCase { XCTAssertEqual(sale.amount, DetailedAmount(currency: .usd, total: 645.12, details: nil)) } - static var allTests: [(String, (RelatedResourceOrderTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (RelatedResourceOrderTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/RelatedResourceRefundTests.swift b/Tests/ModelTests/RelatedResourceTests/RelatedResourceRefundTests.swift similarity index 96% rename from Tests/ModelTests/RelatedResourceRefundTests.swift rename to Tests/ModelTests/RelatedResourceTests/RelatedResourceRefundTests.swift index 2ad3c9e2..5f2efbd7 100644 --- a/Tests/ModelTests/RelatedResourceRefundTests.swift +++ b/Tests/ModelTests/RelatedResourceTests/RelatedResourceRefundTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class RelatedResourceRefundTests: XCTestCase { +public final class RelatedResourceRefundTests: XCTestCase { func testInit()throws { let refund = try RelatedResource.Refund( amount: DetailedAmount(currency: .usd, total: 67.23, details: nil), @@ -114,7 +114,7 @@ final class RelatedResourceRefundTests: XCTestCase { } - static var allTests: [(String, (RelatedResourceRefundTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (RelatedResourceRefundTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/RelatedResourceSaleTests.swift b/Tests/ModelTests/RelatedResourceTests/RelatedResourceSaleTests.swift similarity index 91% rename from Tests/ModelTests/RelatedResourceSaleTests.swift rename to Tests/ModelTests/RelatedResourceTests/RelatedResourceSaleTests.swift index 4d62179e..822434cd 100644 --- a/Tests/ModelTests/RelatedResourceSaleTests.swift +++ b/Tests/ModelTests/RelatedResourceTests/RelatedResourceSaleTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class RelatedResourceSaleTests: XCTestCase { +public final class RelatedResourceSaleTests: XCTestCase { let now = Date() func testInit()throws { @@ -46,7 +46,7 @@ final class RelatedResourceSaleTests: XCTestCase { ) let generated = try String(data: encoder.encode(sale), encoding: .utf8)! - let json = "{\"amount\":{\"currency\":\"USD\",\"total\":\"42.31\"},\"id\":\"9FF17892-49F8-47C9-8117-7662F889DAEA\",\"exchange_rate\":\"0.0\",\"transaction_fee\":{\"currency\":\"USD\",\"value\":\"0.31\"},\"receivable_amount\":{\"currency\":\"USD\",\"value\":\"42.00\"},\"fmf_details\":{\"filter_id\":\"BILLING_OR_SHIPPING_ADDRESS_MISMATCH\",\"name\":\"Name\",\"description\":\"Desc.\",\"filter_type\":\"DENY\"},\"create_time\":\"\(self.now.iso8601)\",\"parent_payment\":\"E7FBF930-B0F3-4514-B1DD-810BDCD6541F\",\"state\":\"pending\",\"processor_response\":{\"avs_code\":\"e\",\"response_code\":\"6399\",\"advice_code\":\"01_NEW_ACCOUNT_INFORMATION\",\"cvv_code\":\"h\",\"eci_submitted\":\"152823\",\"vpas\":\"stat\"}}" + let json = "{\"amount\":{\"currency\":\"USD\",\"total\":\"42.31\"},\"id\":\"9FF17892-49F8-47C9-8117-7662F889DAEA\",\"exchange_rate\":\"0.0\",\"transaction_fee\":{\"currency\":\"USD\",\"value\":\"0.31\"},\"receivable_amount\":{\"currency\":\"USD\",\"value\":\"42\"},\"fmf_details\":{\"filter_id\":\"BILLING_OR_SHIPPING_ADDRESS_MISMATCH\",\"name\":\"Name\",\"description\":\"Desc.\",\"filter_type\":\"DENY\"},\"create_time\":\"\(self.now.iso8601)\",\"parent_payment\":\"E7FBF930-B0F3-4514-B1DD-810BDCD6541F\",\"state\":\"pending\",\"processor_response\":{\"avs_code\":\"e\",\"response_code\":\"6399\",\"advice_code\":\"01_NEW_ACCOUNT_INFORMATION\",\"cvv_code\":\"h\",\"eci_submitted\":\"152823\",\"vpas\":\"stat\"}}" var index = 0 for (jsonChar, genChar) in zip(json, generated) { @@ -85,7 +85,7 @@ final class RelatedResourceSaleTests: XCTestCase { }, "receivable_amount": { "currency": "USD", - "value": "42.00" + "value": "42" }, "exchange_rate": "0.0", "fmf_details": { @@ -141,7 +141,7 @@ final class RelatedResourceSaleTests: XCTestCase { XCTAssertEqual(sale.amount, DetailedAmount(currency: .usd, total: 42.31, details: nil)) } - static var allTests: [(String, (RelatedResourceSaleTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (RelatedResourceSaleTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/RelatedResourceTests.swift b/Tests/ModelTests/RelatedResourceTests/RelatedResourceTests.swift similarity index 94% rename from Tests/ModelTests/RelatedResourceTests.swift rename to Tests/ModelTests/RelatedResourceTests/RelatedResourceTests.swift index ca2f4986..b0e0369e 100644 --- a/Tests/ModelTests/RelatedResourceTests.swift +++ b/Tests/ModelTests/RelatedResourceTests/RelatedResourceTests.swift @@ -1,10 +1,11 @@ import XCTest @testable import PayPal -final class RelatedResourceTests: XCTestCase { +public final class RelatedResourceTests: XCTestCase { func testInit()throws { + let now = Date() let resource = RelatedResource( - sale: .init(id: "", amount: DetailedAmount(currency: .usd, total: 10.0, details: nil), state: .pending, parent: "10"), + sale: .init(id: "", amount: DetailedAmount(currency: .usd, total: 10.0, details: nil), state: .pending, parent: "10", created: now), authorization: .init(amount: DetailedAmount(currency: .usd, total: 10, details: nil), fmf: nil, processor: nil), order: .init(amount: DetailedAmount(currency: .usd, total: 10, details: nil), fmf: nil), capture: .init(amount: nil, isFinal: nil, invoice: nil, transaction: nil, payerNote: nil), @@ -17,7 +18,7 @@ final class RelatedResourceTests: XCTestCase { XCTAssertEqual(resource.authorization, .init(amount: DetailedAmount(currency: .usd, total: 10, details: nil), fmf: nil, processor: nil)) XCTAssertEqual( resource.sale, - .init(id: "", amount: DetailedAmount(currency: .usd, total: 10, details: nil), state: .pending, parent: "10") + .init(id: "", amount: DetailedAmount(currency: .usd, total: 10, details: nil), state: .pending, parent: "10", created: now) ) } @@ -91,7 +92,7 @@ final class RelatedResourceTests: XCTestCase { try XCTAssertEqual(resource, decoder.decode(RelatedResource.self, from: json)) } - static var allTests: [(String, (RelatedResourceTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (RelatedResourceTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/ResourceAuthorizationPaymentModeTests.swift b/Tests/ModelTests/ResourceTests/ResourceAuthorizationPaymentModeTests.swift similarity index 86% rename from Tests/ModelTests/ResourceAuthorizationPaymentModeTests.swift rename to Tests/ModelTests/ResourceTests/ResourceAuthorizationPaymentModeTests.swift index 1cd43fbb..441760b8 100644 --- a/Tests/ModelTests/ResourceAuthorizationPaymentModeTests.swift +++ b/Tests/ModelTests/ResourceTests/ResourceAuthorizationPaymentModeTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Mode = RelatedResource.Authorization.PaymentMode -final class ResourceAuthorizationPaymentModeTests: XCTestCase { +public final class ResourceAuthorizationPaymentModeTests: XCTestCase { private struct Auth: Codable { let mode: Mode } @@ -34,7 +34,7 @@ final class ResourceAuthorizationPaymentModeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Auth.self, from: instant).mode, .instant) } - static var allTests: [(String, (ResourceAuthorizationPaymentModeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ResourceAuthorizationPaymentModeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/ResourceAuthorizationReasonTests.swift b/Tests/ModelTests/ResourceTests/ResourceAuthorizationReasonTests.swift similarity index 87% rename from Tests/ModelTests/ResourceAuthorizationReasonTests.swift rename to Tests/ModelTests/ResourceTests/ResourceAuthorizationReasonTests.swift index db3dfb66..cb8fb4c2 100644 --- a/Tests/ModelTests/ResourceAuthorizationReasonTests.swift +++ b/Tests/ModelTests/ResourceTests/ResourceAuthorizationReasonTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Reason = RelatedResource.Authorization.Reason -final class ResourceAuthorizationReasonTests: XCTestCase { +public final class ResourceAuthorizationReasonTests: XCTestCase { private struct Auth: Codable { let reason: Reason } @@ -34,7 +34,7 @@ final class ResourceAuthorizationReasonTests: XCTestCase { try XCTAssertEqual(decoder.decode(Auth.self, from: authorization).reason, .authorization) } - static var allTests: [(String, (ResourceAuthorizationReasonTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ResourceAuthorizationReasonTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/ResourceAuthorizationStateTests.swift b/Tests/ModelTests/ResourceTests/ResourceAuthorizationStateTests.swift similarity index 92% rename from Tests/ModelTests/ResourceAuthorizationStateTests.swift rename to Tests/ModelTests/ResourceTests/ResourceAuthorizationStateTests.swift index 4717f4e6..c265f120 100644 --- a/Tests/ModelTests/ResourceAuthorizationStateTests.swift +++ b/Tests/ModelTests/ResourceTests/ResourceAuthorizationStateTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias State = RelatedResource.Authorization.State -final class ResourceAuthorizationStateTests: XCTestCase { +public final class ResourceAuthorizationStateTests: XCTestCase { private struct Auth: Codable { let state: State } @@ -48,7 +48,7 @@ final class ResourceAuthorizationStateTests: XCTestCase { try XCTAssertEqual(decoder.decode(Auth.self, from: captured).state, .captured) } - static var allTests: [(String, (ResourceAuthorizationStateTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ResourceAuthorizationStateTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/ResourceCaptureReasonTests.swift b/Tests/ModelTests/ResourceTests/ResourceCaptureReasonTests.swift similarity index 94% rename from Tests/ModelTests/ResourceCaptureReasonTests.swift rename to Tests/ModelTests/ResourceTests/ResourceCaptureReasonTests.swift index af5a1bd4..4cc0b417 100644 --- a/Tests/ModelTests/ResourceCaptureReasonTests.swift +++ b/Tests/ModelTests/ResourceTests/ResourceCaptureReasonTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Reason = RelatedResource.Capture.Reason -final class ResourceCaptureReasonTests: XCTestCase { +public final class ResourceCaptureReasonTests: XCTestCase { private struct Capture: Codable { let reason: Reason } @@ -58,7 +58,7 @@ final class ResourceCaptureReasonTests: XCTestCase { try XCTAssertEqual(decoder.decode(Capture.self, from: refund).reason, .refund) } - static var allTests: [(String, (ResourceCaptureReasonTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ResourceCaptureReasonTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/ResourceCaptureStateTests.swift b/Tests/ModelTests/ResourceTests/ResourceCaptureStateTests.swift similarity index 92% rename from Tests/ModelTests/ResourceCaptureStateTests.swift rename to Tests/ModelTests/ResourceTests/ResourceCaptureStateTests.swift index 39d89745..92a01e9d 100644 --- a/Tests/ModelTests/ResourceCaptureStateTests.swift +++ b/Tests/ModelTests/ResourceTests/ResourceCaptureStateTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias State = RelatedResource.Capture.State -final class ResourceCaptureStateTests: XCTestCase { +public final class ResourceCaptureStateTests: XCTestCase { private struct Capture: Codable { let state: State } @@ -47,7 +47,7 @@ final class ResourceCaptureStateTests: XCTestCase { try XCTAssertEqual(decoder.decode(Capture.self, from: partiallyRefunded).state, .partiallyRefunded) } - static var allTests: [(String, (ResourceCaptureStateTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ResourceCaptureStateTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/ResourceOrderPaymentModeTests.swift b/Tests/ModelTests/ResourceTests/ResourceOrderPaymentModeTests.swift similarity index 91% rename from Tests/ModelTests/ResourceOrderPaymentModeTests.swift rename to Tests/ModelTests/ResourceTests/ResourceOrderPaymentModeTests.swift index 2526cd1c..46a3c0a3 100644 --- a/Tests/ModelTests/ResourceOrderPaymentModeTests.swift +++ b/Tests/ModelTests/ResourceTests/ResourceOrderPaymentModeTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Mode = RelatedResource.Order.PaymentMode -final class ResourceOrderPaymentModeTests: XCTestCase { +public final class ResourceOrderPaymentModeTests: XCTestCase { private struct Order: Codable { let mode: Mode } @@ -46,7 +46,7 @@ final class ResourceOrderPaymentModeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Order.self, from: echeck).mode, .echeck) } - static var allTests: [(String, (ResourceOrderPaymentModeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ResourceOrderPaymentModeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/ResourceOrderReasonTests.swift b/Tests/ModelTests/ResourceTests/ResourceOrderReasonTests.swift similarity index 93% rename from Tests/ModelTests/ResourceOrderReasonTests.swift rename to Tests/ModelTests/ResourceTests/ResourceOrderReasonTests.swift index c7f4f9d0..295f4225 100644 --- a/Tests/ModelTests/ResourceOrderReasonTests.swift +++ b/Tests/ModelTests/ResourceTests/ResourceOrderReasonTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Reason = RelatedResource.Order.Reason -final class ResourceOrderReasonTests: XCTestCase { +public final class ResourceOrderReasonTests: XCTestCase { private struct Order: Codable { let reason: Reason } @@ -49,7 +49,7 @@ final class ResourceOrderReasonTests: XCTestCase { try XCTAssertEqual(decoder.decode(Order.self, from: regulatory).reason, .regulatory) } - static var allTests: [(String, (ResourceOrderReasonTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ResourceOrderReasonTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/ResourceOrderStateTests.swift b/Tests/ModelTests/ResourceTests/ResourceOrderStateTests.swift similarity index 92% rename from Tests/ModelTests/ResourceOrderStateTests.swift rename to Tests/ModelTests/ResourceTests/ResourceOrderStateTests.swift index b34d1e6c..6eb1d15d 100644 --- a/Tests/ModelTests/ResourceOrderStateTests.swift +++ b/Tests/ModelTests/ResourceTests/ResourceOrderStateTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias State = RelatedResource.Order.State -final class ResourceOrderStateTests: XCTestCase { +public final class ResourceOrderStateTests: XCTestCase { private struct Order: Codable { let state: State } @@ -47,7 +47,7 @@ final class ResourceOrderStateTests: XCTestCase { try XCTAssertEqual(decoder.decode(Order.self, from: captured).state, .captured) } - static var allTests: [(String, (ResourceOrderStateTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ResourceOrderStateTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/ResourceProcessorAdviceTests.swift b/Tests/ModelTests/ResourceTests/ResourceProcessorAdviceTests.swift similarity index 93% rename from Tests/ModelTests/ResourceProcessorAdviceTests.swift rename to Tests/ModelTests/ResourceTests/ResourceProcessorAdviceTests.swift index 5ca54f7e..a8aee806 100644 --- a/Tests/ModelTests/ResourceProcessorAdviceTests.swift +++ b/Tests/ModelTests/ResourceTests/ResourceProcessorAdviceTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias Advice = RelatedResource.ProcessorResponse.AdviceCode -final class ResourceProcessorAdviceTests: XCTestCase { +public final class ResourceProcessorAdviceTests: XCTestCase { private struct Processor: Codable { let advice: Advice } @@ -51,7 +51,7 @@ final class ResourceProcessorAdviceTests: XCTestCase { try XCTAssertEqual(decoder.decode(Processor.self, from: dontTry).advice, .dontTry) } - static var allTests: [(String, (ResourceProcessorAdviceTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ResourceProcessorAdviceTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/ResourceRefundStateTests.swift b/Tests/ModelTests/ResourceTests/ResourceRefundStateTests.swift similarity index 91% rename from Tests/ModelTests/ResourceRefundStateTests.swift rename to Tests/ModelTests/ResourceTests/ResourceRefundStateTests.swift index 3a45a8ff..e8986b1a 100644 --- a/Tests/ModelTests/ResourceRefundStateTests.swift +++ b/Tests/ModelTests/ResourceTests/ResourceRefundStateTests.swift @@ -3,7 +3,7 @@ import XCTest fileprivate typealias State = RelatedResource.Refund.State -final class ResourceRefundStateTests: XCTestCase { +public final class ResourceRefundStateTests: XCTestCase { private struct Order: Codable { let state: State } @@ -46,7 +46,7 @@ final class ResourceRefundStateTests: XCTestCase { try XCTAssertEqual(decoder.decode(Order.self, from: failed).state, .failed) } - static var allTests: [(String, (ResourceRefundStateTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ResourceRefundStateTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/RoleTests.swift b/Tests/ModelTests/RoleTests.swift index b7a0b7dc..5b25aabb 100644 --- a/Tests/ModelTests/RoleTests.swift +++ b/Tests/ModelTests/RoleTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class RoleTests: XCTestCase { +public final class RoleTests: XCTestCase { struct User: Codable { let role: Role } @@ -44,7 +44,7 @@ final class RoleTests: XCTestCase { try XCTAssertEqual(decoder.decode(User.self, from: payer).role, .payer) } - static var allTests: [(String, (RoleTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (RoleTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/SaleStatusTests.swift b/Tests/ModelTests/SaleTests/SaleStatusTests.swift similarity index 93% rename from Tests/ModelTests/SaleStatusTests.swift rename to Tests/ModelTests/SaleTests/SaleStatusTests.swift index e1daaffe..25bd5260 100644 --- a/Tests/ModelTests/SaleStatusTests.swift +++ b/Tests/ModelTests/SaleTests/SaleStatusTests.swift @@ -3,7 +3,7 @@ import XCTest typealias SaleStat = Sale.Status -final class SaleStatusTests: XCTestCase { +public final class SaleStatusTests: XCTestCase { struct Sal: Codable { let status: SaleStat } @@ -47,7 +47,7 @@ final class SaleStatusTests: XCTestCase { try XCTAssertEqual(decoder.decode(Sal.self, from: refunded).status, .refunded) } - static var allTests: [(String, (SaleStatusTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (SaleStatusTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/SaleTests.swift b/Tests/ModelTests/SaleTests/SaleTests.swift similarity index 89% rename from Tests/ModelTests/SaleTests.swift rename to Tests/ModelTests/SaleTests/SaleTests.swift index c9bf2bf8..b973e915 100644 --- a/Tests/ModelTests/SaleTests.swift +++ b/Tests/ModelTests/SaleTests/SaleTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class SaleTests: XCTestCase { +public final class SaleTests: XCTestCase { func testInit()throws { let sale = Sale(amount: DetailedAmount(currency: .usd, total: 10.00, details: nil), transaction: CurrencyAmount(currency: .usd, value: 1.00)) @@ -18,7 +18,7 @@ final class SaleTests: XCTestCase { let encoder = JSONEncoder() let sale = Sale(amount: DetailedAmount(currency: .usd, total: 10.00, details: nil), transaction: CurrencyAmount(currency: .usd, value: 1.00)) let generated = try String(data: encoder.encode(sale), encoding: .utf8)! - let json = "{\"amount\":{\"currency\":\"USD\",\"total\":\"10.00\"},\"transaction_fee\":{\"currency\":\"USD\",\"value\":\"1.00\"}}" + let json = "{\"amount\":{\"currency\":\"USD\",\"total\":\"10.00\"},\"transaction_fee\":{\"currency\":\"USD\",\"value\":\"1\"}}" var index = 0 for (jsonChar, genChar) in zip(json, generated) { @@ -41,12 +41,12 @@ final class SaleTests: XCTestCase { "currency": "USD" }, "transaction_fee": { - "value": "1.00", + "value": "1", "currency": "USD" }, "status": "PENDING", - "create_time": "2018-09-18T21:22:51+0000", - "update_time": "2018-09-18T21:23:25+0000", + "create_time": "2018-09-18T21:22:51.000Z", + "update_time": "2018-09-18T21:23:25.000Z", "links": [] } """.data(using: .utf8)! @@ -55,14 +55,14 @@ final class SaleTests: XCTestCase { XCTAssertEqual(sale.id, "259CEDEE-4A03-45A0-B088-B6A318544619") XCTAssertEqual(sale.status, .pending) - XCTAssertEqual(sale.created, Date(iso8601: "2018-09-18T21:22:51+0000")) - XCTAssertEqual(sale.updated, Date(iso8601: "2018-09-18T21:23:25+0000")) + XCTAssertEqual(sale.created, Date(iso8601: "2018-09-18T21:22:51.000Z")) + XCTAssertEqual(sale.updated, Date(iso8601: "2018-09-18T21:23:25.000Z")) XCTAssertEqual(sale.links, []) XCTAssertEqual(sale.transaction, CurrencyAmount(currency: .usd, value: 1.00)) XCTAssertEqual(sale.amount, DetailedAmount(currency: .usd, total: 10.00, details: nil)) } - static var allTests: [(String, (SaleTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (SaleTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/SalesVenueTests.swift b/Tests/ModelTests/SaleTests/SalesVenueTests.swift similarity index 93% rename from Tests/ModelTests/SalesVenueTests.swift rename to Tests/ModelTests/SaleTests/SalesVenueTests.swift index 799521c3..810a639f 100644 --- a/Tests/ModelTests/SalesVenueTests.swift +++ b/Tests/ModelTests/SaleTests/SalesVenueTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class SalesVenueTests: XCTestCase { +public final class SalesVenueTests: XCTestCase { func testInit()throws { let venue = SalesVenue(type: .ebay, ebayID: "D6013453-B76E-4CDD-A021-DFD31A4031FE", description: "Online Ebay Store") @@ -41,7 +41,7 @@ final class SalesVenueTests: XCTestCase { try XCTAssertEqual(venue, decoder.decode(SalesVenue.self, from: json)) } - static var allTests: [(String, (SalesVenueTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (SalesVenueTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/SellerTests.swift b/Tests/ModelTests/SaleTests/SellerTests.swift similarity index 94% rename from Tests/ModelTests/SellerTests.swift rename to Tests/ModelTests/SaleTests/SellerTests.swift index d2130629..4d58d5d4 100644 --- a/Tests/ModelTests/SellerTests.swift +++ b/Tests/ModelTests/SaleTests/SellerTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class SellerTests: XCTestCase { +public final class SellerTests: XCTestCase { func testInit()throws { let seller = try Seller(email: .init("witheringheights@exmaple.com"), name: "Leeli Wingfeather", merchantID: nil) @@ -54,7 +54,7 @@ final class SellerTests: XCTestCase { ) } - static var allTests: [(String, (SellerTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (SellerTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/ShippingCostsTests.swift b/Tests/ModelTests/ShippingTests/ShippingCostsTests.swift similarity index 85% rename from Tests/ModelTests/ShippingCostsTests.swift rename to Tests/ModelTests/ShippingTests/ShippingCostsTests.swift index 00f207ac..211bb0ff 100644 --- a/Tests/ModelTests/ShippingCostsTests.swift +++ b/Tests/ModelTests/ShippingTests/ShippingCostsTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class ShippingCostsTests: XCTestCase { +public final class ShippingCostsTests: XCTestCase { func testInit()throws { let shipping = ShippingCosts( amount: CurrencyAmount(currency: .usd, value: 2.50), @@ -20,8 +20,8 @@ final class ShippingCostsTests: XCTestCase { ) let generated = try String(data: encoder.encode(shipping), encoding: .utf8)! let json = - "{\"amount\":{\"currency\":\"USD\",\"value\":\"2.50\"},\"tax\":{\"name\":\"Shipping\",\"percent\":7.5,\"amount\":{\"currency\":\"USD\"," + - "\"value\":\"0.18\"}}}" + "{\"amount\":{\"currency\":\"USD\",\"value\":\"2.5\"},\"tax\":{\"name\":\"Shipping\"," + + "\"percent\":7.5,\"amount\":{\"currency\":\"USD\",\"value\":\"0.18\"}}}" var index = 0 for (jsonChar, genChar) in zip(json, generated) { @@ -51,7 +51,7 @@ final class ShippingCostsTests: XCTestCase { } }, "amount": { - "value": "2.50", + "value": "2.5", "currency": "USD" } } @@ -60,7 +60,7 @@ final class ShippingCostsTests: XCTestCase { try XCTAssertEqual(shipping, decoder.decode(ShippingCosts.self, from: json)) } - static var allTests: [(String, (ShippingCostsTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ShippingCostsTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/ShippingInfoTests.swift b/Tests/ModelTests/ShippingTests/ShippingInfoTests.swift similarity index 96% rename from Tests/ModelTests/ShippingInfoTests.swift rename to Tests/ModelTests/ShippingTests/ShippingInfoTests.swift index 0141a136..e6909d99 100644 --- a/Tests/ModelTests/ShippingInfoTests.swift +++ b/Tests/ModelTests/ShippingTests/ShippingInfoTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class ShippingInfoTests: XCTestCase { +public final class ShippingInfoTests: XCTestCase { func testInit()throws { let info = try ShippingInfo( firstName: .init("Oskar"), @@ -100,7 +100,7 @@ final class ShippingInfoTests: XCTestCase { try XCTAssertEqual(info, decoder.decode(ShippingInfo.self, from: json)) } - static var allTests: [(String, (ShippingInfoTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (ShippingInfoTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/SignupOptionsTests.swift b/Tests/ModelTests/SignupOptionsTests.swift index 63d16e13..4c89b1b5 100644 --- a/Tests/ModelTests/SignupOptionsTests.swift +++ b/Tests/ModelTests/SignupOptionsTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class SignupOptionsTests: XCTestCase { +public final class SignupOptionsTests: XCTestCase { let web = WebExperiencePreference( partnerLogo: nil, returnURL: nil, @@ -48,7 +48,7 @@ final class SignupOptionsTests: XCTestCase { try XCTAssertEqual(options, decoder.decode(SignupOptions.self, from: json)) } - static var allTests: [(String, (SignupOptionsTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (SignupOptionsTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/StakeholderTests.swift b/Tests/ModelTests/StakeholderTests/StakeholderTests.swift similarity index 91% rename from Tests/ModelTests/StakeholderTests.swift rename to Tests/ModelTests/StakeholderTests/StakeholderTests.swift index 69baf111..22045672 100644 --- a/Tests/ModelTests/StakeholderTests.swift +++ b/Tests/ModelTests/StakeholderTests/StakeholderTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class StakeholderTests: XCTestCase { +public final class StakeholderTests: XCTestCase { func testInit()throws { let holder = Business.Stakeholder( type: .partner, @@ -39,7 +39,7 @@ final class StakeholderTests: XCTestCase { ) let generated = try String(data: encoder.encode(holder), encoding: .utf8)! let json = - "{\"phones\":[],\"country_code_of_nationality\":\"US\",\"date_of_birth\":{\"date_no_time\":\"2000-06-18\"},\"addresses\":[]," + + "{\"phones\":[],\"country_code_of_nationality\":\"US\",\"date_of_birth\":\"2000-06-18\",\"addresses\":[]," + "\"identifications\":[],\"type\":\"PARTNER\",\"name\":{},\"place_of_birth\":{\"country_code\":\"US\",\"city\":\"Boston\"}}" var index = 0 @@ -64,9 +64,7 @@ final class StakeholderTests: XCTestCase { "phones": [], "addresses": [], "name": {}, - "date_of_birth": { - "date_no_time": "2000-06-18" - }, + "date_of_birth": "2000-06-18", "country_code_of_nationality": "US", "type": "PARTNER" } @@ -85,7 +83,7 @@ final class StakeholderTests: XCTestCase { try XCTAssertEqual(holder, decoder.decode(Business.Stakeholder.self, from: json)) } - static var allTests: [(String, (StakeholderTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (StakeholderTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/StakeholderTypeTests.swift b/Tests/ModelTests/StakeholderTests/StakeholderTypeTests.swift similarity index 94% rename from Tests/ModelTests/StakeholderTypeTests.swift rename to Tests/ModelTests/StakeholderTests/StakeholderTypeTests.swift index 11aeb7e8..7841b7d7 100644 --- a/Tests/ModelTests/StakeholderTypeTests.swift +++ b/Tests/ModelTests/StakeholderTests/StakeholderTypeTests.swift @@ -3,7 +3,7 @@ import XCTest typealias StakeholderType = Business.Stakeholder.StakeholderType -final class StakeholderTypeTests: XCTestCase { +public final class StakeholderTypeTests: XCTestCase { struct Holder: Codable { let type: Business.Stakeholder.StakeholderType } @@ -52,7 +52,7 @@ final class StakeholderTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(Holder.self, from: beneficialOwnerBusiness).type, .beneficialOwnerBusiness) } - static var allTests: [(String, (StakeholderTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (StakeholderTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/TaxTests.swift b/Tests/ModelTests/TaxTests.swift index 126a2644..61379bc4 100644 --- a/Tests/ModelTests/TaxTests.swift +++ b/Tests/ModelTests/TaxTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class TaxTests: XCTestCase { +public final class TaxTests: XCTestCase { func testInit()throws { let tax = try Tax(name: .init("Sales"), percent: .init(10), amount: CurrencyAmount(currency: .usd, value: 0.59)) @@ -57,7 +57,7 @@ final class TaxTests: XCTestCase { try XCTAssertEqual(Tax(name: .init("Sales"), percent: .init(10), amount: nil), decoder.decode(Tax.self, from: json)) } - static var allTests: [(String, (TaxTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (TaxTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/TemplateDataTests.swift b/Tests/ModelTests/TemplateTests/TemplateDataTests.swift similarity index 90% rename from Tests/ModelTests/TemplateDataTests.swift rename to Tests/ModelTests/TemplateTests/TemplateDataTests.swift index cd8d65dc..aaa29824 100644 --- a/Tests/ModelTests/TemplateDataTests.swift +++ b/Tests/ModelTests/TemplateTests/TemplateDataTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class TemplateDataTests: XCTestCase { +public final class TemplateDataTests: XCTestCase { let (now, timlessNow): (Date, String) = { let now = Date() let timeless = TimelessDate.formatter.string(from: now) @@ -13,14 +13,14 @@ final class TemplateDataTests: XCTestCase { func testInit()throws { let data = try Template.Data( merchant: MerchantInfo( - email: "hello@vapor.codes", - business: "Qutheory LLC.", - firstName: "Tanner", - lastName: "Nelson", + email: .init("hello@vapor.codes"), + business: .init("Qutheory LLC."), + firstName: .init("Tanner"), + lastName: .init("Nelson"), address: nil, phone: nil, fax: nil, - website: "https://vapor.codes/", + website: .init("https://vapor.codes/"), taxID: nil, info: nil ), @@ -65,14 +65,14 @@ final class TemplateDataTests: XCTestCase { try XCTAssertEqual(data.custom, CustomAmount(label: nil, amount: .init(CurrencyAmount(currency: .usd, value: 10.00)))) try XCTAssertEqual(data.cc, [.init(email: .init("collective@vapor.codes")), .init(email: .init("donator@example.com"))]) try XCTAssertEqual(data.merchant, MerchantInfo( - email: "hello@vapor.codes", - business: "Qutheory LLC.", - firstName: "Tanner", - lastName: "Nelson", + email: .init("hello@vapor.codes"), + business: .init("Qutheory LLC."), + firstName: .init("Tanner"), + lastName: .init("Nelson"), address: nil, phone: nil, fax: nil, - website: "https://vapor.codes/", + website: .init("https://vapor.codes/"), taxID: nil, info: nil )) @@ -101,14 +101,14 @@ final class TemplateDataTests: XCTestCase { let encoder = JSONEncoder() let data = try Template.Data( merchant: MerchantInfo( - email: "hello@vapor.codes", - business: "Qutheory LLC.", - firstName: "Tanner", - lastName: "Nelson", + email: .init("hello@vapor.codes"), + business: .init("Qutheory LLC."), + firstName: .init("Tanner"), + lastName: .init("Nelson"), address: nil, phone: nil, fax: nil, - website: "https://vapor.codes/", + website: .init("https://vapor.codes/"), taxID: nil, info: nil ), @@ -135,11 +135,11 @@ final class TemplateDataTests: XCTestCase { let json = "{\"tax_calculated_after_discount\":true,\"logo_url\":\"https:\\/\\/vapor.codes\\/dist\\/e032390c38279fbdf18ebf0e763eb44f.png\"," + "\"note\":\"Thanks for your donation!\",\"billing_info\":[],\"allow_partial_payment\":false," + - "\"minimum_amount_due\":{\"currency\":\"USD\",\"value\":\"1.00\"},\"merchant_info\":{\"email\":\"hello@vapor.codes\"" + + "\"minimum_amount_due\":{\"currency\":\"USD\",\"value\":\"1\"},\"merchant_info\":{\"email\":\"hello@vapor.codes\"" + ",\"last_name\":\"Nelson\",\"website\":\"https:\\/\\/vapor.codes\\/\",\"business_name\":\"Qutheory LLC.\",\"first_name\":\"Tanner\"}," + "\"cc_info\":[{\"email\":\"collective@vapor.codes\"},{\"email\":\"donator@example.com\"}],\"payment_term\":{" + "\"due_date\":\"\(self.timlessNow)\",\"term_type\":\"DUE_ON_RECEIPT\"}," + - "\"custom\":{\"amount\":{\"currency\":\"USD\",\"value\":\"10.00\"}},\"attachments\":[{\"name\":\"photo.jpg\"," + + "\"custom\":{\"amount\":{\"currency\":\"USD\",\"value\":\"10\"}},\"attachments\":[{\"name\":\"photo.jpg\"," + "\"url\":\"https:\\/\\/avatars3.githubusercontent.com\\/u\\/2872298?s=200&v=4\"}],\"reference\":\"PO number\",\"tax_inclusive\":true," + "\"merchant_memo\":\"Open Collective donation\"}" @@ -165,7 +165,7 @@ final class TemplateDataTests: XCTestCase { "billing_info": [], "allow_partial_payment": false, "minimum_amount_due": { - "value": "1.00", + "value": "1", "currency": "USD" }, "merchant_info": { @@ -189,7 +189,7 @@ final class TemplateDataTests: XCTestCase { }, "custom": { "amount": { - "value": "10.00", + "value": "10", "currency": "USD" } }, @@ -260,14 +260,14 @@ final class TemplateDataTests: XCTestCase { try XCTAssertEqual(data, Template.Data( merchant: MerchantInfo( - email: "hello@vapor.codes", - business: "Qutheory LLC.", - firstName: "Tanner", - lastName: "Nelson", + email: .init("hello@vapor.codes"), + business: .init("Qutheory LLC."), + firstName: .init("Tanner"), + lastName: .init("Nelson"), address: nil, phone: nil, fax: nil, - website: "https://vapor.codes/", + website: .init("https://vapor.codes/"), taxID: nil, info: nil ), @@ -292,7 +292,7 @@ final class TemplateDataTests: XCTestCase { )) } - static var allTests: [(String, (TemplateDataTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (TemplateDataTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testValidations", testValidations), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/TemplateListFieldsTests.swift b/Tests/ModelTests/TemplateTests/TemplateListFieldsTests.swift similarity index 90% rename from Tests/ModelTests/TemplateListFieldsTests.swift rename to Tests/ModelTests/TemplateTests/TemplateListFieldsTests.swift index 6b9d9e59..750243cd 100644 --- a/Tests/ModelTests/TemplateListFieldsTests.swift +++ b/Tests/ModelTests/TemplateTests/TemplateListFieldsTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class TemplateListFieldsTests: XCTestCase { +public final class TemplateListFieldsTests: XCTestCase { struct List: Codable { let field: Template.ListFields } @@ -42,7 +42,7 @@ final class TemplateListFieldsTests: XCTestCase { try XCTAssertEqual(decoder.decode(List.self, from: all).field, .all) } - static var allTests: [(String, (TemplateListFieldsTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (TemplateListFieldsTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/TemplateListTests.swift b/Tests/ModelTests/TemplateTests/TemplateListTests.swift similarity index 73% rename from Tests/ModelTests/TemplateListTests.swift rename to Tests/ModelTests/TemplateTests/TemplateListTests.swift index f895dab6..0fcaf5f3 100644 --- a/Tests/ModelTests/TemplateListTests.swift +++ b/Tests/ModelTests/TemplateTests/TemplateListTests.swift @@ -1,20 +1,20 @@ import XCTest @testable import PayPal -final class TemplateListTests: XCTestCase { +public final class TemplateListTests: XCTestCase { func testInit()throws { - let list = Template.List(addresses: [], emails: [], phones: [], templates: []) + let list = try Template.List(addresses: [], emails: .init([]), phones: [], templates: []) XCTAssertNil(list.links) XCTAssertEqual(list.addresses, []) - XCTAssertEqual(list.emails, []) + XCTAssertEqual(list.emails.value, []) XCTAssertEqual(list.phones, []) XCTAssertEqual(list.templates, []) } func testEncoding()throws { let encoder = JSONEncoder() - let list = Template.List(addresses: [], emails: [], phones: [], templates: []) + let list = try Template.List(addresses: [], emails: .init([]), phones: [], templates: []) let generated = try String(data: encoder.encode(list), encoding: .utf8)! let json = "{\"templates\":[],\"addresses\":[],\"emails\":[],\"phones\":[]}" @@ -38,12 +38,12 @@ final class TemplateListTests: XCTestCase { "templates": [] } """.data(using: .utf8)! - let list = Template.List(addresses: [], emails: [], phones: [], templates: []) + let list = try Template.List(addresses: [], emails: .init([]), phones: [], templates: []) try XCTAssertEqual(list, decoder.decode(Template.List.self, from: json)) } - static var allTests: [(String, (TemplateListTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (TemplateListTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/TemplateSettingFieldTests.swift b/Tests/ModelTests/TemplateTests/TemplateSettingFieldTests.swift similarity index 93% rename from Tests/ModelTests/TemplateSettingFieldTests.swift rename to Tests/ModelTests/TemplateTests/TemplateSettingFieldTests.swift index 872c9cfe..eef71198 100644 --- a/Tests/ModelTests/TemplateSettingFieldTests.swift +++ b/Tests/ModelTests/TemplateTests/TemplateSettingFieldTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class TemplateSettingFieldTests: XCTestCase { +public final class TemplateSettingFieldTests: XCTestCase { struct Settings: Codable { let field: Template.Settings.Field } @@ -48,7 +48,7 @@ final class TemplateSettingFieldTests: XCTestCase { try XCTAssertEqual(decoder.decode(Settings.self, from: custom).field, .custom) } - static var allTests: [(String, (TemplateSettingFieldTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (TemplateSettingFieldTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/TemplateSettingsMetadataTests.swift b/Tests/ModelTests/TemplateTests/TemplateSettingsMetadataTests.swift similarity index 88% rename from Tests/ModelTests/TemplateSettingsMetadataTests.swift rename to Tests/ModelTests/TemplateTests/TemplateSettingsMetadataTests.swift index 6d9d8591..1e3eea05 100644 --- a/Tests/ModelTests/TemplateSettingsMetadataTests.swift +++ b/Tests/ModelTests/TemplateTests/TemplateSettingsMetadataTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class TemplateSettingsMetadataTests: XCTestCase { +public final class TemplateSettingsMetadataTests: XCTestCase { func testInit()throws { let metadata = Template.Settings.Metadata(hidden: false) @@ -36,7 +36,7 @@ final class TemplateSettingsMetadataTests: XCTestCase { try XCTAssertEqual(metadata, decoder.decode(Template.Settings.Metadata.self, from: json)) } - static var allTests: [(String, (TemplateSettingsMetadataTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (TemplateSettingsMetadataTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/TemplateSettingsTests.swift b/Tests/ModelTests/TemplateTests/TemplateSettingsTests.swift similarity index 91% rename from Tests/ModelTests/TemplateSettingsTests.swift rename to Tests/ModelTests/TemplateTests/TemplateSettingsTests.swift index be72ec92..7f1e1455 100644 --- a/Tests/ModelTests/TemplateSettingsTests.swift +++ b/Tests/ModelTests/TemplateTests/TemplateSettingsTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class TemplateSettingsTests: XCTestCase { +public final class TemplateSettingsTests: XCTestCase { func testInit()throws { let settings = Template.Settings(field: .itemsDescription, preference: .init(hidden: true)) @@ -40,7 +40,7 @@ final class TemplateSettingsTests: XCTestCase { try XCTAssertEqual(settings, decoder.decode(Template.Settings.self, from: json)) } - static var allTests: [(String, (TemplateSettingsTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (TemplateSettingsTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/TemplateTests.swift b/Tests/ModelTests/TemplateTests/TemplateTests.swift similarity index 96% rename from Tests/ModelTests/TemplateTests.swift rename to Tests/ModelTests/TemplateTests/TemplateTests.swift index 934911b0..c41e0dca 100644 --- a/Tests/ModelTests/TemplateTests.swift +++ b/Tests/ModelTests/TemplateTests/TemplateTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class TemplateTests: XCTestCase { +public final class TemplateTests: XCTestCase { func testInit()throws { let template = Template( name: "Hours Template", @@ -88,7 +88,7 @@ final class TemplateTests: XCTestCase { try XCTAssertEqual(template, decoder.decode(Template.self, from: json)) } - static var allTests: [(String, (TemplateTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (TemplateTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/TermTests.swift b/Tests/ModelTests/TermTests/TermTests.swift similarity index 95% rename from Tests/ModelTests/TermTests.swift rename to Tests/ModelTests/TermTests/TermTests.swift index c447d0c8..de7323d1 100644 --- a/Tests/ModelTests/TermTests.swift +++ b/Tests/ModelTests/TermTests/TermTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class TermTests: XCTestCase { +public final class TermTests: XCTestCase { func testInit()throws { let term = try Term( type: .monthly, @@ -72,7 +72,7 @@ final class TermTests: XCTestCase { ) } - static var allTests: [(String, (TermTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (TermTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/TermTypeTests.swift b/Tests/ModelTests/TermTests/TermTypeTests.swift similarity index 92% rename from Tests/ModelTests/TermTypeTests.swift rename to Tests/ModelTests/TermTests/TermTypeTests.swift index fcae1ba1..a7b01da2 100644 --- a/Tests/ModelTests/TermTypeTests.swift +++ b/Tests/ModelTests/TermTests/TermTypeTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class TermTypeTests: XCTestCase { +public final class TermTypeTests: XCTestCase { struct TaC: Codable { let type: TermType } @@ -43,7 +43,7 @@ final class TermTypeTests: XCTestCase { try XCTAssertEqual(decoder.decode(TaC.self, from: yearly).type, .yearly) } - static var allTests: [(String, (TermTypeTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (TermTypeTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/TimelessDateTests.swift b/Tests/ModelTests/TimelessDateTests.swift index 8c10b8b6..eb020b7d 100644 --- a/Tests/ModelTests/TimelessDateTests.swift +++ b/Tests/ModelTests/TimelessDateTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class TimelessDateTests: XCTestCase { +public final class TimelessDateTests: XCTestCase { func testInit()throws { let epoch = TimelessDate(date: "1970-01-01") let date: TimelessDate = 981_244_800.0 @@ -14,10 +14,10 @@ final class TimelessDateTests: XCTestCase { func testEncoding()throws { let encoder = JSONEncoder() - let date = TimelessDate(date: "2001-02-04")! + let date = ["date": TimelessDate(date: "2001-02-04")!] let generated = try String(data: encoder.encode(date), encoding: .utf8) - let json = "{\"date_no_time\":\"2001-02-04\"}" + let json = "{\"date\":\"2001-02-04\"}" XCTAssertEqual(generated, json) } @@ -27,15 +27,15 @@ final class TimelessDateTests: XCTestCase { let json = """ { - "date_no_time": "2001-02-04" + "date": "2001-02-04" } """ - let date = TimelessDate(date: "2001-02-04")! - try XCTAssertEqual(date, decoder.decode(TimelessDate.self, from: json)) + let date = ["date": TimelessDate(date: "2001-02-04")!] + try XCTAssertEqual(date, decoder.decode([String: TimelessDate].self, from: json)) } - static var allTests: [(String, (TimelessDateTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (TimelessDateTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/TrackingTests.swift b/Tests/ModelTests/TrackingTests.swift index 66fd40c2..a2709b01 100644 --- a/Tests/ModelTests/TrackingTests.swift +++ b/Tests/ModelTests/TrackingTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class TrackingTests: XCTestCase { +public final class TrackingTests: XCTestCase { func testInit()throws { let tracking = Tracking(carrier: .usps, other: nil, url: "https://whoshippedit.com/shippment/9163524667210796186056", number: "9163524667210796186056") @@ -36,7 +36,7 @@ final class TrackingTests: XCTestCase { try XCTAssertEqual(tracking, decoder.decode(Tracking.self, from: json)) } - static var allTests: [(String, (TrackingTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (TrackingTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/TransactionInfoStatusTests.swift b/Tests/ModelTests/TransactionTests/TransactionInfoStatusTests.swift similarity index 93% rename from Tests/ModelTests/TransactionInfoStatusTests.swift rename to Tests/ModelTests/TransactionTests/TransactionInfoStatusTests.swift index 02fa3b52..17fc2bd8 100644 --- a/Tests/ModelTests/TransactionInfoStatusTests.swift +++ b/Tests/ModelTests/TransactionTests/TransactionInfoStatusTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class TransactionInfoStatusTests: XCTestCase { +public final class TransactionInfoStatusTests: XCTestCase { struct Request: Codable { let method: PayPal.Method } @@ -53,7 +53,7 @@ final class TransactionInfoStatusTests: XCTestCase { try XCTAssertEqual(decoder.decode(TI.self, from: reversed).status, .reversed) } - static var allTests: [(String, (TransactionInfoStatusTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (TransactionInfoStatusTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/TransactionInfoTests.swift b/Tests/ModelTests/TransactionTests/TransactionInfoTests.swift similarity index 97% rename from Tests/ModelTests/TransactionInfoTests.swift rename to Tests/ModelTests/TransactionTests/TransactionInfoTests.swift index fb985c85..eed444e4 100644 --- a/Tests/ModelTests/TransactionInfoTests.swift +++ b/Tests/ModelTests/TransactionTests/TransactionInfoTests.swift @@ -2,7 +2,7 @@ import XCTest import Failable @testable import PayPal -final class TransactionInfoTests: XCTestCase { +public final class TransactionInfoTests: XCTestCase { let now = Date() func testInit()throws { @@ -100,7 +100,7 @@ final class TransactionInfoTests: XCTestCase { try XCTAssertEqual(transaction, decoder.decode(TransactionInfo.self, from: json)) } - static var allTests: [(String, (TransactionInfoTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (TransactionInfoTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/TransactionStateTests.swift b/Tests/ModelTests/TransactionTests/TransactionStateTests.swift similarity index 92% rename from Tests/ModelTests/TransactionStateTests.swift rename to Tests/ModelTests/TransactionTests/TransactionStateTests.swift index cbe3bf22..68dc8244 100644 --- a/Tests/ModelTests/TransactionStateTests.swift +++ b/Tests/ModelTests/TransactionTests/TransactionStateTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class TransactionStateTests: XCTestCase { +public final class TransactionStateTests: XCTestCase { struct BillingTransaction: Codable { let state: Transaction.State } @@ -45,7 +45,7 @@ final class TransactionStateTests: XCTestCase { try XCTAssertEqual(decoder.decode(BillingTransaction.self, from: denied).state, .denied) } - static var allTests: [(String, (TransactionStateTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (TransactionStateTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/TransactionTests.swift b/Tests/ModelTests/TransactionTests/TransactionTests.swift similarity index 91% rename from Tests/ModelTests/TransactionTests.swift rename to Tests/ModelTests/TransactionTests/TransactionTests.swift index 00a0872a..0ca9d6a6 100644 --- a/Tests/ModelTests/TransactionTests.swift +++ b/Tests/ModelTests/TransactionTests/TransactionTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class TransactionTests: XCTestCase { +public final class TransactionTests: XCTestCase { func testInit()throws { let transaction = Transaction( amount: CurrencyCodeAmount(currency: .usd, value: 79.25), @@ -32,7 +32,7 @@ final class TransactionTests: XCTestCase { let generated = try String(data: encoder.encode(transaction), encoding: .utf8) let json = "{\"amount\":{\"value\":\"79.25\",\"currency_code\":\"USD\"},\"fee_amount\":{\"value\":\"7.25\",\"currency_code\":\"USD\"}," + - "\"net_amount\":{\"value\":\"72.00\",\"currency_code\":\"USD\"}}" + "\"net_amount\":{\"value\":\"72\",\"currency_code\":\"USD\"}}" XCTAssertEqual(generated, json) } @@ -43,7 +43,7 @@ final class TransactionTests: XCTestCase { { "net_amount": { "currency_code": "USD", - "value": "72.00" + "value": "72" }, "fee_amount": { "currency_code": "USD", @@ -62,11 +62,11 @@ final class TransactionTests: XCTestCase { "transaction_type": "Recurring Payment", "payer_email": "3E6F6A01-BB46-440E-B41D-9C2D611041E8", "payer_name": "Skelpo Inc.", - "time_stamp": "2018-07-23T17:24:48Z", + "time_stamp": "2018-07-23T17:24:48.000Z", "time_zone": "CDT", "net_amount": { "currency_code": "USD", - "value": "72.00" + "value": "72" }, "fee_amount": { "currency_code": "USD", @@ -91,14 +91,14 @@ final class TransactionTests: XCTestCase { XCTAssertEqual(transaction.type, "Recurring Payment") XCTAssertEqual(transaction.email, "3E6F6A01-BB46-440E-B41D-9C2D611041E8") XCTAssertEqual(transaction.name, "Skelpo Inc.") - XCTAssertEqual(transaction.timestamp, Date(iso8601: "2018-07-23T17:24:48Z")!) + XCTAssertEqual(transaction.timestamp, Date(iso8601: "2018-07-23T17:24:48.000Z")!) XCTAssertEqual(transaction.timezone, "CDT") XCTAssertEqual(transaction.amount, CurrencyCodeAmount(currency: .usd, value: 79.25)) XCTAssertEqual(transaction.fee, CurrencyCodeAmount(currency: .usd, value: 7.25)) XCTAssertEqual(transaction.net, CurrencyCodeAmount(currency: .usd, value: 72.00)) } - static var allTests: [(String, (TransactionTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (TransactionTests) -> ()throws -> ())] = [ ("testInit", testInit), ("testEncoding", testEncoding), ("testDecoding", testDecoding) diff --git a/Tests/ModelTests/UpdateActionTests.swift b/Tests/ModelTests/UpdateActionTests.swift index f7b3e664..a73da080 100644 --- a/Tests/ModelTests/UpdateActionTests.swift +++ b/Tests/ModelTests/UpdateActionTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class UpdateActionTests: XCTestCase { +public final class UpdateActionTests: XCTestCase { struct Update: Codable { let action: UpdateAction } @@ -42,7 +42,7 @@ final class UpdateActionTests: XCTestCase { try XCTAssertEqual(decoder.decode(Update.self, from: seller).action, .seller) } - static var allTests: [(String, (UpdateActionTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (UpdateActionTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/ModelTests/UserInfoAddressTests.swift b/Tests/ModelTests/UserIntoTests/UserInfoAddressTests.swift similarity index 84% rename from Tests/ModelTests/UserInfoAddressTests.swift rename to Tests/ModelTests/UserIntoTests/UserInfoAddressTests.swift index 2eab5167..aeeaf141 100644 --- a/Tests/ModelTests/UserInfoAddressTests.swift +++ b/Tests/ModelTests/UserIntoTests/UserInfoAddressTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class UserInfoAddressTests: XCTestCase { +public final class UserInfoAddressTests: XCTestCase { func testDecoding()throws { let json = """ { @@ -21,7 +21,7 @@ final class UserInfoAddressTests: XCTestCase { XCTAssertEqual(address.country, .switzerland) } - static var allTests: [(String, (UserInfoAddressTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (UserInfoAddressTests) -> ()throws -> ())] = [ ("testDecoding", testDecoding) ] } diff --git a/Tests/ModelTests/UserInfoTests.swift b/Tests/ModelTests/UserIntoTests/UserInfoTests.swift similarity index 94% rename from Tests/ModelTests/UserInfoTests.swift rename to Tests/ModelTests/UserIntoTests/UserInfoTests.swift index 15b418d7..023c0657 100644 --- a/Tests/ModelTests/UserInfoTests.swift +++ b/Tests/ModelTests/UserIntoTests/UserInfoTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class UserInfoTests: XCTestCase { +public final class UserInfoTests: XCTestCase { func testDecoding()throws { let json = """ { @@ -54,7 +54,7 @@ final class UserInfoTests: XCTestCase { XCTAssertEqual(info.payerID, "P-BCFC8B5AD16874F7") } - static var allTests: [(String, (UserInfoTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (UserInfoTests) -> ()throws -> ())] = [ ("testDecoding", testDecoding) ] } diff --git a/Tests/ModelTests/VenueTests.swift b/Tests/ModelTests/VenueTests.swift index dffcb929..dea8394f 100644 --- a/Tests/ModelTests/VenueTests.swift +++ b/Tests/ModelTests/VenueTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import PayPal -final class VenueTests: XCTestCase { +public final class VenueTests: XCTestCase { struct Prod: Codable { let venue: Venue } @@ -44,7 +44,7 @@ final class VenueTests: XCTestCase { try XCTAssertEqual(decoder.decode(Prod.self, from: other).venue, .other) } - static var allTests: [(String, (VenueTests) -> ()throws -> ())] = [ + public static var allTests: [(String, (VenueTests) -> ()throws -> ())] = [ ("testCaseRawValues", testCaseRawValues), ("testAllCase", testAllCase), ("testEncoding", testEncoding), diff --git a/Tests/PayPalTests/PayPalTests.swift b/Tests/PayPalTests/PayPalTests.swift index 5dd72d49..e34ed3fb 100644 --- a/Tests/PayPalTests/PayPalTests.swift +++ b/Tests/PayPalTests/PayPalTests.swift @@ -1,6 +1,6 @@ import XCTest @testable import PayPal -final class PayPalTests: XCTestCase { - static var allTests: [(String, (PayPalTests) -> ()throws -> ())] = [] +public final class PayPalTests: XCTestCase { + public static var allTests: [(String, (PayPalTests) -> ()throws -> ())] = [] } diff --git a/Tests/PayPalTests/XCTestManifests.swift b/Tests/PayPalTests/XCTestManifests.swift index 3b544f60..c3ae9597 100644 --- a/Tests/PayPalTests/XCTestManifests.swift +++ b/Tests/PayPalTests/XCTestManifests.swift @@ -1,4 +1,7 @@ import XCTest +import ModelTests +import ConfigTests +import ControllerTests #if !os(macOS) public func allTests() -> [XCTestCaseEntry] { @@ -242,6 +245,8 @@ public func allTests() -> [XCTestCaseEntry] { testCase(ProductNameTests.allCases), testCase(ProductVettingStatusTests.allCases), testCase(ProductGrantedPermissionTests.allCases), + testCase(MerchantInfoTests.allTests), + testCase(BusinessSalesTests.allTests), // Controller Tests testCase(APITests.allTests), diff --git a/test.pdf b/test.pdf deleted file mode 100644 index 52f29de7..00000000 Binary files a/test.pdf and /dev/null differ