mirror of
https://github.com/encounter/JSONAPI.git
synced 2026-03-30 11:18:38 -07:00
Added test library, attribute literal expressibility, and tests
This commit is contained in:
+8
-4
@@ -6,23 +6,27 @@ import PackageDescription
|
||||
let package = Package(
|
||||
name: "JSONAPI",
|
||||
products: [
|
||||
// Products define the executables and libraries produced by a package, and make them visible to other packages.
|
||||
.library(
|
||||
name: "JSONAPI",
|
||||
targets: ["JSONAPI"]),
|
||||
.library(
|
||||
name: "JSONAPITestLib",
|
||||
targets: ["JSONAPITestLib"])
|
||||
],
|
||||
dependencies: [
|
||||
// antitypical/Result without the Foundation requirement:
|
||||
.package(url: "https://github.com/mattpolzin/Result", .branch("master"))
|
||||
],
|
||||
targets: [
|
||||
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
|
||||
.target(
|
||||
name: "JSONAPI",
|
||||
dependencies: ["Result"]),
|
||||
.target(
|
||||
name: "JSONAPITestLib",
|
||||
dependencies: ["JSONAPI"]),
|
||||
.testTarget(
|
||||
name: "JSONAPITests",
|
||||
dependencies: ["JSONAPI"]),
|
||||
dependencies: ["JSONAPITestLib"])
|
||||
],
|
||||
swiftLanguageVersions: [.v4_2]
|
||||
)
|
||||
|
||||
@@ -24,6 +24,15 @@ extension TransformedAttribute: CustomStringConvertible {
|
||||
|
||||
extension TransformedAttribute: Equatable where Transformer.From: Equatable, Transformer.To: Equatable {}
|
||||
|
||||
extension TransformedAttribute where Transformer == IdentityTransformer<RawValue> {
|
||||
// If we are using the identity transform, we can skip the transform and guarantee no
|
||||
// error is thrown.
|
||||
public init(value: RawValue) {
|
||||
rawValue = value
|
||||
self.value = value
|
||||
}
|
||||
}
|
||||
|
||||
public typealias ValidatedAttribute<RawValue: Codable, Validator: JSONAPI.Validator> = TransformedAttribute<RawValue, Validator> where RawValue == Validator.From
|
||||
|
||||
public typealias Attribute<T: Codable> = TransformedAttribute<T, IdentityTransformer<T>>
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
|
||||
import JSONAPI
|
||||
|
||||
extension TransformedAttribute: ExpressibleByUnicodeScalarLiteral where RawValue: ExpressibleByUnicodeScalarLiteral, Transformer == IdentityTransformer<RawValue> {
|
||||
public typealias UnicodeScalarLiteralType = RawValue.UnicodeScalarLiteralType
|
||||
|
||||
public init(unicodeScalarLiteral value: RawValue.UnicodeScalarLiteralType) {
|
||||
self.init(value: RawValue(unicodeScalarLiteral: value))
|
||||
}
|
||||
}
|
||||
|
||||
extension TransformedAttribute: ExpressibleByExtendedGraphemeClusterLiteral where RawValue: ExpressibleByExtendedGraphemeClusterLiteral, Transformer == IdentityTransformer<RawValue> {
|
||||
public typealias ExtendedGraphemeClusterLiteralType = RawValue.ExtendedGraphemeClusterLiteralType
|
||||
|
||||
public init(extendedGraphemeClusterLiteral value: RawValue.ExtendedGraphemeClusterLiteralType) {
|
||||
self.init(value: RawValue(extendedGraphemeClusterLiteral: value))
|
||||
}
|
||||
}
|
||||
|
||||
extension TransformedAttribute: ExpressibleByStringLiteral where RawValue: ExpressibleByStringLiteral, Transformer == IdentityTransformer<RawValue> {
|
||||
public typealias StringLiteralType = RawValue.StringLiteralType
|
||||
|
||||
public init(stringLiteral value: RawValue.StringLiteralType) {
|
||||
self.init(value: RawValue(stringLiteral: value))
|
||||
}
|
||||
}
|
||||
|
||||
extension TransformedAttribute: ExpressibleByNilLiteral where RawValue: ExpressibleByNilLiteral, Transformer == IdentityTransformer<RawValue> {
|
||||
public init(nilLiteral: ()) {
|
||||
self.init(value: RawValue(nilLiteral: ()))
|
||||
}
|
||||
}
|
||||
|
||||
extension TransformedAttribute: ExpressibleByFloatLiteral where RawValue: ExpressibleByFloatLiteral, Transformer == IdentityTransformer<RawValue> {
|
||||
public typealias FloatLiteralType = RawValue.FloatLiteralType
|
||||
|
||||
public init(floatLiteral value: RawValue.FloatLiteralType) {
|
||||
self.init(value: RawValue(floatLiteral: value))
|
||||
}
|
||||
}
|
||||
|
||||
extension TransformedAttribute: ExpressibleByBooleanLiteral where RawValue: ExpressibleByBooleanLiteral, Transformer == IdentityTransformer<RawValue> {
|
||||
public typealias BooleanLiteralType = RawValue.BooleanLiteralType
|
||||
|
||||
public init(booleanLiteral value: BooleanLiteralType) {
|
||||
self.init(value: RawValue(booleanLiteral: value))
|
||||
}
|
||||
}
|
||||
|
||||
extension TransformedAttribute: ExpressibleByIntegerLiteral where RawValue: ExpressibleByIntegerLiteral, Transformer == IdentityTransformer<RawValue> {
|
||||
public typealias IntegerLiteralType = RawValue.IntegerLiteralType
|
||||
|
||||
public init(integerLiteral value: IntegerLiteralType) {
|
||||
self.init(value: RawValue(integerLiteral: value))
|
||||
}
|
||||
}
|
||||
|
||||
// regretably, array and dictionary literals are not so easy because Dictionaries and Arrays
|
||||
// cannot be turned back into variadic arguments to pass onto the RawValue type's constructor.
|
||||
|
||||
// we can still provide a case for the Array and Dictionary types, though.
|
||||
public protocol DictionaryType {
|
||||
associatedtype Key: Hashable
|
||||
associatedtype Value
|
||||
|
||||
init<S>(_ keysAndValues: S, uniquingKeysWith combine: (Dictionary<Key, Value>.Value, Dictionary<Key, Value>.Value) throws -> Dictionary<Key, Value>.Value) rethrows where S : Sequence, S.Element == (Key, Value)
|
||||
}
|
||||
extension Dictionary: DictionaryType {}
|
||||
|
||||
extension TransformedAttribute: ExpressibleByDictionaryLiteral where RawValue: DictionaryType, Transformer == IdentityTransformer<RawValue> {
|
||||
public typealias Key = RawValue.Key
|
||||
|
||||
public typealias Value = RawValue.Value
|
||||
|
||||
public init(dictionaryLiteral elements: (RawValue.Key, RawValue.Value)...) {
|
||||
|
||||
// we arbitrarily keep the first value if two values are assigned to the same key
|
||||
self.init(value: RawValue(elements, uniquingKeysWith: { val, _ in val }))
|
||||
}
|
||||
}
|
||||
|
||||
public protocol ArrayType {
|
||||
associatedtype Element
|
||||
|
||||
init<S>(_ s: S) where Element == S.Element, S : Sequence
|
||||
}
|
||||
extension Array: ArrayType {}
|
||||
extension ArraySlice: ArrayType {}
|
||||
|
||||
extension TransformedAttribute: ExpressibleByArrayLiteral where RawValue: ArrayType, Transformer == IdentityTransformer<RawValue> {
|
||||
public typealias ArrayLiteralElement = RawValue.Element
|
||||
|
||||
public init(arrayLiteral elements: ArrayLiteralElement...) {
|
||||
self.init(value: RawValue(elements))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// AttributeTests.swift
|
||||
// JSONAPITests
|
||||
//
|
||||
// Created by Mathew Polzin on 11/27/18.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import JSONAPI
|
||||
|
||||
class AttributeTests: XCTestCase {
|
||||
|
||||
func test_AttributeIsTransformedAttribute() {
|
||||
XCTAssertEqual(try TransformedAttribute<String, IdentityTransformer<String>>(rawValue: "hello"), try Attribute<String>(rawValue: "hello"))
|
||||
}
|
||||
|
||||
func test_AttributeNonThrowingConstructor() {
|
||||
XCTAssertEqual(try Attribute<String>(rawValue: "hello"), Attribute<String>(value: "hello"))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// Attribute+LiteralTests.swift
|
||||
// JSONAPITests
|
||||
//
|
||||
// Created by Mathew Polzin on 11/27/18.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import JSONAPI
|
||||
import JSONAPITestLib
|
||||
|
||||
class Attribute_LiteralTests: XCTestCase {
|
||||
|
||||
func test_StringLiteral() {
|
||||
XCTAssertEqual(Attribute<String>(value: "hello"), "hello")
|
||||
}
|
||||
|
||||
func test_BooleanLiteral() {
|
||||
XCTAssertEqual(Attribute<Bool>(value: false), false)
|
||||
}
|
||||
|
||||
func test_IntegerLiteral() {
|
||||
XCTAssertEqual(Attribute<Int>(value: 12), 12)
|
||||
}
|
||||
|
||||
func test_FloatLiteral() {
|
||||
XCTAssertEqual(Attribute<Float>(value: 1.2), 1.2)
|
||||
XCTAssertEqual(Attribute<Double>(value: 1.2), 1.2)
|
||||
}
|
||||
|
||||
func test_ArrayLiteral() {
|
||||
XCTAssertEqual(Attribute<[String]>(value: ["hello", "world"]), ["hello", "world"])
|
||||
}
|
||||
|
||||
func test_DictionaryLiteral() {
|
||||
XCTAssertEqual(Attribute<[String : Int]>(value: ["hello": 1]), ["hello": 1])
|
||||
}
|
||||
|
||||
func test_NilLiteral() {
|
||||
XCTAssertEqual(Attribute<String?>(value: nil), nil)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,24 @@
|
||||
import XCTest
|
||||
|
||||
extension AttributeTests {
|
||||
static let __allTests = [
|
||||
("test_AttributeIsTransformedAttribute", test_AttributeIsTransformedAttribute),
|
||||
("test_AttributeNonThrowingConstructor", test_AttributeNonThrowingConstructor),
|
||||
]
|
||||
}
|
||||
|
||||
extension Attribute_LiteralTests {
|
||||
static let __allTests = [
|
||||
("test_ArrayLiteral", test_ArrayLiteral),
|
||||
("test_BooleanLiteral", test_BooleanLiteral),
|
||||
("test_DictionaryLiteral", test_DictionaryLiteral),
|
||||
("test_FloatLiteral", test_FloatLiteral),
|
||||
("test_IntegerLiteral", test_IntegerLiteral),
|
||||
("test_NilLiteral", test_NilLiteral),
|
||||
("test_StringLiteral", test_StringLiteral),
|
||||
]
|
||||
}
|
||||
|
||||
extension DocumentTests {
|
||||
static let __allTests = [
|
||||
("test_errorDocumentNoMeta", test_errorDocumentNoMeta),
|
||||
@@ -180,6 +199,8 @@ extension ResourceBodyTests {
|
||||
#if !os(macOS)
|
||||
public func __allTests() -> [XCTestCaseEntry] {
|
||||
return [
|
||||
testCase(AttributeTests.__allTests),
|
||||
testCase(Attribute_LiteralTests.__allTests),
|
||||
testCase(DocumentTests.__allTests),
|
||||
testCase(EntityTests.__allTests),
|
||||
testCase(IncludedTests.__allTests),
|
||||
|
||||
Reference in New Issue
Block a user