Add Links and tests

This commit is contained in:
Mathew Polzin
2018-11-24 22:46:53 -08:00
parent 987bf2b750
commit 86e87ebf5d
5 changed files with 166 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
//
// Links.swift
// JSONAPI
//
// Created by Mathew Polzin on 11/24/18.
//
/// A Links structure should contain nothing but JSONAPI.Link properties.
public protocol Links: Codable, Equatable {}
/// Use NoLinks where no links should belong to a JSON API component
public struct NoLinks: Links {}
public protocol URL: Codable, Equatable {}
public struct Link<URL: JSONAPI.URL, Meta: JSONAPI.Meta>: Equatable, Codable {
public let url: URL
public let meta: Meta
}
public extension Link {
private enum CodingKeys: String, CodingKey {
case href
case meta
}
init(from decoder: Decoder) throws {
guard Meta.self == NoMetadata.self,
let noMeta = NoMetadata() as? Meta else {
let container = try decoder.container(keyedBy: CodingKeys.self)
meta = try container.decode(Meta.self, forKey: .meta)
url = try container.decode(URL.self, forKey: .href)
return
}
let container = try decoder.singleValueContainer()
url = try container.decode(URL.self)
meta = noMeta
}
func encode(to encoder: Encoder) throws {
guard Meta.self == NoMetadata.self else {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(url, forKey: .href)
try container.encode(meta, forKey: .meta)
return
}
var container = encoder.singleValueContainer()
try container.encode(url)
}
}
+4
View File
@@ -15,6 +15,10 @@
public protocol Meta: Codable, Equatable {
}
// We make Optional a Meta if it wraps a Meta so that Metadata can be specified as
// nullable.
extension Optional: Meta where Wrapped: Meta {}
public struct NoMetadata: Meta {
public static var none: NoMetadata { return NoMetadata() }
+70
View File
@@ -0,0 +1,70 @@
//
// LinksTests.swift
// JSONAPITests
//
// Created by Mathew Polzin on 11/24/18.
//
import XCTest
import JSONAPI
class LinksTests: XCTestCase {
func test_linkWithNoMeta() {
let links = decoded(type: LinksTests.Links.self, data: link_without_meta)
XCTAssertEqual(links.link.url, "https://website.com/path/file")
XCTAssertEqual(links.link.meta, NoMetadata())
}
func test_linkWithNoMeta_encode() {
test_DecodeEncodeEquality(type: LinksTests.Links.self, data: link_without_meta)
}
func test_linkWithNullMetadata() {
let link = decoded(type: Link<LinksTests.URL, Metadata?>.self, data: link_with_null_meta)
XCTAssertEqual(link.url, "https://website.com/path/file")
XCTAssertNil(link.meta)
}
func test_linkWithNullMetadata_encode() {
test_DecodeEncodeEquality(type: Link<LinksTests.URL, Metadata?>.self, data: link_with_null_meta)
}
func test_linkWithMetadata() {
let link = decoded(type: Link<LinksTests.URL, Metadata?>.self, data: link_with_metadata)
XCTAssertEqual(link.url, "https://website.com/path/file")
XCTAssertEqual(link.meta, Metadata(hello: "world"))
let link2 = decoded(type: Link<LinksTests.URL, Metadata>.self, data: link_with_metadata)
XCTAssertEqual(link2.url, "https://website.com/path/file")
XCTAssertEqual(link2.meta, Metadata(hello: "world"))
}
func test_linkWithMetadata_encode() {
test_DecodeEncodeEquality(type: Link<LinksTests.URL, Metadata?>.self, data: link_with_metadata)
test_DecodeEncodeEquality(type: Link<LinksTests.URL, Metadata>.self, data: link_with_metadata)
}
func test_linkFailsIfMetaNotFound() {
XCTAssertThrowsError(try JSONDecoder().decode(Link<LinksTests.URL, Metadata>.self, from: link_with_null_meta))
}
}
// MARK: - Test types
extension LinksTests {
typealias URL = String
struct Links: JSONAPI.Links {
let link: Link<LinksTests.URL, NoMetadata>
}
struct Metadata: JSONAPI.Meta {
let hello: String
}
}
extension String: JSONAPI.URL {}
@@ -0,0 +1,28 @@
//
// LinkStubs.swift
// JSONAPITests
//
// Created by Mathew Polzin on 11/24/18.
//
let link_without_meta = """
{
"link": "https://website.com/path/file"
}
""".data(using: .utf8)!
let link_with_null_meta = """
{
"href": "https://website.com/path/file",
"meta": null
}
""".data(using: .utf8)!
let link_with_metadata = """
{
"href": "https://website.com/path/file",
"meta": {
"hello": "world"
}
}
""".data(using: .utf8)!
+13
View File
@@ -100,6 +100,18 @@ extension IncludedTests {
]
}
extension LinksTests {
static let __allTests = [
("test_linkFailsIfMetaNotFound", test_linkFailsIfMetaNotFound),
("test_linkWithMetadata", test_linkWithMetadata),
("test_linkWithMetadata_encode", test_linkWithMetadata_encode),
("test_linkWithNoMeta", test_linkWithNoMeta),
("test_linkWithNoMeta_encode", test_linkWithNoMeta_encode),
("test_linkWithNullMetadata", test_linkWithNullMetadata),
("test_linkWithNullMetadata_encode", test_linkWithNullMetadata_encode),
]
}
extension PolyTests {
static let __allTests = [
("test_init_Poly0", test_init_Poly0),
@@ -156,6 +168,7 @@ public func __allTests() -> [XCTestCaseEntry] {
testCase(DocumentTests.__allTests),
testCase(EntityTests.__allTests),
testCase(IncludedTests.__allTests),
testCase(LinksTests.__allTests),
testCase(PolyTests.__allTests),
testCase(RelationshipTests.__allTests),
testCase(ResourceBodyTests.__allTests),