mirror of
https://github.com/encounter/JSONAPI.git
synced 2026-03-30 11:18:38 -07:00
Add Links and tests
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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() }
|
||||
|
||||
|
||||
@@ -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)!
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user